libxml / tests /tests_HTMLparser_htmlInitParserCtxt.c
AryaWu's picture
Upload folder using huggingface_hub
6baed57 verified
#include "unity/unity.h"
#include <libxml/HTMLparser.h>
#include <libxml/parser.h>
#include <libxml/xmlmemory.h>
#include <libxml/dict.h>
#include <string.h>
#include <stdlib.h>
/* Wrapper prototype provided by the source module for the static function */
int test_htmlInitParserCtxt(htmlParserCtxtPtr ctxt, const htmlSAXHandler *sax, void *userData);
/* Helpers for cleanup of allocations performed by htmlInitParserCtxt */
static void cleanup_ctxt_allocs(htmlParserCtxt *ctxt) {
if (ctxt == NULL) return;
if (ctxt->sax) {
xmlFree((void *)ctxt->sax);
ctxt->sax = NULL;
}
if (ctxt->inputTab) {
xmlFree((void *)ctxt->inputTab);
ctxt->inputTab = NULL;
ctxt->inputMax = 0;
ctxt->inputNr = 0;
}
if (ctxt->nodeTab) {
xmlFree((void *)ctxt->nodeTab);
ctxt->nodeTab = NULL;
ctxt->nodeMax = 0;
ctxt->nodeNr = 0;
}
if (ctxt->nameTab) {
xmlFree((void *)ctxt->nameTab);
ctxt->nameTab = NULL;
ctxt->nameMax = 0;
ctxt->nameNr = 0;
}
if (ctxt->dict) {
xmlDictFree(ctxt->dict);
ctxt->dict = NULL;
}
}
/* Memory hook machinery to simulate allocation failure */
static int g_fail_alloc_enable = 0;
static int g_fail_alloc_always = 0;
static int g_alloc_call_count = 0;
static void myXmlFree(void *ptr) {
free(ptr);
}
static void *myXmlMalloc(size_t size) {
if (g_fail_alloc_enable && (g_fail_alloc_always || (g_alloc_call_count++ == 0))) {
return NULL;
}
return malloc(size);
}
static void *myXmlRealloc(void *ptr, size_t size) {
if (g_fail_alloc_enable && g_fail_alloc_always) {
return NULL;
}
return realloc(ptr, size);
}
static char *myXmlStrdup(const char *str) {
if (g_fail_alloc_enable && g_fail_alloc_always) {
return NULL;
}
size_t len = strlen(str) + 1;
char *p = (char *)malloc(len);
if (p) memcpy(p, str, len);
return p;
}
static xmlFreeFunc oldFreeF = NULL;
static xmlMallocFunc oldMallocF = NULL;
static xmlReallocFunc oldReallocF = NULL;
static xmlStrdupFunc oldStrdupF = NULL;
static void enable_alloc_failure_always(void) {
xmlMemGet(&oldFreeF, &oldMallocF, &oldReallocF, &oldStrdupF);
g_fail_alloc_enable = 1;
g_fail_alloc_always = 1;
g_alloc_call_count = 0;
xmlMemSetup(myXmlFree, myXmlMalloc, myXmlRealloc, myXmlStrdup);
}
static void restore_alloc_functions(void) {
xmlMemSetup(oldFreeF, oldMallocF, oldReallocF, oldStrdupF);
g_fail_alloc_enable = 0;
g_fail_alloc_always = 0;
g_alloc_call_count = 0;
}
void setUp(void) {
/* Ensure libxml is initialized */
xmlInitParser();
}
void tearDown(void) {
/* Cleanup global parser state (safe between tests) */
xmlCleanupParser();
}
/* Test: NULL context should return error (-1) */
void test_htmlInitParserCtxt_null_context_returns_error(void) {
int rc = test_htmlInitParserCtxt(NULL, NULL, NULL);
TEST_ASSERT_EQUAL_INT(-1, rc);
}
/* Test: Initialize with default SAX (sax == NULL); userData must be ctxt; key fields set */
void test_htmlInitParserCtxt_init_with_default_sax(void) {
htmlParserCtxt ctxt;
/* Pass non-NULL userData to ensure it's ignored when sax == NULL */
int dummy = 123;
int rc = test_htmlInitParserCtxt(&ctxt, NULL, &dummy);
TEST_ASSERT_EQUAL_INT(0, rc);
/* Basic allocations */
TEST_ASSERT_NOT_NULL(ctxt.dict);
TEST_ASSERT_NOT_NULL(ctxt.sax);
TEST_ASSERT_NOT_NULL(ctxt.inputTab);
TEST_ASSERT_NOT_NULL(ctxt.nodeTab);
TEST_ASSERT_NOT_NULL(ctxt.nameTab);
/* Input stack state */
TEST_ASSERT_EQUAL_INT(0, ctxt.inputNr);
TEST_ASSERT_EQUAL_INT(1, ctxt.inputMax);
TEST_ASSERT_NULL(ctxt.input);
/* Node and name stacks */
TEST_ASSERT_EQUAL_INT(0, ctxt.nodeNr);
TEST_ASSERT_TRUE(ctxt.nodeMax == 1 || ctxt.nodeMax == 10);
TEST_ASSERT_NULL(ctxt.node);
TEST_ASSERT_EQUAL_INT(0, ctxt.nameNr);
TEST_ASSERT_TRUE(ctxt.nameMax == 1 || ctxt.nameMax == 10);
TEST_ASSERT_NULL(ctxt.name);
/* Document and flags */
TEST_ASSERT_NULL(ctxt.myDoc);
TEST_ASSERT_EQUAL_INT(1, ctxt.wellFormed);
TEST_ASSERT_EQUAL_INT(0, ctxt.replaceEntities);
TEST_ASSERT_EQUAL_INT(xmlKeepBlanksDefaultValue, ctxt.keepBlanks);
TEST_ASSERT_EQUAL_INT(0, ctxt.validate);
TEST_ASSERT_EQUAL_INT(0, ctxt.checkIndex);
TEST_ASSERT_EQUAL_INT(0, ctxt.record_info);
TEST_ASSERT_EQUAL_INT(-1, ctxt.standalone);
/* vctxt sanity */
TEST_ASSERT_EQUAL_PTR(&ctxt, ctxt.vctxt.userData);
TEST_ASSERT_NOT_NULL(ctxt.vctxt.error);
TEST_ASSERT_NOT_NULL(ctxt.vctxt.warning);
/* Default SAX handler should be initialized */
TEST_ASSERT_NOT_NULL(ctxt.sax);
TEST_ASSERT_TRUE(((htmlSAXHandler *)ctxt.sax)->initialized != 0);
/* userData must be ctxt when sax == NULL */
TEST_ASSERT_EQUAL_PTR(&ctxt, ctxt.userData);
cleanup_ctxt_allocs(&ctxt);
}
/* Test: Initialize with custom SAX handler and explicit userData */
void test_htmlInitParserCtxt_init_with_custom_sax_and_userData(void) {
htmlParserCtxt ctxt;
htmlSAXHandler customSax;
memset(&customSax, 0, sizeof(customSax));
customSax.initialized = 0x1234; /* marker */
int userToken = 42;
void *ud = &userToken;
int rc = test_htmlInitParserCtxt(&ctxt, &customSax, ud);
TEST_ASSERT_EQUAL_INT(0, rc);
TEST_ASSERT_NOT_NULL(ctxt.dict);
TEST_ASSERT_NOT_NULL(ctxt.sax);
TEST_ASSERT_NOT_NULL(ctxt.inputTab);
TEST_ASSERT_NOT_NULL(ctxt.nodeTab);
TEST_ASSERT_NOT_NULL(ctxt.nameTab);
/* Copied SAX handler must be byte-wise identical */
TEST_ASSERT_EQUAL_INT(0, memcmp(ctxt.sax, &customSax, sizeof(customSax)));
/* userData should equal the provided pointer when sax != NULL */
TEST_ASSERT_EQUAL_PTR(ud, ctxt.userData);
/* Stack sizes sane */
TEST_ASSERT_TRUE(ctxt.nodeMax == 1 || ctxt.nodeMax == 10);
TEST_ASSERT_TRUE(ctxt.nameMax == 1 || ctxt.nameMax == 10);
cleanup_ctxt_allocs(&ctxt);
}
/* Test: Initialize with custom SAX handler and NULL userData: userData must default to ctxt */
void test_htmlInitParserCtxt_init_with_custom_sax_null_userData_defaults_to_ctxt(void) {
htmlParserCtxt ctxt;
htmlSAXHandler customSax;
memset(&customSax, 0, sizeof(customSax));
customSax.initialized = 777;
int rc = test_htmlInitParserCtxt(&ctxt, &customSax, NULL);
TEST_ASSERT_EQUAL_INT(0, rc);
TEST_ASSERT_NOT_NULL(ctxt.sax);
TEST_ASSERT_EQUAL_INT(0, memcmp(ctxt.sax, &customSax, sizeof(customSax)));
TEST_ASSERT_EQUAL_PTR(&ctxt, ctxt.userData);
cleanup_ctxt_allocs(&ctxt);
}
/* Test: Allocation failure path returns error (-1) */
void test_htmlInitParserCtxt_allocation_failure_returns_error(void) {
enable_alloc_failure_always();
htmlParserCtxt ctxt;
int rc = test_htmlInitParserCtxt(&ctxt, NULL, NULL);
restore_alloc_functions();
TEST_ASSERT_EQUAL_INT(-1, rc);
/* Nothing to clean up; initialization failed before allocations were assigned */
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_htmlInitParserCtxt_null_context_returns_error);
RUN_TEST(test_htmlInitParserCtxt_init_with_default_sax);
RUN_TEST(test_htmlInitParserCtxt_init_with_custom_sax_and_userData);
RUN_TEST(test_htmlInitParserCtxt_init_with_custom_sax_null_userData_defaults_to_ctxt);
RUN_TEST(test_htmlInitParserCtxt_allocation_failure_returns_error);
return UNITY_END();
}