File size: 6,075 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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#include "unity/unity.h"
#include <libxml/HTMLparser.h>

#include <stdlib.h>
#include <string.h>

/* Wrapper for the static function under test (provided in the module) */
void test_htmlParseComment(htmlParserCtxtPtr ctxt, int bogus);

/* Capture structure for SAX comment callback */
typedef struct {
    int count;
    char *last;
} CommentCapture;

static void free_capture(CommentCapture *cap) {
    if (cap->last) {
        free(cap->last);
        cap->last = NULL;
    }
    cap->count = 0;
}

static void comment_cb(void *ctx, const xmlChar *value) {
    CommentCapture *cap = (CommentCapture *)ctx;
    cap->count++;
    /* Copy the comment text into an owned buffer (ASCII-safe) */
    const char *val = (const char *)value;
    size_t n = strlen(val);
    free_capture(cap);
    cap->last = (char *)malloc(n + 1);
    if (cap->last) {
        memcpy(cap->last, val, n + 1);
    }
}

/* Helper to create a parser context with given input buffer */
static htmlParserCtxtPtr make_ctxt(const char *data) {
    if (data == NULL) data = "";
    int len = (int)strlen(data);
    htmlParserCtxtPtr ctxt = htmlCreateMemoryParserCtxt(data, len);
    return ctxt;
}

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

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

/* Bogus comment: content is read until '>', which is then skipped */
void test_htmlParseComment_bogus_basic(void) {
    CommentCapture cap = {0, NULL};
    htmlParserCtxtPtr ctxt = make_ctxt("hello>");
    TEST_ASSERT_NOT_NULL(ctxt);

    xmlSAXHandler sax;
    memset(&sax, 0, sizeof(sax));
    sax.comment = comment_cb;

    ctxt->sax = &sax;
    ctxt->userData = &cap;
    ctxt->disableSAX = 0;

    test_htmlParseComment(ctxt, 1);

    TEST_ASSERT_EQUAL_INT(1, cap.count);
    TEST_ASSERT_NOT_NULL(cap.last);
    TEST_ASSERT_EQUAL_STRING("hello", cap.last);

    free_capture(&cap);
    htmlFreeParserCtxt(ctxt);
}

/* Bogus comment without closing '>' should still emit collected content */
void test_htmlParseComment_bogus_no_terminator(void) {
    CommentCapture cap = {0, NULL};
    htmlParserCtxtPtr ctxt = make_ctxt("noend");
    TEST_ASSERT_NOT_NULL(ctxt);

    xmlSAXHandler sax;
    memset(&sax, 0, sizeof(sax));
    sax.comment = comment_cb;

    ctxt->sax = &sax;
    ctxt->userData = &cap;
    ctxt->disableSAX = 0;

    test_htmlParseComment(ctxt, 1);

    TEST_ASSERT_EQUAL_INT(1, cap.count);
    TEST_ASSERT_NOT_NULL(cap.last);
    TEST_ASSERT_EQUAL_STRING("noend", cap.last);

    free_capture(&cap);
    htmlFreeParserCtxt(ctxt);
}

/* Non-bogus: immediate '>' produces an empty comment */
void test_htmlParseComment_nonbogus_immediate_gt(void) {
    CommentCapture cap = {0, NULL};
    htmlParserCtxtPtr ctxt = make_ctxt(">");
    TEST_ASSERT_NOT_NULL(ctxt);

    xmlSAXHandler sax;
    memset(&sax, 0, sizeof(sax));
    sax.comment = comment_cb;

    ctxt->sax = &sax;
    ctxt->userData = &cap;
    ctxt->disableSAX = 0;

    test_htmlParseComment(ctxt, 0);

    TEST_ASSERT_EQUAL_INT(1, cap.count);
    TEST_ASSERT_NOT_NULL(cap.last);
    TEST_ASSERT_EQUAL_STRING("", cap.last);

    free_capture(&cap);
    htmlFreeParserCtxt(ctxt);
}

/* Non-bogus: immediate "->" also produces an empty comment */
void test_htmlParseComment_nonbogus_immediate_arrow(void) {
    CommentCapture cap = {0, NULL};
    htmlParserCtxtPtr ctxt = make_ctxt("->");
    TEST_ASSERT_NOT_NULL(ctxt);

    xmlSAXHandler sax;
    memset(&sax, 0, sizeof(sax));
    sax.comment = comment_cb;

    ctxt->sax = &sax;
    ctxt->userData = &cap;
    ctxt->disableSAX = 0;

    test_htmlParseComment(ctxt, 0);

    TEST_ASSERT_EQUAL_INT(1, cap.count);
    TEST_ASSERT_NOT_NULL(cap.last);
    TEST_ASSERT_EQUAL_STRING("", cap.last);

    free_capture(&cap);
    htmlFreeParserCtxt(ctxt);
}

/* Non-bogus: parse data until '-' is encountered; expect content before '-' */
void test_htmlParseComment_nonbogus_until_dash(void) {
    CommentCapture cap = {0, NULL};
    htmlParserCtxtPtr ctxt = make_ctxt("abc-def->");
    TEST_ASSERT_NOT_NULL(ctxt);

    xmlSAXHandler sax;
    memset(&sax, 0, sizeof(sax));
    sax.comment = comment_cb;

    ctxt->sax = &sax;
    ctxt->userData = &cap;
    ctxt->disableSAX = 0;

    test_htmlParseComment(ctxt, 0);

    TEST_ASSERT_EQUAL_INT(1, cap.count);
    TEST_ASSERT_NOT_NULL(cap.last);
    TEST_ASSERT_EQUAL_STRING("abc", cap.last);

    free_capture(&cap);
    htmlFreeParserCtxt(ctxt);
}

/* Ensure no callback is emitted when SAX is disabled */
void test_htmlParseComment_SAX_disabled(void) {
    CommentCapture cap = {0, NULL};
    htmlParserCtxtPtr ctxt = make_ctxt("ignored>");
    TEST_ASSERT_NOT_NULL(ctxt);

    xmlSAXHandler sax;
    memset(&sax, 0, sizeof(sax));
    sax.comment = comment_cb;

    ctxt->sax = &sax;
    ctxt->userData = &cap;
    ctxt->disableSAX = 1; /* Disable SAX */

    test_htmlParseComment(ctxt, 1);

    TEST_ASSERT_EQUAL_INT(0, cap.count);
    TEST_ASSERT_NULL(cap.last);

    free_capture(&cap);
    htmlFreeParserCtxt(ctxt);
}

/* Ensure safe behavior when ctxt->sax is NULL */
void test_htmlParseComment_null_sax(void) {
    CommentCapture cap = {0, NULL};
    htmlParserCtxtPtr ctxt = make_ctxt("hello>");
    TEST_ASSERT_NOT_NULL(ctxt);

    ctxt->sax = NULL;          /* No SAX handler */
    ctxt->userData = &cap;
    ctxt->disableSAX = 0;

    test_htmlParseComment(ctxt, 1);

    TEST_ASSERT_EQUAL_INT(0, cap.count);
    TEST_ASSERT_NULL(cap.last);

    free_capture(&cap);
    htmlFreeParserCtxt(ctxt);
}

int main(void) {
    /* Initialize libxml2 parser library */
    xmlInitParser();

    UNITY_BEGIN();

    RUN_TEST(test_htmlParseComment_bogus_basic);
    RUN_TEST(test_htmlParseComment_bogus_no_terminator);
    RUN_TEST(test_htmlParseComment_nonbogus_immediate_gt);
    RUN_TEST(test_htmlParseComment_nonbogus_immediate_arrow);
    RUN_TEST(test_htmlParseComment_nonbogus_until_dash);
    RUN_TEST(test_htmlParseComment_SAX_disabled);
    RUN_TEST(test_htmlParseComment_null_sax);

    int rc = UNITY_END();

    /* Cleanup libxml2 global state */
    xmlCleanupParser();

    return rc;
}