#include "unity/unity.h" #include #include #include #include #include #include #include /* Internal libxml buffer API used by the function under test */ #include "private/buf.h" /* Wrapper for the static function under test (declared in the module) */ extern size_t test_htmlBufNodeDumpFormat(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int format); static xmlBufPtr make_buf(void) { xmlBufPtr buf = xmlBufCreate(); TEST_ASSERT_NOT_NULL_MESSAGE(buf, "Failed to create xmlBuf"); return buf; } static void assert_buf_equals(xmlBufPtr buf, const char *expected) { size_t expected_len = strlen(expected); const xmlChar *content = xmlBufContent(buf); size_t used = xmlBufUse(buf); TEST_ASSERT_EQUAL_UINT64((uint64_t)expected_len, (uint64_t)used); TEST_ASSERT_NOT_NULL(content); TEST_ASSERT_EQUAL_INT(0, memcmp((const char *)content, expected, expected_len)); } void setUp(void) { /* Ensure parser is initialized for any libxml operations */ xmlInitParser(); } void tearDown(void) { /* Cleanup global state after each test */ xmlCleanupParser(); } /* Error handling tests */ void test_htmlBufNodeDumpFormat_null_cur_returns_minus_one(void) { xmlBufPtr buf = make_buf(); size_t ret = test_htmlBufNodeDumpFormat(buf, NULL, NULL, 0); TEST_ASSERT_EQUAL_UINT64((uint64_t)(size_t)-1, (uint64_t)ret); xmlBufFree(buf); } void test_htmlBufNodeDumpFormat_null_buf_returns_minus_one(void) { xmlNodePtr node = xmlNewNode(NULL, BAD_CAST "div"); TEST_ASSERT_NOT_NULL(node); size_t ret = test_htmlBufNodeDumpFormat(NULL, NULL, node, 0); TEST_ASSERT_EQUAL_UINT64((uint64_t)(size_t)-1, (uint64_t)ret); xmlFreeNode(node); } /* Basic serialization tests */ void test_htmlBufNodeDumpFormat_empty_html_empty_elem_br(void) { xmlBufPtr buf = make_buf(); xmlNodePtr node = xmlNewNode(NULL, BAD_CAST "br"); TEST_ASSERT_NOT_NULL(node); size_t ret = test_htmlBufNodeDumpFormat(buf, NULL, node, 0); const char *expected = "
"; TEST_ASSERT_EQUAL_UINT64((uint64_t)strlen(expected), (uint64_t)ret); assert_buf_equals(buf, expected); xmlFreeNode(node); xmlBufFree(buf); } void test_htmlBufNodeDumpFormat_non_empty_without_children_div(void) { xmlBufPtr buf = make_buf(); xmlNodePtr node = xmlNewNode(NULL, BAD_CAST "div"); TEST_ASSERT_NOT_NULL(node); size_t ret = test_htmlBufNodeDumpFormat(buf, NULL, node, 0); const char *expected = "
"; TEST_ASSERT_EQUAL_UINT64((uint64_t)strlen(expected), (uint64_t)ret); assert_buf_equals(buf, expected); xmlFreeNode(node); xmlBufFree(buf); } void test_htmlBufNodeDumpFormat_text_child_with_escaping(void) { xmlBufPtr buf = make_buf(); xmlNodePtr node = xmlNewNode(NULL, BAD_CAST "div"); TEST_ASSERT_NOT_NULL(node); xmlNodePtr text = xmlNewText(BAD_CAST "5 < 6 & 7"); TEST_ASSERT_NOT_NULL(text); xmlAddChild(node, text); size_t ret = test_htmlBufNodeDumpFormat(buf, NULL, node, 0); const char *expected = "
5 < 6 & 7
"; TEST_ASSERT_EQUAL_UINT64((uint64_t)strlen(expected), (uint64_t)ret); assert_buf_equals(buf, expected); xmlFreeNode(node); /* Frees children as well */ xmlBufFree(buf); } void test_htmlBufNodeDumpFormat_namespace_prefix_and_declaration(void) { xmlBufPtr buf = make_buf(); xmlNodePtr node = xmlNewNode(NULL, BAD_CAST "span"); TEST_ASSERT_NOT_NULL(node); /* Declare and set namespace prefix x with href "urn:test" */ xmlNsPtr ns = xmlNewNs(node, BAD_CAST "urn:test", BAD_CAST "x"); TEST_ASSERT_NOT_NULL(ns); xmlSetNs(node, ns); size_t ret = test_htmlBufNodeDumpFormat(buf, NULL, node, 0); const char *expected = ""; TEST_ASSERT_EQUAL_UINT64((uint64_t)strlen(expected), (uint64_t)ret); assert_buf_equals(buf, expected); xmlFreeNode(node); xmlBufFree(buf); } void test_htmlBufNodeDumpFormat_multiple_calls_append_and_return_increment(void) { xmlBufPtr buf = make_buf(); xmlNodePtr node = xmlNewNode(NULL, BAD_CAST "div"); TEST_ASSERT_NOT_NULL(node); const char *once = "
"; size_t ret1 = test_htmlBufNodeDumpFormat(buf, NULL, node, 0); TEST_ASSERT_EQUAL_UINT64((uint64_t)strlen(once), (uint64_t)ret1); assert_buf_equals(buf, once); size_t before = xmlBufUse(buf); size_t ret2 = test_htmlBufNodeDumpFormat(buf, NULL, node, 0); TEST_ASSERT_EQUAL_UINT64((uint64_t)strlen(once), (uint64_t)ret2); size_t after = xmlBufUse(buf); TEST_ASSERT_EQUAL_UINT64((uint64_t)(before + strlen(once)), (uint64_t)after); const xmlChar *content = xmlBufContent(buf); TEST_ASSERT_NOT_NULL(content); TEST_ASSERT_EQUAL_INT(0, memcmp((const char *)content, once, strlen(once))); TEST_ASSERT_EQUAL_INT(0, memcmp((const char *)content + strlen(once), once, strlen(once))); xmlFreeNode(node); xmlBufFree(buf); } void test_htmlBufNodeDumpFormat_formatting_newlines_with_block_children(void) { xmlBufPtr buf = make_buf(); /* Build:
12
to trigger newlines with format=1 */ xmlNodePtr div = xmlNewNode(NULL, BAD_CAST "div"); TEST_ASSERT_NOT_NULL(div); xmlNodePtr span1 = xmlNewNode(NULL, BAD_CAST "span"); xmlAddChild(span1, xmlNewText(BAD_CAST "1")); xmlAddChild(div, span1); xmlNodePtr span2 = xmlNewNode(NULL, BAD_CAST "span"); xmlAddChild(span2, xmlNewText(BAD_CAST "2")); xmlAddChild(div, span2); size_t ret = test_htmlBufNodeDumpFormat(buf, NULL, div, 1); /* Expected behavior: newline after opening div and before closing div */ const char *expected = "
\n12\n
"; TEST_ASSERT_EQUAL_UINT64((uint64_t)strlen(expected), (uint64_t)ret); assert_buf_equals(buf, expected); xmlFreeNode(div); xmlBufFree(buf); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_htmlBufNodeDumpFormat_null_cur_returns_minus_one); RUN_TEST(test_htmlBufNodeDumpFormat_null_buf_returns_minus_one); RUN_TEST(test_htmlBufNodeDumpFormat_empty_html_empty_elem_br); RUN_TEST(test_htmlBufNodeDumpFormat_non_empty_without_children_div); RUN_TEST(test_htmlBufNodeDumpFormat_text_child_with_escaping); RUN_TEST(test_htmlBufNodeDumpFormat_namespace_prefix_and_declaration); RUN_TEST(test_htmlBufNodeDumpFormat_multiple_calls_append_and_return_increment); RUN_TEST(test_htmlBufNodeDumpFormat_formatting_newlines_with_block_children); return UNITY_END(); }