File size: 4,914 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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "unity/unity.h"
#include <libxml/HTMLparser.h>

#include <libxml/tree.h>
#include <libxml/parser.h>
#include <stdlib.h>
#include <string.h>

/* Unity fixtures */
void setUp(void) {
    /* Setup code here, or leave empty */
}

void tearDown(void) {
    /* Cleanup code here, or leave empty */
}

/* Helper to build a document with a root element of given name */
static xmlDocPtr make_doc_with_root(const char *root_name, xmlNodePtr *out_root) {
    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
    TEST_ASSERT_NOT_NULL_MESSAGE(doc, "Failed to create xmlDoc");

    xmlNodePtr root = xmlNewNode(NULL, BAD_CAST root_name);
    TEST_ASSERT_NOT_NULL_MESSAGE(root, "Failed to create root node");

    xmlDocSetRootElement(doc, root);
    if (out_root) *out_root = root;
    return doc;
}

void test_htmlIsAutoClosed_null_elem_with_null_doc(void) {
    int res = htmlIsAutoClosed(NULL, NULL);
    TEST_ASSERT_EQUAL_INT(1, res);
}

void test_htmlIsAutoClosed_null_elem_with_real_doc(void) {
    xmlNodePtr root = NULL;
    xmlDocPtr doc = make_doc_with_root("p", &root);

    int res = htmlIsAutoClosed(doc, NULL);
    TEST_ASSERT_EQUAL_INT(1, res);

    xmlFreeDoc(doc);
}

void test_htmlIsAutoClosed_no_children_returns_0(void) {
    xmlNodePtr root = NULL;
    xmlDocPtr doc = make_doc_with_root("p", &root);

    int res = htmlIsAutoClosed(doc, root);
    TEST_ASSERT_EQUAL_INT(0, res);

    xmlFreeDoc(doc);
}

void test_htmlIsAutoClosed_immediate_same_name_child_ignored_returns_0(void) {
    xmlNodePtr root = NULL;
    xmlDocPtr doc = make_doc_with_root("p", &root);

    /* Immediate child with same name as parent */
    xmlNodePtr child = xmlNewChild(root, NULL, BAD_CAST "p", NULL);
    TEST_ASSERT_NOT_NULL(child);

    int res = htmlIsAutoClosed(doc, root);
    TEST_ASSERT_EQUAL_INT(0, res);

    xmlFreeDoc(doc);
}

void test_htmlIsAutoClosed_child_non_trigger_returns_0(void) {
    xmlNodePtr root = NULL;
    xmlDocPtr doc = make_doc_with_root("p", &root);

    /* span does not auto-close p */
    xmlNodePtr child = xmlNewChild(root, NULL, BAD_CAST "span", NULL);
    TEST_ASSERT_NOT_NULL(child);

    int res = htmlIsAutoClosed(doc, root);
    TEST_ASSERT_EQUAL_INT(0, res);

    xmlFreeDoc(doc);
}

void test_htmlIsAutoClosed_child_triggers_autoclose_returns_1(void) {
    xmlNodePtr root = NULL;
    xmlDocPtr doc = make_doc_with_root("p", &root);

    /* div should auto-close p according to HTML rules */
    xmlNodePtr child = xmlNewChild(root, NULL, BAD_CAST "div", NULL);
    TEST_ASSERT_NOT_NULL(child);

    int res = htmlIsAutoClosed(doc, root);
    TEST_ASSERT_EQUAL_INT(1, res);

    xmlFreeDoc(doc);
}

void test_htmlIsAutoClosed_descendant_triggers_autoclose_returns_1(void) {
    xmlNodePtr root = NULL;
    xmlDocPtr doc = make_doc_with_root("p", &root);

    /* Non-trigger child with a trigger descendant: span > div */
    xmlNodePtr span = xmlNewChild(root, NULL, BAD_CAST "span", NULL);
    TEST_ASSERT_NOT_NULL(span);
    xmlNodePtr div = xmlNewChild(span, NULL, BAD_CAST "div", NULL);
    TEST_ASSERT_NOT_NULL(div);

    int res = htmlIsAutoClosed(doc, root);
    TEST_ASSERT_EQUAL_INT(1, res);

    xmlFreeDoc(doc);
}

void test_htmlIsAutoClosed_multiple_children_only_one_triggers_returns_1(void) {
    xmlNodePtr root = NULL;
    xmlDocPtr doc = make_doc_with_root("p", &root);

    xmlNodePtr c1 = xmlNewChild(root, NULL, BAD_CAST "span", NULL);
    xmlNodePtr c2 = xmlNewChild(root, NULL, BAD_CAST "em", NULL);
    xmlNodePtr c3 = xmlNewChild(root, NULL, BAD_CAST "div", NULL); /* trigger */
    TEST_ASSERT_NOT_NULL(c1);
    TEST_ASSERT_NOT_NULL(c2);
    TEST_ASSERT_NOT_NULL(c3);

    int res = htmlIsAutoClosed(doc, root);
    TEST_ASSERT_EQUAL_INT(1, res);

    xmlFreeDoc(doc);
}

void test_htmlIsAutoClosed_null_doc_parameter_works_with_valid_tree(void) {
    xmlNodePtr root = NULL;
    xmlDocPtr doc = make_doc_with_root("p", &root);

    /* Attach a trigger child but pass NULL as doc */
    xmlNodePtr div = xmlNewChild(root, NULL, BAD_CAST "div", NULL);
    TEST_ASSERT_NOT_NULL(div);

    int res = htmlIsAutoClosed(NULL, root);
    TEST_ASSERT_EQUAL_INT(1, res);

    xmlFreeDoc(doc);
}

int main(void) {
    xmlInitParser();

    UNITY_BEGIN();
    RUN_TEST(test_htmlIsAutoClosed_null_elem_with_null_doc);
    RUN_TEST(test_htmlIsAutoClosed_null_elem_with_real_doc);
    RUN_TEST(test_htmlIsAutoClosed_no_children_returns_0);
    RUN_TEST(test_htmlIsAutoClosed_immediate_same_name_child_ignored_returns_0);
    RUN_TEST(test_htmlIsAutoClosed_child_non_trigger_returns_0);
    RUN_TEST(test_htmlIsAutoClosed_child_triggers_autoclose_returns_1);
    RUN_TEST(test_htmlIsAutoClosed_descendant_triggers_autoclose_returns_1);
    RUN_TEST(test_htmlIsAutoClosed_multiple_children_only_one_triggers_returns_1);
    RUN_TEST(test_htmlIsAutoClosed_null_doc_parameter_works_with_valid_tree);
    int ret = UNITY_END();

    xmlCleanupParser();
    return ret;
}