| | #include "unity/unity.h" |
| | #include <libxml/HTMLparser.h> |
| | #include <libxml/parser.h> |
| | #include <libxml/tree.h> |
| | #include <libxml/xmlmemory.h> |
| |
|
| | #include <stdlib.h> |
| | #include <string.h> |
| |
|
| | |
| | extern void test_htmlParserFinishElementParsing(htmlParserCtxtPtr ctxt); |
| |
|
| | static htmlParserCtxtPtr |
| | create_ctxt_with_input(size_t base_len, size_t cur_offset, unsigned long consumed, unsigned long line, |
| | xmlParserInputPtr *outInput, xmlChar **outBase) { |
| | htmlParserCtxtPtr ctxt = htmlNewParserCtxt(); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(ctxt, "Failed to create HTML parser context"); |
| |
|
| | xmlParserInputPtr in = xmlNewInputStream(ctxt); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(in, "Failed to create new input stream"); |
| |
|
| | xmlChar *base = (xmlChar *)xmlMalloc(base_len); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(base, "Failed to allocate base buffer"); |
| | memset(base, 'A', base_len); |
| |
|
| | |
| | TEST_ASSERT_MESSAGE(cur_offset <= base_len, "cur_offset exceeds base buffer length"); |
| |
|
| | in->base = base; |
| | in->cur = base + cur_offset; |
| | in->end = base + base_len; |
| | in->consumed = consumed; |
| | in->line = line; |
| |
|
| | ctxt->input = in; |
| |
|
| | if (outInput) *outInput = in; |
| | if (outBase) *outBase = base; |
| |
|
| | return ctxt; |
| | } |
| |
|
| | static void |
| | destroy_ctxt_and_input(htmlParserCtxtPtr ctxt, xmlParserInputPtr in, xmlChar *base) { |
| | if (ctxt != NULL) { |
| | |
| | ctxt->input = NULL; |
| | } |
| | if (in != NULL) { |
| | |
| | in->base = NULL; |
| | in->cur = NULL; |
| | in->end = NULL; |
| | xmlFreeInputStream(in); |
| | } |
| | if (base != NULL) { |
| | xmlFree(base); |
| | } |
| | if (ctxt != NULL) { |
| | htmlFreeParserCtxt(ctxt); |
| | } |
| | } |
| |
|
| | void setUp(void) { |
| | xmlInitParser(); |
| | } |
| |
|
| | void tearDown(void) { |
| | xmlCleanupParser(); |
| | } |
| |
|
| | void test_htmlParserFinishElementParsing_records_end_info_basic(void) { |
| | xmlParserInputPtr in = NULL; |
| | xmlChar *base = NULL; |
| | |
| | htmlParserCtxtPtr ctxt = create_ctxt_with_input(32, 5, 2, 7, &in, &base); |
| |
|
| | |
| | xmlNodePtr node = xmlNewNode(NULL, (const xmlChar *)"test"); |
| | TEST_ASSERT_NOT_NULL(node); |
| | ctxt->node = node; |
| | ctxt->record_info = 1; |
| |
|
| | xmlParserNodeInfo *info = (xmlParserNodeInfo *)xmlMalloc(sizeof(xmlParserNodeInfo)); |
| | TEST_ASSERT_NOT_NULL(info); |
| | memset(info, 0, sizeof(*info)); |
| | ctxt->nodeInfo = info; |
| |
|
| | |
| | test_htmlParserFinishElementParsing(ctxt); |
| |
|
| | |
| | const xmlParserNodeInfo *found = xmlParserFindNodeInfo(ctxt, node); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(found, "xmlParserNodeInfo not found for node"); |
| | TEST_ASSERT_EQUAL_PTR(node, found->node); |
| | |
| | TEST_ASSERT_EQUAL_UINT(7u, (unsigned int)found->end_pos); |
| | TEST_ASSERT_EQUAL_UINT(7u, (unsigned int)found->end_line); |
| |
|
| | |
| | xmlFreeNode(node); |
| | |
| | |
| | destroy_ctxt_and_input(ctxt, in, base); |
| | } |
| |
|
| | void test_htmlParserFinishElementParsing_calculates_end_pos_with_consumed_offset(void) { |
| | xmlParserInputPtr in = NULL; |
| | xmlChar *base = NULL; |
| | |
| | htmlParserCtxtPtr ctxt = create_ctxt_with_input(64, 13, 21, 3, &in, &base); |
| |
|
| | xmlNodePtr node = xmlNewNode(NULL, (const xmlChar *)"elem"); |
| | TEST_ASSERT_NOT_NULL(node); |
| | ctxt->node = node; |
| | ctxt->record_info = 1; |
| |
|
| | xmlParserNodeInfo *info = (xmlParserNodeInfo *)xmlMalloc(sizeof(xmlParserNodeInfo)); |
| | TEST_ASSERT_NOT_NULL(info); |
| | memset(info, 0, sizeof(*info)); |
| | ctxt->nodeInfo = info; |
| |
|
| | test_htmlParserFinishElementParsing(ctxt); |
| |
|
| | const xmlParserNodeInfo *found = xmlParserFindNodeInfo(ctxt, node); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(found, "xmlParserNodeInfo not found for node"); |
| | TEST_ASSERT_EQUAL_PTR(node, found->node); |
| | |
| | TEST_ASSERT_EQUAL_UINT(34u, (unsigned int)found->end_pos); |
| | TEST_ASSERT_EQUAL_UINT(3u, (unsigned int)found->end_line); |
| |
|
| | xmlFreeNode(node); |
| | destroy_ctxt_and_input(ctxt, in, base); |
| | } |
| |
|
| | void test_htmlParserFinishElementParsing_noop_when_node_null(void) { |
| | xmlParserInputPtr in = NULL; |
| | xmlChar *base = NULL; |
| | htmlParserCtxtPtr ctxt = create_ctxt_with_input(16, 4, 9, 11, &in, &base); |
| |
|
| | |
| | ctxt->node = NULL; |
| | ctxt->record_info = 1; |
| |
|
| | |
| | xmlParserNodeInfo *info = (xmlParserNodeInfo *)xmlMalloc(sizeof(xmlParserNodeInfo)); |
| | TEST_ASSERT_NOT_NULL(info); |
| | memset(info, 0, sizeof(*info)); |
| | ctxt->nodeInfo = info; |
| |
|
| | test_htmlParserFinishElementParsing(ctxt); |
| |
|
| | |
| | xmlNodePtr node = xmlNewNode(NULL, (const xmlChar *)"unused"); |
| | TEST_ASSERT_NOT_NULL(node); |
| | const xmlParserNodeInfo *found = xmlParserFindNodeInfo(ctxt, node); |
| | TEST_ASSERT_NULL(found); |
| |
|
| | xmlFreeNode(node); |
| | |
| | destroy_ctxt_and_input(ctxt, in, base); |
| | } |
| |
|
| | void test_htmlParserFinishElementParsing_noop_when_record_info_false_even_with_node(void) { |
| | |
| | htmlParserCtxtPtr ctxt = htmlNewParserCtxt(); |
| | TEST_ASSERT_NOT_NULL(ctxt); |
| |
|
| | xmlNodePtr node = xmlNewNode(NULL, (const xmlChar *)"n"); |
| | TEST_ASSERT_NOT_NULL(node); |
| | ctxt->node = node; |
| | ctxt->record_info = 0; |
| | ctxt->input = NULL; |
| |
|
| | |
| | xmlParserNodeInfo *info = (xmlParserNodeInfo *)xmlMalloc(sizeof(xmlParserNodeInfo)); |
| | TEST_ASSERT_NOT_NULL(info); |
| | memset(info, 0, sizeof(*info)); |
| | ctxt->nodeInfo = info; |
| |
|
| | test_htmlParserFinishElementParsing(ctxt); |
| |
|
| | |
| | const xmlParserNodeInfo *found = xmlParserFindNodeInfo(ctxt, node); |
| | TEST_ASSERT_NULL(found); |
| |
|
| | xmlFreeNode(node); |
| | |
| | htmlFreeParserCtxt(ctxt); |
| | } |
| |
|
| | int main(void) { |
| | UNITY_BEGIN(); |
| | RUN_TEST(test_htmlParserFinishElementParsing_records_end_info_basic); |
| | RUN_TEST(test_htmlParserFinishElementParsing_calculates_end_pos_with_consumed_offset); |
| | RUN_TEST(test_htmlParserFinishElementParsing_noop_when_node_null); |
| | RUN_TEST(test_htmlParserFinishElementParsing_noop_when_record_info_false_even_with_node); |
| | return UNITY_END(); |
| | } |