File size: 4,928 Bytes
6baed57 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
#include "unity/unity.h"
#include <libxml/HTMLparser.h>
#include <stdlib.h>
#include <string.h>
/* Forward declaration in case it's not exposed by the public header. */
int htmlAutoCloseTag(xmlDoc *doc, const xmlChar *name, xmlNode *elem);
static xmlDocPtr make_doc_with_root(const char *rootName, xmlNodePtr *outRoot) {
xmlDocPtr doc = xmlNewDoc((const xmlChar *)"1.0");
TEST_ASSERT_NOT_NULL_MESSAGE(doc, "xmlNewDoc failed");
xmlNodePtr root = xmlNewNode(NULL, (const xmlChar *)rootName);
TEST_ASSERT_NOT_NULL_MESSAGE(root, "xmlNewNode failed for root");
xmlDocSetRootElement(doc, root);
if (outRoot) *outRoot = root;
return doc;
}
void setUp(void) {
/* No global setup required */
}
void tearDown(void) {
/* No global teardown required */
}
/* elem == NULL => should return 1 */
void test_htmlAutoCloseTag_null_elem_returns_1(void) {
int ret = htmlAutoCloseTag(NULL, (const xmlChar *)"li", NULL);
TEST_ASSERT_EQUAL_INT(1, ret);
}
/* elem->name equals name => should return 0 */
void test_htmlAutoCloseTag_equal_name_returns_0(void) {
xmlNodePtr root = NULL;
xmlDocPtr doc = make_doc_with_root("p", &root);
int ret = htmlAutoCloseTag(doc, (const xmlChar *)"p", root);
TEST_ASSERT_EQUAL_INT(0, ret);
xmlFreeDoc(doc);
}
/* Direct auto-close: starting 'dt' should auto-close a preceding 'dd' */
void test_htmlAutoCloseTag_direct_autoclose_dd_by_dt_returns_1(void) {
xmlNodePtr root = NULL;
xmlDocPtr doc = make_doc_with_root("dd", &root);
int ret = htmlAutoCloseTag(doc, (const xmlChar *)"dt", root);
TEST_ASSERT_EQUAL_INT(1, ret);
xmlFreeDoc(doc);
}
/* No auto-close between unrelated tags: 'div' vs 'span' => 0 */
void test_htmlAutoCloseTag_no_autoclose_div_vs_span_returns_0(void) {
xmlNodePtr root = NULL;
xmlDocPtr doc = make_doc_with_root("div", &root);
int ret = htmlAutoCloseTag(doc, (const xmlChar *)"span", root);
TEST_ASSERT_EQUAL_INT(0, ret);
xmlFreeDoc(doc);
}
/* Descendant triggers auto-close: <div><dd/></div> with new tag 'dt' => 1 */
void test_htmlAutoCloseTag_descendant_dd_autoclosed_by_dt_returns_1(void) {
xmlNodePtr root = NULL;
xmlDocPtr doc = make_doc_with_root("div", &root);
xmlNodePtr child = xmlNewNode(NULL, (const xmlChar *)"dd");
TEST_ASSERT_NOT_NULL(child);
xmlAddChild(root, child);
int ret = htmlAutoCloseTag(doc, (const xmlChar *)"dt", root);
TEST_ASSERT_EQUAL_INT(1, ret);
xmlFreeDoc(doc);
}
/* Should iterate over children: first child no match, second child matches => 1 */
void test_htmlAutoCloseTag_sibling_second_child_matches_returns_1(void) {
xmlNodePtr root = NULL;
xmlDocPtr doc = make_doc_with_root("div", &root);
xmlNodePtr child1 = xmlNewNode(NULL, (const xmlChar *)"span"); /* no match */
xmlNodePtr child2 = xmlNewNode(NULL, (const xmlChar *)"dd"); /* dt will close */
TEST_ASSERT_NOT_NULL(child1);
TEST_ASSERT_NOT_NULL(child2);
xmlAddChild(root, child1);
xmlAddChild(root, child2);
int ret = htmlAutoCloseTag(doc, (const xmlChar *)"dt", root);
TEST_ASSERT_EQUAL_INT(1, ret);
xmlFreeDoc(doc);
}
/* Top-level equal name should short-circuit to 0 (even if children might match) */
void test_htmlAutoCloseTag_top_equal_name_short_circuits_returns_0(void) {
xmlNodePtr root = NULL;
xmlDocPtr doc = make_doc_with_root("p", &root);
/* Add a child that would be closed by 'dt' to ensure it's ignored due to top-level equal-name */
xmlNodePtr child = xmlNewNode(NULL, (const xmlChar *)"dd");
TEST_ASSERT_NOT_NULL(child);
xmlAddChild(root, child);
int ret = htmlAutoCloseTag(doc, (const xmlChar *)"p", root);
TEST_ASSERT_EQUAL_INT(0, ret);
xmlFreeDoc(doc);
}
/* No descendant matches: ensure returns 0 */
void test_htmlAutoCloseTag_no_descendant_match_returns_0(void) {
xmlNodePtr root = NULL;
xmlDocPtr doc = make_doc_with_root("div", &root);
xmlNodePtr c1 = xmlNewNode(NULL, (const xmlChar *)"span");
xmlNodePtr c2 = xmlNewNode(NULL, (const xmlChar *)"em");
TEST_ASSERT_NOT_NULL(c1);
TEST_ASSERT_NOT_NULL(c2);
xmlAddChild(root, c1);
xmlAddChild(root, c2);
int ret = htmlAutoCloseTag(doc, (const xmlChar *)"span", root);
TEST_ASSERT_EQUAL_INT(0, ret);
xmlFreeDoc(doc);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_htmlAutoCloseTag_null_elem_returns_1);
RUN_TEST(test_htmlAutoCloseTag_equal_name_returns_0);
RUN_TEST(test_htmlAutoCloseTag_direct_autoclose_dd_by_dt_returns_1);
RUN_TEST(test_htmlAutoCloseTag_no_autoclose_div_vs_span_returns_0);
RUN_TEST(test_htmlAutoCloseTag_descendant_dd_autoclosed_by_dt_returns_1);
RUN_TEST(test_htmlAutoCloseTag_sibling_second_child_matches_returns_1);
RUN_TEST(test_htmlAutoCloseTag_top_equal_name_short_circuits_returns_0);
RUN_TEST(test_htmlAutoCloseTag_no_descendant_match_returns_0);
return UNITY_END();
} |