| | #include "unity/unity.h" |
| | #include <libxml/HTMLparser.h> |
| | #include <libxml/parser.h> |
| | #include <string.h> |
| | #include <stdlib.h> |
| | #include <stdio.h> |
| |
|
| | void setUp(void) { |
| | xmlInitParser(); |
| | } |
| | void tearDown(void) { |
| | xmlCleanupParser(); |
| | } |
| |
|
| | |
| | |
| | static void assert_output_equals(const unsigned char *out, int outlen, const char *expected) { |
| | size_t explen = strlen(expected); |
| | TEST_ASSERT_EQUAL_UINT32_MESSAGE((uint32_t)explen, (uint32_t)outlen, "Output length mismatch"); |
| | char *tmp = (char *)malloc(outlen + 1); |
| | TEST_ASSERT_NOT_NULL(tmp); |
| | memcpy(tmp, out, outlen); |
| | tmp[outlen] = '\0'; |
| | TEST_ASSERT_EQUAL_STRING(expected, tmp); |
| | free(tmp); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_null_args(void) { |
| | unsigned char outbuf[32]; |
| | int outlen = (int)sizeof(outbuf); |
| | const unsigned char inbuf[] = "test"; |
| | int inlen = 4; |
| | int rc; |
| |
|
| | rc = htmlEncodeEntities(NULL, &outlen, inbuf, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(-1, rc); |
| |
|
| | outlen = (int)sizeof(outbuf); inlen = 4; |
| | rc = htmlEncodeEntities(outbuf, NULL, inbuf, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(-1, rc); |
| |
|
| | outlen = (int)sizeof(outbuf); inlen = 4; |
| | rc = htmlEncodeEntities(outbuf, &outlen, NULL, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(-1, rc); |
| |
|
| | outlen = (int)sizeof(outbuf); inlen = 4; |
| | rc = htmlEncodeEntities(outbuf, &outlen, inbuf, NULL, 0); |
| | TEST_ASSERT_EQUAL_INT(-1, rc); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_ascii_passthrough(void) { |
| | const char *in = "Hello world!"; |
| | int inlen = (int)strlen(in); |
| | unsigned char outbuf[128]; |
| | int outlen = (int)sizeof(outbuf); |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, (const unsigned char*)in, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| | TEST_ASSERT_EQUAL_INT((int)strlen(in), outlen); |
| | TEST_ASSERT_EQUAL_INT((int)strlen(in), inlen); |
| | assert_output_equals(outbuf, outlen, in); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_special_ascii_entities(void) { |
| | const char *in = "&<>"; |
| | int inlen = (int)strlen(in); |
| | unsigned char outbuf[64]; |
| | int outlen = (int)sizeof(outbuf); |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, (const unsigned char*)in, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| | assert_output_equals(outbuf, outlen, "&<>"); |
| | TEST_ASSERT_EQUAL_INT(3, inlen); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_double_quote_encoded(void) { |
| | const char inbytes[] = {'\'', '\"'}; |
| | int inlen = 2; |
| | unsigned char outbuf[64]; |
| | int outlen = (int)sizeof(outbuf); |
| | int rc = htmlEncodeEntities(outbuf, &outlen, (const unsigned char*)inbytes, &inlen, '\"'); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| | assert_output_equals(outbuf, outlen, "'""); |
| | TEST_ASSERT_EQUAL_INT(2, inlen); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_single_quote_encoded(void) { |
| | const char inbytes[] = {'\''}; |
| | int inlen = 1; |
| | unsigned char outbuf[64]; |
| | int outlen = (int)sizeof(outbuf); |
| | int rc = htmlEncodeEntities(outbuf, &outlen, (const unsigned char*)inbytes, &inlen, '\''); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| |
|
| | |
| | char tmp[64]; |
| | memcpy(tmp, outbuf, outlen); |
| | tmp[outlen] = '\0'; |
| |
|
| | |
| | int is_apos = (strcmp(tmp, "'") == 0); |
| | int is_num = (strcmp(tmp, "'") == 0); |
| | TEST_ASSERT_TRUE_MESSAGE(is_apos || is_num, "Expected ' or ' for single quote"); |
| | TEST_ASSERT_EQUAL_INT(1, inlen); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_named_entity_copyright(void) { |
| | const unsigned char inbytes[] = {0xC2, 0xA9}; |
| | int inlen = 2; |
| | unsigned char outbuf[64]; |
| | int outlen = (int)sizeof(outbuf); |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, inbytes, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| | assert_output_equals(outbuf, outlen, "©"); |
| | TEST_ASSERT_EQUAL_INT(2, inlen); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_numeric_entity_smiley(void) { |
| | const unsigned char inbytes[] = {0xF0, 0x9F, 0x99, 0x82}; |
| | int inlen = 4; |
| | unsigned char outbuf[64]; |
| | int outlen = (int)sizeof(outbuf); |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, inbytes, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| | assert_output_equals(outbuf, outlen, "🙂"); |
| | TEST_ASSERT_EQUAL_INT(4, inlen); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_output_too_small_no_progress(void) { |
| | const char *in = "&"; |
| | int inlen = 1; |
| | unsigned char outbuf[1]; |
| | int outlen = 1; |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, (const unsigned char*)in, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| | TEST_ASSERT_EQUAL_INT(0, outlen); |
| | TEST_ASSERT_EQUAL_INT(0, inlen); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_partial_progress_due_to_output_limit(void) { |
| | const char *in = "A&B"; |
| | int inlen = 3; |
| | unsigned char outbuf[1]; |
| | int outlen = 1; |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, (const unsigned char*)in, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| | TEST_ASSERT_EQUAL_INT(1, outlen); |
| | TEST_ASSERT_EQUAL_INT(1, inlen); |
| | TEST_ASSERT_EQUAL_UINT8('A', outbuf[0]); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_malformed_trailing_in_leading_pos(void) { |
| | const unsigned char inbytes[] = {0x80}; |
| | int inlen = 1; |
| | unsigned char outbuf[16]; |
| | int outlen = (int)sizeof(outbuf); |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, inbytes, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(-2, rc); |
| | TEST_ASSERT_EQUAL_INT(0, outlen); |
| | TEST_ASSERT_EQUAL_INT(0, inlen); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_truncated_multibyte_at_end(void) { |
| | const unsigned char inbytes[] = {'A', 0xC2}; |
| | int inlen = 2; |
| | unsigned char outbuf[16]; |
| | int outlen = (int)sizeof(outbuf); |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, inbytes, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| | TEST_ASSERT_EQUAL_INT(1, outlen); |
| | TEST_ASSERT_EQUAL_INT(1, inlen); |
| | TEST_ASSERT_EQUAL_UINT8('A', outbuf[0]); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_invalid_trailing_byte(void) { |
| | const unsigned char inbytes[] = {'A', 0xC2, 'A'}; |
| | int inlen = 3; |
| | unsigned char outbuf[16]; |
| | int outlen = (int)sizeof(outbuf); |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, inbytes, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(-2, rc); |
| | TEST_ASSERT_EQUAL_INT(1, outlen); |
| | TEST_ASSERT_EQUAL_INT(1, inlen); |
| | } |
| |
|
| | |
| | void test_htmlEncodeEntities_mixed_content(void) { |
| | |
| | const unsigned char inbytes[] = {'A', '&', 0xC2, 0xA9, '<', 'B', '>', 0xF0, 0x9F, 0x99, 0x82}; |
| | int inlen = (int)sizeof(inbytes); |
| | unsigned char outbuf[128]; |
| | int outlen = (int)sizeof(outbuf); |
| |
|
| | int rc = htmlEncodeEntities(outbuf, &outlen, inbytes, &inlen, 0); |
| | TEST_ASSERT_EQUAL_INT(0, rc); |
| | assert_output_equals(outbuf, outlen, "A&©<B>🙂"); |
| | TEST_ASSERT_EQUAL_INT((int)sizeof(inbytes), inlen); |
| | } |
| |
|
| | int main(void) { |
| | UNITY_BEGIN(); |
| | RUN_TEST(test_htmlEncodeEntities_null_args); |
| | RUN_TEST(test_htmlEncodeEntities_ascii_passthrough); |
| | RUN_TEST(test_htmlEncodeEntities_special_ascii_entities); |
| | RUN_TEST(test_htmlEncodeEntities_double_quote_encoded); |
| | RUN_TEST(test_htmlEncodeEntities_single_quote_encoded); |
| | RUN_TEST(test_htmlEncodeEntities_named_entity_copyright); |
| | RUN_TEST(test_htmlEncodeEntities_numeric_entity_smiley); |
| | RUN_TEST(test_htmlEncodeEntities_output_too_small_no_progress); |
| | RUN_TEST(test_htmlEncodeEntities_partial_progress_due_to_output_limit); |
| | RUN_TEST(test_htmlEncodeEntities_malformed_trailing_in_leading_pos); |
| | RUN_TEST(test_htmlEncodeEntities_truncated_multibyte_at_end); |
| | RUN_TEST(test_htmlEncodeEntities_invalid_trailing_byte); |
| | RUN_TEST(test_htmlEncodeEntities_mixed_content); |
| | return UNITY_END(); |
| | } |