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