| #include "unity/unity.h" |
| #include <libxml/HTMLparser.h> |
| #include <libxml/xmlmemory.h> |
|
|
| #include <string.h> |
| #include <stdlib.h> |
|
|
| |
| extern int test_htmlSkipBlankChars(xmlParserCtxtPtr ctxt); |
|
|
| void setUp(void) { |
| |
| xmlInitParser(); |
| } |
|
|
| void tearDown(void) { |
| |
| } |
|
|
| |
| static void create_ctxt_with_content(const char *content, |
| int init_line, int init_col, |
| xmlParserCtxtPtr *out_ctxt, |
| xmlParserInputPtr *out_input, |
| xmlChar **out_buf, |
| int *out_len) { |
| TEST_ASSERT_NOT_NULL_MESSAGE(out_ctxt, "out_ctxt must not be NULL"); |
| TEST_ASSERT_NOT_NULL_MESSAGE(out_input, "out_input must not be NULL"); |
| TEST_ASSERT_NOT_NULL_MESSAGE(out_buf, "out_buf must not be NULL"); |
|
|
| int len = (content != NULL) ? (int)strlen(content) : 0; |
| xmlChar *buf = (xmlChar *)xmlMalloc((size_t)len + 1); |
| TEST_ASSERT_NOT_NULL_MESSAGE(buf, "Failed to allocate buffer"); |
| if (len > 0 && content != NULL) { |
| memcpy(buf, content, (size_t)len); |
| } |
| buf[len] = 0; |
|
|
| htmlParserCtxtPtr hctxt = htmlNewParserCtxt(); |
| TEST_ASSERT_NOT_NULL_MESSAGE(hctxt, "Failed to create parser context"); |
|
|
| xmlParserInputPtr input = (xmlParserInputPtr)xmlMalloc(sizeof(*input)); |
| TEST_ASSERT_NOT_NULL_MESSAGE(input, "Failed to allocate parser input"); |
| memset(input, 0, sizeof(*input)); |
| input->base = buf; |
| input->cur = buf; |
| input->end = buf + len; |
| input->line = init_line; |
| input->col = init_col; |
|
|
| hctxt->input = input; |
|
|
| *out_ctxt = (xmlParserCtxtPtr)hctxt; |
| *out_input = input; |
| *out_buf = buf; |
| if (out_len) |
| *out_len = len; |
| } |
|
|
| static void destroy_ctxt_with_content(xmlParserCtxtPtr ctxt, |
| xmlParserInputPtr input, |
| xmlChar *buf) { |
| if (ctxt != NULL) { |
| |
| ctxt->input = NULL; |
| htmlFreeParserCtxt((htmlParserCtxtPtr)ctxt); |
| } |
| if (input != NULL) |
| xmlFree(input); |
| if (buf != NULL) |
| xmlFree(buf); |
| } |
|
|
| |
| void test_htmlSkipBlankChars_only_spaces(void) { |
| xmlParserCtxtPtr ctxt = NULL; |
| xmlParserInputPtr input = NULL; |
| xmlChar *buf = NULL; |
|
|
| create_ctxt_with_content(" abc", 3, 5, &ctxt, &input, &buf, NULL); |
|
|
| int ret = test_htmlSkipBlankChars(ctxt); |
|
|
| TEST_ASSERT_EQUAL_INT(4, ret); |
| TEST_ASSERT_EQUAL_INT(3, input->line); |
| TEST_ASSERT_EQUAL_INT(9, input->col); |
| TEST_ASSERT_EQUAL_CHAR('a', (char)*(input->cur)); |
|
|
| destroy_ctxt_with_content(ctxt, input, buf); |
| } |
|
|
| |
| void test_htmlSkipBlankChars_newlines_and_spaces(void) { |
| xmlParserCtxtPtr ctxt = NULL; |
| xmlParserInputPtr input = NULL; |
| xmlChar *buf = NULL; |
|
|
| |
| create_ctxt_with_content("\n \n\tX", 1, 1, &ctxt, &input, &buf, NULL); |
|
|
| int ret = test_htmlSkipBlankChars(ctxt); |
|
|
| TEST_ASSERT_EQUAL_INT(4, ret); |
| TEST_ASSERT_EQUAL_INT(3, input->line); |
| TEST_ASSERT_EQUAL_INT(2, input->col); |
| TEST_ASSERT_EQUAL_CHAR('X', (char)*(input->cur)); |
|
|
| destroy_ctxt_with_content(ctxt, input, buf); |
| } |
|
|
| |
| void test_htmlSkipBlankChars_stops_on_non_ws(void) { |
| xmlParserCtxtPtr ctxt = NULL; |
| xmlParserInputPtr input = NULL; |
| xmlChar *buf = NULL; |
|
|
| create_ctxt_with_content(" \t\rA B", 1, 1, &ctxt, &input, &buf, NULL); |
|
|
| int ret = test_htmlSkipBlankChars(ctxt); |
|
|
| TEST_ASSERT_EQUAL_INT(3, ret); |
| TEST_ASSERT_EQUAL_INT(1, input->line); |
| TEST_ASSERT_EQUAL_INT(4, input->col); |
| TEST_ASSERT_EQUAL_CHAR('A', (char)*(input->cur)); |
|
|
| destroy_ctxt_with_content(ctxt, input, buf); |
| } |
|
|
| |
| void test_htmlSkipBlankChars_zero_avail(void) { |
| xmlParserCtxtPtr ctxt = NULL; |
| xmlParserInputPtr input = NULL; |
| xmlChar *buf = NULL; |
|
|
| create_ctxt_with_content("", 10, 7, &ctxt, &input, &buf, NULL); |
|
|
| int ret = test_htmlSkipBlankChars(ctxt); |
|
|
| TEST_ASSERT_EQUAL_INT(0, ret); |
| TEST_ASSERT_EQUAL_INT(10, input->line); |
| TEST_ASSERT_EQUAL_INT(7, input->col); |
| TEST_ASSERT_TRUE(input->cur == input->end); |
|
|
| destroy_ctxt_with_content(ctxt, input, buf); |
| } |
|
|
| |
| void test_htmlSkipBlankChars_parser_stopped(void) { |
| xmlParserCtxtPtr ctxt = NULL; |
| xmlParserInputPtr input = NULL; |
| xmlChar *buf = NULL; |
|
|
| create_ctxt_with_content(" \n\tabc", 2, 3, &ctxt, &input, &buf, NULL); |
|
|
| |
| ctxt->instate = XML_PARSER_EOF; |
|
|
| int ret = test_htmlSkipBlankChars(ctxt); |
|
|
| TEST_ASSERT_EQUAL_INT(0, ret); |
| TEST_ASSERT_EQUAL_INT(2, input->line); |
| TEST_ASSERT_EQUAL_INT(3, input->col); |
| TEST_ASSERT_TRUE(input->cur == input->base); |
|
|
| destroy_ctxt_with_content(ctxt, input, buf); |
| } |
|
|
| |
| void test_htmlSkipBlankChars_large_whitespace(void) { |
| char tmp[102 + 1]; |
| memset(tmp, ' ', 100); |
| tmp[100] = 'Z'; |
| tmp[101] = '\0'; |
|
|
| xmlParserCtxtPtr ctxt = NULL; |
| xmlParserInputPtr input = NULL; |
| xmlChar *buf = NULL; |
|
|
| create_ctxt_with_content(tmp, 1, 1, &ctxt, &input, &buf, NULL); |
|
|
| int ret = test_htmlSkipBlankChars(ctxt); |
|
|
| TEST_ASSERT_EQUAL_INT(100, ret); |
| TEST_ASSERT_EQUAL_INT(1, input->line); |
| TEST_ASSERT_EQUAL_INT(101, input->col); |
| TEST_ASSERT_EQUAL_CHAR('Z', (char)*(input->cur)); |
|
|
| destroy_ctxt_with_content(ctxt, input, buf); |
| } |
|
|
| int main(void) { |
| UNITY_BEGIN(); |
| RUN_TEST(test_htmlSkipBlankChars_only_spaces); |
| RUN_TEST(test_htmlSkipBlankChars_newlines_and_spaces); |
| RUN_TEST(test_htmlSkipBlankChars_stops_on_non_ws); |
| RUN_TEST(test_htmlSkipBlankChars_zero_avail); |
| RUN_TEST(test_htmlSkipBlankChars_parser_stopped); |
| RUN_TEST(test_htmlSkipBlankChars_large_whitespace); |
| return UNITY_END(); |
| } |