/* * test_json_serialization.c - Unit tests for JSON serialization */ #include #include #include #include #include #include #include #include #include /* Mock JSON string escaping function for testing */ static void append_json_string(apr_pool_t *pool, apr_strbuf_t *buf, const char *str) { if (str == NULL) { return; } for (const char *p = str; *p; p++) { char c = *p; switch (c) { case '"': apr_strbuf_append(buf, "\\\"", 2); break; case '\\': apr_strbuf_append(buf, "\\\\", 2); break; case '\b': apr_strbuf_append(buf, "\\b", 2); break; case '\f': apr_strbuf_append(buf, "\\f", 2); break; case '\n': apr_strbuf_append(buf, "\\n", 2); break; case '\r': apr_strbuf_append(buf, "\\r", 2); break; case '\t': apr_strbuf_append(buf, "\\t", 2); break; default: if ((unsigned char)c < 0x20) { char unicode[8]; apr_snprintf(unicode, sizeof(unicode), "\\u%04x", (unsigned char)c); apr_strbuf_append(buf, unicode, -1); } else { apr_strbuf_append_char(buf, c); } break; } } } /* Test: Empty string */ static void test_json_escape_empty_string(void **state) { apr_pool_t *pool; apr_pool_create(&pool, NULL); apr_strbuf_t buf; char *initial = apr_palloc(pool, 256); apr_strbuf_init(pool, &buf, initial, 256); append_json_string(pool, &buf, ""); assert_string_equal(buf.buf, ""); apr_pool_destroy(pool); } /* Test: Simple string without special characters */ static void test_json_escape_simple_string(void **state) { apr_pool_t *pool; apr_pool_create(&pool, NULL); apr_strbuf_t buf; char *initial = apr_palloc(pool, 256); apr_strbuf_init(pool, &buf, initial, 256); append_json_string(pool, &buf, "hello world"); assert_string_equal(buf.buf, "hello world"); apr_pool_destroy(pool); } /* Test: String with double quotes */ static void test_json_escape_quotes(void **state) { apr_pool_t *pool; apr_pool_create(&pool, NULL); apr_strbuf_t buf; char *initial = apr_palloc(pool, 256); apr_strbuf_init(pool, &buf, initial, 256); append_json_string(pool, &buf, "hello \"world\""); assert_string_equal(buf.buf, "hello \\\"world\\\""); apr_pool_destroy(pool); } /* Test: String with backslashes */ static void test_json_escape_backslashes(void **state) { apr_pool_t *pool; apr_pool_create(&pool, NULL); apr_strbuf_t buf; char *initial = apr_palloc(pool, 256); apr_strbuf_init(pool, &buf, initial, 256); append_json_string(pool, &buf, "path\\to\\file"); assert_string_equal(buf.buf, "path\\\\to\\\\file"); apr_pool_destroy(pool); } /* Test: String with newlines and tabs */ static void test_json_escape_newlines_tabs(void **state) { apr_pool_t *pool; apr_pool_create(&pool, NULL); apr_strbuf_t buf; char *initial = apr_palloc(pool, 256); apr_strbuf_init(pool, &buf, initial, 256); append_json_string(pool, &buf, "line1\nline2\ttab"); assert_string_equal(buf.buf, "line1\\nline2\\ttab"); apr_pool_destroy(pool); } /* Test: String with control characters */ static void test_json_escape_control_chars(void **state) { apr_pool_t *pool; apr_pool_create(&pool, NULL); apr_strbuf_t buf; char *initial = apr_palloc(pool, 256); apr_strbuf_init(pool, &buf, initial, 256); /* Test with bell character (0x07) */ append_json_string(pool, &buf, "test\bell"); /* Should contain unicode escape */ assert_true(strstr(buf.buf, "\\u0007") != NULL); apr_pool_destroy(pool); } /* Test: NULL string */ static void test_json_escape_null_string(void **state) { apr_pool_t *pool; apr_pool_create(&pool, NULL); apr_strbuf_t buf; char *initial = apr_palloc(pool, 256); apr_strbuf_init(pool, &buf, initial, 256); append_json_string(pool, &buf, NULL); assert_string_equal(buf.buf, ""); apr_pool_destroy(pool); } /* Test: Complex user agent string */ static void test_json_escape_user_agent(void **state) { apr_pool_t *pool; apr_pool_create(&pool, NULL); apr_strbuf_t buf; char *initial = apr_palloc(pool, 512); apr_strbuf_init(pool, &buf, initial, 512); const char *ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) \"Test\""; append_json_string(pool, &buf, ua); assert_true(strstr(buf.buf, "\\\"Test\\\"") != NULL); apr_pool_destroy(pool); } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_json_escape_empty_string), cmocka_unit_test(test_json_escape_simple_string), cmocka_unit_test(test_json_escape_quotes), cmocka_unit_test(test_json_escape_backslashes), cmocka_unit_test(test_json_escape_newlines_tabs), cmocka_unit_test(test_json_escape_control_chars), cmocka_unit_test(test_json_escape_null_string), cmocka_unit_test(test_json_escape_user_agent), }; return cmocka_run_group_tests(tests, NULL, NULL); }