/* * test_config_parsing.c - Unit tests for configuration parsing */ #include #include #include #include #include #include #include #include #include /* Default configuration values */ #define DEFAULT_MAX_HEADERS 10 #define DEFAULT_MAX_HEADER_VALUE_LEN 256 #define DEFAULT_RECONNECT_INTERVAL 10 #define DEFAULT_ERROR_REPORT_INTERVAL 10 #define MAX_SOCKET_PATH_LEN 108 /* Mock configuration structure */ typedef struct { int enabled; const char *socket_path; int max_headers; int max_header_value_len; int reconnect_interval; int error_report_interval; } mock_config_t; /* Mock parsing functions */ static int parse_enabled(const char *value) { if (strcasecmp(value, "on") == 0 || strcmp(value, "1") == 0) { return 1; } return 0; } static const char *parse_socket_path(const char *value) { if (value == NULL || strlen(value) == 0) { return NULL; } if (strlen(value) >= MAX_SOCKET_PATH_LEN) { return NULL; } return value; } static int parse_int_strict(const char *value, int *result) { char *endptr = NULL; long val; if (value == NULL || *value == '\0' || result == NULL) { return -1; } errno = 0; val = strtol(value, &endptr, 10); if (errno != 0 || endptr == value || *endptr != '\0' || val < INT_MIN || val > INT_MAX) { return -1; } *result = (int)val; return 0; } static int parse_max_headers(const char *value, int *result) { if (parse_int_strict(value, result) != 0 || *result < 0) { return -1; } return 0; } static int parse_interval(const char *value, int *result) { if (parse_int_strict(value, result) != 0 || *result < 0) { return -1; } return 0; } static int parse_max_header_value_len(const char *value, int *result) { if (parse_int_strict(value, result) != 0 || *result < 1) { return -1; } return 0; } /* Test: Parse enabled On */ static void test_parse_enabled_on(void **state) { (void)state; assert_int_equal(parse_enabled("On"), 1); assert_int_equal(parse_enabled("on"), 1); assert_int_equal(parse_enabled("ON"), 1); assert_int_equal(parse_enabled("1"), 1); } /* Test: Parse enabled Off */ static void test_parse_enabled_off(void **state) { (void)state; assert_int_equal(parse_enabled("Off"), 0); assert_int_equal(parse_enabled("off"), 0); assert_int_equal(parse_enabled("OFF"), 0); assert_int_equal(parse_enabled("0"), 0); } /* Test: Parse socket path valid */ static void test_parse_socket_path_valid(void **state) { (void)state; const char *result = parse_socket_path("/var/run/logcorrelator/http.socket"); assert_string_equal(result, "/var/run/logcorrelator/http.socket"); } /* Test: Parse socket path empty */ static void test_parse_socket_path_empty(void **state) { (void)state; const char *result = parse_socket_path(""); assert_null(result); } /* Test: Parse socket path NULL */ static void test_parse_socket_path_null(void **state) { (void)state; const char *result = parse_socket_path(NULL); assert_null(result); } /* Test: Parse socket path max length valid */ static void test_parse_socket_path_max_len_valid(void **state) { (void)state; char path[MAX_SOCKET_PATH_LEN]; memset(path, 'a', MAX_SOCKET_PATH_LEN - 1); path[MAX_SOCKET_PATH_LEN - 1] = '\0'; assert_non_null(parse_socket_path(path)); } /* Test: Parse socket path max length invalid */ static void test_parse_socket_path_max_len_invalid(void **state) { (void)state; char path[MAX_SOCKET_PATH_LEN + 1]; memset(path, 'b', MAX_SOCKET_PATH_LEN); path[MAX_SOCKET_PATH_LEN] = '\0'; assert_null(parse_socket_path(path)); } /* Test: Parse max headers valid */ static void test_parse_max_headers_valid(void **state) { int result; (void)state; assert_int_equal(parse_max_headers("10", &result), 0); assert_int_equal(result, 10); assert_int_equal(parse_max_headers("0", &result), 0); assert_int_equal(result, 0); assert_int_equal(parse_max_headers("100", &result), 0); assert_int_equal(result, 100); } /* Test: Parse max headers invalid */ static void test_parse_max_headers_invalid(void **state) { int result; (void)state; assert_int_equal(parse_max_headers("-1", &result), -1); assert_int_equal(parse_max_headers("abc", &result), -1); assert_int_equal(parse_max_headers("10abc", &result), -1); } /* Test: Parse reconnect interval valid */ static void test_parse_reconnect_interval_valid(void **state) { int result; (void)state; assert_int_equal(parse_interval("10", &result), 0); assert_int_equal(result, 10); assert_int_equal(parse_interval("0", &result), 0); assert_int_equal(result, 0); assert_int_equal(parse_interval("60", &result), 0); assert_int_equal(result, 60); } /* Test: Parse reconnect interval invalid */ static void test_parse_reconnect_interval_invalid(void **state) { int result; (void)state; assert_int_equal(parse_interval("-5", &result), -1); assert_int_equal(parse_interval("abc", &result), -1); assert_int_equal(parse_interval("10abc", &result), -1); } /* Test: Parse max header value length valid */ static void test_parse_max_header_value_len_valid(void **state) { int result; (void)state; assert_int_equal(parse_max_header_value_len("1", &result), 0); assert_int_equal(result, 1); assert_int_equal(parse_max_header_value_len("256", &result), 0); assert_int_equal(result, 256); } /* Test: Parse max header value length invalid */ static void test_parse_max_header_value_len_invalid(void **state) { int result; (void)state; assert_int_equal(parse_max_header_value_len("0", &result), -1); assert_int_equal(parse_max_header_value_len("-1", &result), -1); assert_int_equal(parse_max_header_value_len("10abc", &result), -1); } /* Test: strict numeric parsing invalid suffix for all int directives */ static void test_strict_numeric_invalid_suffix_all(void **state) { int result; (void)state; assert_int_equal(parse_max_headers("10abc", &result), -1); assert_int_equal(parse_interval("10abc", &result), -1); assert_int_equal(parse_max_header_value_len("10abc", &result), -1); } /* Test: Default configuration values */ static void test_default_config_values(void **state) { (void)state; assert_int_equal(DEFAULT_MAX_HEADERS, 10); assert_int_equal(DEFAULT_MAX_HEADER_VALUE_LEN, 256); assert_int_equal(DEFAULT_RECONNECT_INTERVAL, 10); assert_int_equal(DEFAULT_ERROR_REPORT_INTERVAL, 10); } /* Test: Configuration validation - enabled requires socket */ static void test_config_validation_enabled_requires_socket(void **state) { int enabled = 1; const char *socket = "/var/run/socket"; (void)state; assert_true(enabled == 0 || socket != NULL); socket = NULL; assert_false(enabled == 0 || socket != NULL); } /* Test: Configuration validation - enabled with empty socket is invalid */ static void test_config_validation_enabled_with_empty_socket(void **state) { int enabled = 1; const char *socket = parse_socket_path(""); (void)state; assert_false(enabled == 0 || socket != NULL); } /* Test: Header value length validation */ static void test_header_value_len_validation(void **state) { int result; (void)state; assert_int_equal(parse_max_header_value_len("1", &result), 0); assert_true(result >= 1); assert_int_equal(parse_max_header_value_len("0", &result), -1); } /* Test: Large but valid values */ static void test_large_valid_values(void **state) { int result; (void)state; assert_int_equal(parse_max_headers("1000000", &result), 0); assert_int_equal(result, 1000000); assert_int_equal(parse_interval("86400", &result), 0); assert_int_equal(result, 86400); } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_parse_enabled_on), cmocka_unit_test(test_parse_enabled_off), cmocka_unit_test(test_parse_socket_path_valid), cmocka_unit_test(test_parse_socket_path_empty), cmocka_unit_test(test_parse_socket_path_null), cmocka_unit_test(test_parse_socket_path_max_len_valid), cmocka_unit_test(test_parse_socket_path_max_len_invalid), cmocka_unit_test(test_parse_max_headers_valid), cmocka_unit_test(test_parse_max_headers_invalid), cmocka_unit_test(test_parse_reconnect_interval_valid), cmocka_unit_test(test_parse_reconnect_interval_invalid), cmocka_unit_test(test_parse_max_header_value_len_valid), cmocka_unit_test(test_parse_max_header_value_len_invalid), cmocka_unit_test(test_strict_numeric_invalid_suffix_all), cmocka_unit_test(test_default_config_values), cmocka_unit_test(test_config_validation_enabled_requires_socket), cmocka_unit_test(test_config_validation_enabled_with_empty_socket), cmocka_unit_test(test_header_value_len_validation), cmocka_unit_test(test_large_valid_values), }; return cmocka_run_group_tests(tests, NULL, NULL); }