|
|
#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(); |
|
|
} |