| | #include "unity/unity.h" |
| | #include <libxml/HTMLtree.h> |
| |
|
| | #include <libxml/tree.h> |
| | #include <stdio.h> |
| | #include <stdlib.h> |
| | #include <string.h> |
| |
|
| | |
| | void setUp(void) { |
| | |
| | } |
| |
|
| | void tearDown(void) { |
| | |
| | } |
| |
|
| | |
| | |
| | static int create_temp_file(char *outPath, size_t outPathSize, FILE **outF) { |
| | if (outPath == NULL || outF == NULL || outPathSize == 0) |
| | return 0; |
| |
|
| | |
| | char tmpbuf[L_tmpnam]; |
| | #if defined(_MSC_VER) |
| | if (tmpnam_s(tmpbuf, L_tmpnam) != 0) |
| | return 0; |
| | #else |
| | if (tmpnam(tmpbuf) == NULL) |
| | return 0; |
| | #endif |
| | |
| | strncpy(outPath, tmpbuf, outPathSize - 1); |
| | outPath[outPathSize - 1] = '\0'; |
| |
|
| | FILE *f = fopen(outPath, "wb"); |
| | if (f == NULL) |
| | return 0; |
| |
|
| | *outF = f; |
| | return 1; |
| | } |
| |
|
| | |
| | |
| | static char *read_file_to_string(const char *path, long *length) { |
| | if (path == NULL) |
| | return NULL; |
| |
|
| | FILE *f = fopen(path, "rb"); |
| | if (f == NULL) |
| | return NULL; |
| |
|
| | if (fseek(f, 0, SEEK_END) != 0) { |
| | fclose(f); |
| | return NULL; |
| | } |
| | long size = ftell(f); |
| | if (size < 0) { |
| | fclose(f); |
| | return NULL; |
| | } |
| | rewind(f); |
| |
|
| | char *buf = (char *)malloc((size_t)size + 1); |
| | if (buf == NULL) { |
| | fclose(f); |
| | return NULL; |
| | } |
| |
|
| | size_t nread = fread(buf, 1, (size_t)size, f); |
| | fclose(f); |
| | buf[nread] = '\0'; |
| | if (length) |
| | *length = (long)nread; |
| | return buf; |
| | } |
| |
|
| | |
| | static xmlDocPtr build_simple_html_doc(void) { |
| | xmlDocPtr doc = htmlNewDocNoDtD(NULL, NULL); |
| | if (doc == NULL) |
| | return NULL; |
| |
|
| | xmlNodePtr root = htmlNewDocNode(doc, NULL, BAD_CAST "html", NULL); |
| | if (root == NULL) { |
| | xmlFreeDoc(doc); |
| | return NULL; |
| | } |
| | xmlDocSetRootElement(doc, root); |
| |
|
| | xmlNodePtr body = htmlNewDocNode(doc, NULL, BAD_CAST "body", NULL); |
| | if (body == NULL) { |
| | xmlFreeDoc(doc); |
| | return NULL; |
| | } |
| | xmlAddChild(root, body); |
| |
|
| | xmlNodePtr p = htmlNewDocNode(doc, NULL, BAD_CAST "p", NULL); |
| | if (p == NULL) { |
| | xmlFreeDoc(doc); |
| | return NULL; |
| | } |
| | xmlAddChild(body, p); |
| |
|
| | xmlNodePtr text = xmlNewText(BAD_CAST "Hello"); |
| | if (text == NULL) { |
| | xmlFreeDoc(doc); |
| | return NULL; |
| | } |
| | xmlAddChild(p, text); |
| |
|
| | return doc; |
| | } |
| |
|
| | |
| | static void test_htmlDocDump_null_doc_returns_minus1(void) { |
| | char path[256]; |
| | FILE *f = NULL; |
| | TEST_ASSERT_TRUE_MESSAGE(create_temp_file(path, sizeof(path), &f), "Failed to create temp file"); |
| |
|
| | int ret = htmlDocDump(f, NULL); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(-1, ret, "htmlDocDump should return -1 for NULL doc"); |
| |
|
| | |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(0, fflush(f), "Flushing file failed"); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(0, fclose(f), "Closing file failed"); |
| |
|
| | |
| | long size = 0; |
| | char *contents = read_file_to_string(path, &size); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(contents, "Failed to read temp file"); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(0, (int)size, "File should be empty when doc is NULL"); |
| | free(contents); |
| | remove(path); |
| | } |
| |
|
| | |
| | static void test_htmlDocDump_null_file_returns_minus1(void) { |
| | xmlDocPtr doc = build_simple_html_doc(); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(doc, "Failed to build HTML doc"); |
| |
|
| | int ret = htmlDocDump(NULL, doc); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(-1, ret, "htmlDocDump should return -1 for NULL file"); |
| |
|
| | xmlFreeDoc(doc); |
| | } |
| |
|
| | |
| | static void test_htmlDocDump_invalid_encoding_returns_minus1_and_no_write(void) { |
| | xmlDocPtr doc = build_simple_html_doc(); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(doc, "Failed to build HTML doc"); |
| |
|
| | |
| | doc->encoding = xmlStrdup(BAD_CAST "x-unknown-encoding-xyz-1234"); |
| |
|
| | char path[256]; |
| | FILE *f = NULL; |
| | TEST_ASSERT_TRUE_MESSAGE(create_temp_file(path, sizeof(path), &f), "Failed to create temp file"); |
| |
|
| | int ret = htmlDocDump(f, doc); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(-1, ret, "htmlDocDump should return -1 for unsupported encoding"); |
| |
|
| | |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(0, fflush(f), "Flushing file failed"); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(0, fclose(f), "Closing file failed"); |
| |
|
| | long size = -1; |
| | char *contents = read_file_to_string(path, &size); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(contents, "Failed to read temp file"); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE(0, (int)size, "File should be empty on encoder failure"); |
| | free(contents); |
| | remove(path); |
| |
|
| | xmlFreeDoc(doc); |
| | } |
| |
|
| | |
| | static void test_htmlDocDump_writes_content_with_default_encoding(void) { |
| | xmlDocPtr doc = build_simple_html_doc(); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(doc, "Failed to build HTML doc"); |
| |
|
| | |
| | doc->encoding = NULL; |
| |
|
| | char path[256]; |
| | FILE *f = NULL; |
| | TEST_ASSERT_TRUE_MESSAGE(create_temp_file(path, sizeof(path), &f), "Failed to create temp file"); |
| |
|
| | int ret = htmlDocDump(f, doc); |
| | TEST_ASSERT_MESSAGE(ret >= 0, "htmlDocDump should succeed (ret >= 0) with default encoding"); |
| |
|
| | |
| |
|
| | long size = -1; |
| | char *contents = read_file_to_string(path, &size); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(contents, "Failed to read dumped file"); |
| | TEST_ASSERT_MESSAGE(size > 0, "Dumped file should contain data"); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(strstr(contents, "Hello"), "Dumped HTML should contain text 'Hello'"); |
| | |
| | TEST_ASSERT_NOT_NULL_MESSAGE(strstr(contents, "<html"), "Dumped HTML should contain <html> element"); |
| |
|
| | free(contents); |
| | remove(path); |
| | xmlFreeDoc(doc); |
| | } |
| |
|
| | |
| | static void test_htmlDocDump_writes_content_with_utf8_encoding(void) { |
| | xmlDocPtr doc = build_simple_html_doc(); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(doc, "Failed to build HTML doc"); |
| |
|
| | |
| | doc->encoding = xmlStrdup(BAD_CAST "UTF-8"); |
| |
|
| | char path[256]; |
| | FILE *f = NULL; |
| | TEST_ASSERT_TRUE_MESSAGE(create_temp_file(path, sizeof(path), &f), "Failed to create temp file"); |
| |
|
| | int ret = htmlDocDump(f, doc); |
| | TEST_ASSERT_MESSAGE(ret >= 0, "htmlDocDump should succeed (ret >= 0) with UTF-8 encoding"); |
| |
|
| | long size = -1; |
| | char *contents = read_file_to_string(path, &size); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(contents, "Failed to read dumped file"); |
| | TEST_ASSERT_MESSAGE(size > 0, "Dumped file should contain data"); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(strstr(contents, "Hello"), "Dumped HTML should contain text 'Hello'"); |
| |
|
| | free(contents); |
| | remove(path); |
| | xmlFreeDoc(doc); |
| | } |
| |
|
| | |
| | int main(void) { |
| | UNITY_BEGIN(); |
| | RUN_TEST(test_htmlDocDump_null_doc_returns_minus1); |
| | RUN_TEST(test_htmlDocDump_null_file_returns_minus1); |
| | RUN_TEST(test_htmlDocDump_invalid_encoding_returns_minus1_and_no_write); |
| | RUN_TEST(test_htmlDocDump_writes_content_with_default_encoding); |
| | RUN_TEST(test_htmlDocDump_writes_content_with_utf8_encoding); |
| | return UNITY_END(); |
| | } |