Initial commit: mod_reqin_log Apache module
Features: - JSON logging of HTTP requests to Unix domain socket - Configurable HTTP headers logging (flat JSON structure) - Header value truncation and count limits - Automatic reconnect on socket disconnection - Error reporting with throttling Configuration directives: - JsonSockLogEnabled: Enable/disable logging - JsonSockLogSocket: Unix socket path - JsonSockLogHeaders: List of headers to log - JsonSockLogMaxHeaders: Maximum headers to log - JsonSockLogMaxHeaderValueLen: Max header value length - JsonSockLogReconnectInterval: Reconnect delay - JsonSockLogErrorReportInterval: Error log throttle Includes: - Module source code (src/) - Unit and integration tests (tests/, scripts/) - Documentation (README.md, architecture.yml) - Build configuration (CMakeLists.txt, Makefile) - Packaging (deb/rpm) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
198
tests/unit/test_json_serialization.c
Normal file
198
tests/unit/test_json_serialization.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* test_json_serialization.c - Unit tests for JSON serialization
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <cmocka.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <apr_strings.h>
|
||||
#include <apr_time.h>
|
||||
#include <apr_lib.h>
|
||||
|
||||
/* 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);
|
||||
}
|
||||
Reference in New Issue
Block a user