File size: 4,884 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
#include "unity/unity.h"
#include <libxml/HTMLparser.h>

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

/* Wrapper for the static function under test (provided in the module) */
void test_htmlSkipBogusDoctype(htmlParserCtxtPtr ctxt);

static htmlParserCtxtPtr make_ctxt_from_str(const char *s) {
    /* Use memory-based context so we control input content precisely */
    return htmlCreateMemoryParserCtxt(s, (int)strlen(s));
}

void setUp(void) {
    /* No global setup required */
}

void tearDown(void) {
    /* No global teardown required */
}

/* Basic case: single-line input with immediate '>' */
void test_htmlSkipBogusDoctype_basic(void) {
    const char *buf = "bogus>";
    htmlParserCtxtPtr ctxt = make_ctxt_from_str(buf);
    TEST_ASSERT_NOT_NULL(ctxt);
    TEST_ASSERT_NOT_NULL(ctxt->input);

    /* Start at known position */
    ctxt->input->line = 1;
    ctxt->input->col = 1;

    test_htmlSkipBogusDoctype(ctxt);

    /* Expect cursor right after '>' */
    int offset = (int)(ctxt->input->cur - ctxt->input->base);
    TEST_ASSERT_EQUAL_INT(6, offset); /* "bogus>" is 6 chars */
    /* No newlines, so line unchanged; col counts characters processed including '>' */
    TEST_ASSERT_EQUAL_INT(1, ctxt->input->line);
    TEST_ASSERT_EQUAL_INT(7, ctxt->input->col); /* initial 1 + 6 chars processed */

    htmlFreeParserCtxt(ctxt);
}

/* Newline handling: ensure line increments and col resets to 1 after '\n' */
void test_htmlSkipBogusDoctype_with_newlines(void) {
    const char *buf = "ab\ncd>";
    htmlParserCtxtPtr ctxt = make_ctxt_from_str(buf);
    TEST_ASSERT_NOT_NULL(ctxt);
    TEST_ASSERT_NOT_NULL(ctxt->input);

    ctxt->input->line = 1;
    ctxt->input->col = 1;

    test_htmlSkipBogusDoctype(ctxt);

    int offset = (int)(ctxt->input->cur - ctxt->input->base);
    TEST_ASSERT_EQUAL_INT(6, offset); /* processed entire string up to and including '>' */

    /* One newline encountered: line increments by 1 */
    TEST_ASSERT_EQUAL_INT(2, ctxt->input->line);

    /* Col progression:
       'a' -> 2, 'b' -> 3, '\n' -> (inc to 4 then reset to 1), 'c' -> 2, 'd' -> 3, '>' -> 4
     */
    TEST_ASSERT_EQUAL_INT(4, ctxt->input->col);

    htmlFreeParserCtxt(ctxt);
}

/* No closing '>' => should advance to end-of-buffer with correct line/col */
void test_htmlSkipBogusDoctype_no_gt_reaches_eof(void) {
    const char *buf = "no gt present";
    const int len = (int)strlen(buf);
    htmlParserCtxtPtr ctxt = make_ctxt_from_str(buf);
    TEST_ASSERT_NOT_NULL(ctxt);
    TEST_ASSERT_NOT_NULL(ctxt->input);

    ctxt->input->line = 5;
    ctxt->input->col = 10;

    test_htmlSkipBogusDoctype(ctxt);

    /* Cursor at end */
    int offset = (int)(ctxt->input->cur - ctxt->input->base);
    TEST_ASSERT_EQUAL_INT(len, offset);

    /* No newlines in input; col increments by total characters processed */
    TEST_ASSERT_EQUAL_INT(5, ctxt->input->line);
    TEST_ASSERT_EQUAL_INT(10 + len, ctxt->input->col);

    htmlFreeParserCtxt(ctxt);
}

/* Zero available input at entry (cur == end) => no changes */
void test_htmlSkipBogusDoctype_zero_avail_noop(void) {
    const char *buf = ">";
    htmlParserCtxtPtr ctxt = make_ctxt_from_str(buf);
    TEST_ASSERT_NOT_NULL(ctxt);
    TEST_ASSERT_NOT_NULL(ctxt->input);

    /* Move to end so avail == 0 */
    ctxt->input->cur = ctxt->input->end;
    ctxt->input->line = 3;
    ctxt->input->col = 7;

    test_htmlSkipBogusDoctype(ctxt);

    /* Expect unchanged */
    TEST_ASSERT_TRUE(ctxt->input->cur == ctxt->input->end);
    TEST_ASSERT_EQUAL_INT(3, ctxt->input->line);
    TEST_ASSERT_EQUAL_INT(7, ctxt->input->col);

    htmlFreeParserCtxt(ctxt);
}

/* Long input to ensure scanning works when avail is large (>64) */
void test_htmlSkipBogusDoctype_long_input(void) {
    /* Create 200 'x' characters followed by '>' */
    const int xcount = 200;
    const int total = xcount + 1;
    char *buf = (char *)malloc((size_t)total + 1);
    TEST_ASSERT_NOT_NULL(buf);
    memset(buf, 'x', (size_t)xcount);
    buf[xcount] = '>';
    buf[total] = '\0';

    htmlParserCtxtPtr ctxt = make_ctxt_from_str(buf);
    TEST_ASSERT_NOT_NULL(ctxt);
    TEST_ASSERT_NOT_NULL(ctxt->input);

    ctxt->input->line = 1;
    ctxt->input->col = 1;

    test_htmlSkipBogusDoctype(ctxt);

    int offset = (int)(ctxt->input->cur - ctxt->input->base);
    TEST_ASSERT_EQUAL_INT(total, offset);    /* advanced past '>' */
    TEST_ASSERT_EQUAL_INT(1, ctxt->input->line);
    TEST_ASSERT_EQUAL_INT(1 + total, ctxt->input->col);

    htmlFreeParserCtxt(ctxt);
    free(buf);
}

int main(void) {
    UNITY_BEGIN();

    RUN_TEST(test_htmlSkipBogusDoctype_basic);
    RUN_TEST(test_htmlSkipBogusDoctype_with_newlines);
    RUN_TEST(test_htmlSkipBogusDoctype_no_gt_reaches_eof);
    RUN_TEST(test_htmlSkipBogusDoctype_zero_avail_noop);
    RUN_TEST(test_htmlSkipBogusDoctype_long_input);

    return UNITY_END();
}