libxml / tests /tests_HTMLparser_htmlParseElementInternal.c
AryaWu's picture
Upload folder using huggingface_hub
6baed57 verified
#include "unity/unity.h"
#include <libxml/HTMLparser.h>
#include <string.h>
#include <stdlib.h>
/* Use public prototypes only; wrapper provided in module */
extern int test_htmlParseElementInternal(htmlParserCtxtPtr ctxt);
typedef struct {
int startCount;
int endCount;
char lastStart[64];
char lastEnd[64];
} TestSaxCounters;
static void sax_start(void *ctx, const xmlChar *name, const xmlChar **atts) {
(void)atts;
TestSaxCounters *c = (TestSaxCounters *)ctx;
c->startCount++;
if (name != NULL) {
strncpy(c->lastStart, (const char *)name, sizeof(c->lastStart) - 1);
c->lastStart[sizeof(c->lastStart) - 1] = '\0';
}
}
static void sax_end(void *ctx, const xmlChar *name) {
TestSaxCounters *c = (TestSaxCounters *)ctx;
c->endCount++;
if (name != NULL) {
strncpy(c->lastEnd, (const char *)name, sizeof(c->lastEnd) - 1);
c->lastEnd[sizeof(c->lastEnd) - 1] = '\0';
}
}
static htmlParserCtxtPtr make_ctxt_with_input(const char *input,
int use_html5,
xmlSAXHandler *sax,
void *user) {
htmlParserCtxtPtr ctxt = htmlCreatePushParserCtxt(sax, user,
input,
(int)strlen(input),
NULL,
XML_CHAR_ENCODING_NONE);
TEST_ASSERT_NOT_NULL_MESSAGE(ctxt, "Failed to create HTML push parser context");
if (use_html5) {
ctxt->options |= HTML_PARSE_HTML5;
}
return ctxt;
}
void setUp(void) {
xmlInitParser();
}
void tearDown(void) {
/* No global cleanup here; libxml cleanup is handled externally if needed */
}
/* Tests */
void test_htmlParseElementInternal_null_context_returns_0(void) {
int ret = test_htmlParseElementInternal(NULL);
TEST_ASSERT_EQUAL_INT(0, ret);
}
void test_htmlParseElementInternal_null_input_returns_0(void) {
htmlParserCtxtPtr ctxt = htmlNewParserCtxt();
TEST_ASSERT_NOT_NULL(ctxt);
/* Ensure input is NULL */
TEST_ASSERT_NULL(ctxt->input);
int ret = test_htmlParseElementInternal(ctxt);
TEST_ASSERT_EQUAL_INT(0, ret);
htmlFreeParserCtxt(ctxt);
}
void test_htmlParseElementInternal_nonempty_tag_returns_1_and_callbacks(void) {
const char *src = "<div>";
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.startElement = sax_start;
sax.endElement = sax_end;
TestSaxCounters counters = {0};
htmlParserCtxtPtr ctxt = make_ctxt_with_input(src, 0, &sax, &counters);
int ret = test_htmlParseElementInternal(ctxt);
TEST_ASSERT_EQUAL_INT(1, ret);
TEST_ASSERT_EQUAL_INT(1, counters.startCount);
TEST_ASSERT_EQUAL_INT(0, counters.endCount);
TEST_ASSERT_EQUAL_STRING("div", counters.lastStart);
/* Name should remain as current element since not empty */
TEST_ASSERT_NOT_NULL(ctxt->name);
TEST_ASSERT_TRUE(xmlStrEqual(ctxt->name, BAD_CAST "div"));
htmlFreeParserCtxt(ctxt);
}
void test_htmlParseElementInternal_self_closing_non_html5_calls_endElement_and_returns_0(void) {
const char *src = "<input/>";
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.startElement = sax_start;
sax.endElement = sax_end;
TestSaxCounters counters = {0};
htmlParserCtxtPtr ctxt = make_ctxt_with_input(src, 0, &sax, &counters);
int ret = test_htmlParseElementInternal(ctxt);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_INT(1, counters.startCount);
TEST_ASSERT_EQUAL_INT(1, counters.endCount);
TEST_ASSERT_EQUAL_STRING("input", counters.lastStart);
TEST_ASSERT_EQUAL_STRING("input", counters.lastEnd);
htmlFreeParserCtxt(ctxt);
}
void test_htmlParseElementInternal_self_closing_html5_does_not_call_endElement_returns_0(void) {
const char *src = "<input/>";
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.startElement = sax_start;
sax.endElement = sax_end;
TestSaxCounters counters = {0};
htmlParserCtxtPtr ctxt = make_ctxt_with_input(src, 1, &sax, &counters);
int ret = test_htmlParseElementInternal(ctxt);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_INT(1, counters.startCount);
TEST_ASSERT_EQUAL_INT(0, counters.endCount);
TEST_ASSERT_EQUAL_STRING("input", counters.lastStart);
htmlFreeParserCtxt(ctxt);
}
void test_htmlParseElementInternal_dtd_empty_without_solidus_returns_0_and_calls_end(void) {
const char *src = "<br>";
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.startElement = sax_start;
sax.endElement = sax_end;
TestSaxCounters counters = {0};
htmlParserCtxtPtr ctxt = make_ctxt_with_input(src, 0, &sax, &counters);
int ret = test_htmlParseElementInternal(ctxt);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_INT(1, counters.startCount);
TEST_ASSERT_EQUAL_INT(1, counters.endCount);
TEST_ASSERT_EQUAL_STRING("br", counters.lastStart);
TEST_ASSERT_EQUAL_STRING("br", counters.lastEnd);
htmlFreeParserCtxt(ctxt);
}
void test_htmlParseElementInternal_missing_gt_returns_0_and_no_callbacks(void) {
const char *src = "<div";
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.startElement = sax_start;
sax.endElement = sax_end;
TestSaxCounters counters = {0};
htmlParserCtxtPtr ctxt = make_ctxt_with_input(src, 0, &sax, &counters);
int ret = test_htmlParseElementInternal(ctxt);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_INT(0, counters.startCount);
TEST_ASSERT_EQUAL_INT(0, counters.endCount);
htmlFreeParserCtxt(ctxt);
}
void test_htmlParseElementInternal_unknown_tag_keeps_endCheckState_zero_returns_1(void) {
const char *src = "<custom>";
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.startElement = sax_start;
sax.endElement = sax_end;
TestSaxCounters counters = {0};
htmlParserCtxtPtr ctxt = make_ctxt_with_input(src, 0, &sax, &counters);
TEST_ASSERT_EQUAL_INT(0, ctxt->endCheckState);
int ret = test_htmlParseElementInternal(ctxt);
TEST_ASSERT_EQUAL_INT(1, ret);
TEST_ASSERT_EQUAL_INT(1, counters.startCount);
TEST_ASSERT_EQUAL_INT(0, counters.endCount);
TEST_ASSERT_EQUAL_INT(0, ctxt->endCheckState); /* remains unchanged */
htmlFreeParserCtxt(ctxt);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_htmlParseElementInternal_null_context_returns_0);
RUN_TEST(test_htmlParseElementInternal_null_input_returns_0);
RUN_TEST(test_htmlParseElementInternal_nonempty_tag_returns_1_and_callbacks);
RUN_TEST(test_htmlParseElementInternal_self_closing_non_html5_calls_endElement_and_returns_0);
RUN_TEST(test_htmlParseElementInternal_self_closing_html5_does_not_call_endElement_returns_0);
RUN_TEST(test_htmlParseElementInternal_dtd_empty_without_solidus_returns_0_and_calls_end);
RUN_TEST(test_htmlParseElementInternal_missing_gt_returns_0_and_no_callbacks);
RUN_TEST(test_htmlParseElementInternal_unknown_tag_keeps_endCheckState_zero_returns_1);
return UNITY_END();
}