|
|
#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> |
|
|
|
|
|
|
|
|
int test_htmlInitParserCtxt(htmlParserCtxtPtr ctxt, const htmlSAXHandler *sax, void *userData); |
|
|
|
|
|
|
|
|
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; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
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) { |
|
|
|
|
|
xmlInitParser(); |
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
xmlCleanupParser(); |
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlInitParserCtxt_null_context_returns_error(void) { |
|
|
int rc = test_htmlInitParserCtxt(NULL, NULL, NULL); |
|
|
TEST_ASSERT_EQUAL_INT(-1, rc); |
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlInitParserCtxt_init_with_default_sax(void) { |
|
|
htmlParserCtxt ctxt; |
|
|
|
|
|
int dummy = 123; |
|
|
int rc = test_htmlInitParserCtxt(&ctxt, NULL, &dummy); |
|
|
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); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(0, ctxt.inputNr); |
|
|
TEST_ASSERT_EQUAL_INT(1, ctxt.inputMax); |
|
|
TEST_ASSERT_NULL(ctxt.input); |
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(&ctxt, ctxt.vctxt.userData); |
|
|
TEST_ASSERT_NOT_NULL(ctxt.vctxt.error); |
|
|
TEST_ASSERT_NOT_NULL(ctxt.vctxt.warning); |
|
|
|
|
|
|
|
|
TEST_ASSERT_NOT_NULL(ctxt.sax); |
|
|
TEST_ASSERT_TRUE(((htmlSAXHandler *)ctxt.sax)->initialized != 0); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(&ctxt, ctxt.userData); |
|
|
|
|
|
cleanup_ctxt_allocs(&ctxt); |
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlInitParserCtxt_init_with_custom_sax_and_userData(void) { |
|
|
htmlParserCtxt ctxt; |
|
|
htmlSAXHandler customSax; |
|
|
memset(&customSax, 0, sizeof(customSax)); |
|
|
customSax.initialized = 0x1234; |
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(0, memcmp(ctxt.sax, &customSax, sizeof(customSax))); |
|
|
|
|
|
|
|
|
TEST_ASSERT_EQUAL_PTR(ud, ctxt.userData); |
|
|
|
|
|
|
|
|
TEST_ASSERT_TRUE(ctxt.nodeMax == 1 || ctxt.nodeMax == 10); |
|
|
TEST_ASSERT_TRUE(ctxt.nameMax == 1 || ctxt.nameMax == 10); |
|
|
|
|
|
cleanup_ctxt_allocs(&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); |
|
|
} |
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
} |
|
|
|
|
|
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(); |
|
|
} |