You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
10 KiB
296 lines
10 KiB
/** |
|
* Comprehensive test for debug configuration system |
|
* Tests runtime debug control, categories, levels, and formatting |
|
*/ |
|
|
|
#define _GNU_SOURCE // For setenv/unsetenv |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <unistd.h> |
|
|
|
#include "../lib/debug_config.h" |
|
|
|
static int test_passed = 0; |
|
static int test_failed = 0; |
|
|
|
#define TEST_START(name) do { \ |
|
printf("TEST: %s... ", name); \ |
|
} while(0) |
|
|
|
#define TEST_PASS() do { \ |
|
printf("PASS\n"); \ |
|
test_passed++; \ |
|
} while(0) |
|
|
|
#define TEST_FAIL(msg) do { \ |
|
printf("FAIL: %s\n", msg); \ |
|
test_failed++; \ |
|
} while(0) |
|
|
|
#define ASSERT_TRUE(cond, msg) do { \ |
|
if (!(cond)) { TEST_FAIL(msg); return; } \ |
|
} while(0) |
|
|
|
#define ASSERT_FALSE(cond, msg) do { \ |
|
if (cond) { TEST_FAIL(msg); return; } \ |
|
} while(0) |
|
|
|
#define ASSERT_EQ(a, b, msg) do { \ |
|
if ((a) != (b)) { TEST_FAIL(msg); return; } \ |
|
} while(0) |
|
|
|
static void test_basic_functionality(void) { |
|
TEST_START("Basic functionality"); |
|
|
|
debug_config_init(); |
|
|
|
/* Test default configuration */ |
|
ASSERT_EQ(g_debug_config.level, DEBUG_LEVEL_ERROR, "Default level should be ERROR"); |
|
ASSERT_EQ(g_debug_config.categories, DEBUG_CATEGORY_ALL, "All categories should be enabled by default"); |
|
ASSERT_FALSE(g_debug_config.timestamp_enabled, "Timestamps should be disabled by default"); |
|
ASSERT_FALSE(g_debug_config.function_name_enabled, "Function names should be disabled by default"); |
|
ASSERT_FALSE(g_debug_config.color_enabled, "Colors should be disabled by default"); |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
static void test_debug_levels(void) { |
|
TEST_START("Debug levels"); |
|
|
|
debug_config_init(); |
|
|
|
/* Test level changes */ |
|
debug_set_level(DEBUG_LEVEL_DEBUG); |
|
ASSERT_EQ(g_debug_config.level, DEBUG_LEVEL_DEBUG, "Level should be set to DEBUG"); |
|
|
|
debug_set_level(DEBUG_LEVEL_NONE); |
|
ASSERT_EQ(g_debug_config.level, DEBUG_LEVEL_NONE, "Level should be set to NONE"); |
|
|
|
/* Test output filtering */ |
|
ASSERT_FALSE(debug_should_output(DEBUG_LEVEL_INFO, DEBUG_CATEGORY_ALL), |
|
"INFO should not output at NONE level"); |
|
ASSERT_TRUE(debug_should_output(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_ALL), |
|
"ERROR should output at NONE level (fallback)"); |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
static void test_categories(void) { |
|
TEST_START("Categories"); |
|
|
|
debug_config_init(); |
|
debug_set_categories(DEBUG_CATEGORY_NONE); // Start with none |
|
|
|
/* Test enabling specific categories */ |
|
debug_enable_category(DEBUG_CATEGORY_UASYNC); |
|
ASSERT_TRUE(g_debug_config.categories & DEBUG_CATEGORY_UASYNC, "UASYNC should be enabled"); |
|
ASSERT_FALSE(g_debug_config.categories & DEBUG_CATEGORY_LL_QUEUE, "LL_QUEUE should be disabled"); |
|
|
|
/* Test disabling categories */ |
|
debug_disable_category(DEBUG_CATEGORY_UASYNC); |
|
ASSERT_FALSE(g_debug_config.categories & DEBUG_CATEGORY_UASYNC, "UASYNC should be disabled"); |
|
|
|
/* Test output filtering by category */ |
|
debug_set_level(DEBUG_LEVEL_DEBUG); |
|
debug_enable_category(DEBUG_CATEGORY_UASYNC); |
|
ASSERT_TRUE(debug_should_output(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_UASYNC), |
|
"UASYNC debug should output when enabled"); |
|
ASSERT_FALSE(debug_should_output(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_LL_QUEUE), |
|
"LL_QUEUE debug should not output when disabled"); |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
static void test_output_formatting(void) { |
|
TEST_START("Output formatting"); |
|
|
|
debug_config_init(); |
|
debug_set_level(DEBUG_LEVEL_DEBUG); |
|
debug_set_categories(DEBUG_CATEGORY_ALL); |
|
|
|
/* Test enabling different formatting options */ |
|
debug_enable_timestamp(1); |
|
ASSERT_TRUE(g_debug_config.timestamp_enabled, "Timestamps should be enabled"); |
|
|
|
debug_enable_function_name(1); |
|
ASSERT_TRUE(g_debug_config.function_name_enabled, "Function names should be enabled"); |
|
|
|
debug_enable_file_line(1); |
|
ASSERT_TRUE(g_debug_config.file_line_enabled, "File:line should be enabled"); |
|
|
|
debug_enable_color(1); |
|
ASSERT_TRUE(g_debug_config.color_enabled, "Colors should be enabled"); |
|
|
|
/* Test disabling */ |
|
debug_enable_timestamp(0); |
|
ASSERT_FALSE(g_debug_config.timestamp_enabled, "Timestamps should be disabled"); |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
static void test_rate_limiting(void) { |
|
TEST_START("Rate limiting"); |
|
|
|
debug_config_init(); |
|
debug_set_rate_limit(10); // 10 messages per second |
|
|
|
ASSERT_EQ(g_debug_config.max_output_per_second, 10, "Rate limit should be set to 10"); |
|
|
|
/* Test that rate limiting works (basic test) */ |
|
int allowed_count = 0; |
|
for (int i = 0; i < 20; i++) { |
|
if (debug_should_output(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_ALL)) allowed_count++; |
|
} |
|
|
|
/* Should allow at least 10 messages (first batch) */ |
|
ASSERT_TRUE(allowed_count >= 10, "Should allow at least 10 messages initially"); |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
static void test_config_parsing(void) { |
|
TEST_START("Configuration parsing"); |
|
|
|
debug_config_init(); |
|
|
|
/* Test simple level format */ |
|
ASSERT_EQ(debug_parse_config("debug"), 0, "Should parse 'debug' successfully"); |
|
ASSERT_EQ(g_debug_config.level, DEBUG_LEVEL_DEBUG, "Level should be set to DEBUG"); |
|
ASSERT_EQ(g_debug_config.categories, DEBUG_CATEGORY_ALL, "All categories should be enabled"); |
|
|
|
/* Test category:level format */ |
|
debug_set_categories(DEBUG_CATEGORY_NONE); |
|
debug_set_level(DEBUG_LEVEL_ERROR); |
|
|
|
ASSERT_EQ(debug_parse_config("uasync:debug,ll_queue:info"), 0, "Should parse category:level format"); |
|
ASSERT_TRUE(g_debug_config.categories & DEBUG_CATEGORY_UASYNC, "UASYNC should be enabled"); |
|
ASSERT_TRUE(g_debug_config.categories & DEBUG_CATEGORY_LL_QUEUE, "LL_QUEUE should be enabled"); |
|
ASSERT_EQ(g_debug_config.level, DEBUG_LEVEL_DEBUG, "Level should be set to highest requested"); |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
static void test_environment_variable(void) { |
|
TEST_START("Environment variable parsing"); |
|
|
|
/* Set environment variable */ |
|
setenv("UTUN_DEBUG", "uasync:debug,connection:warn", 1); |
|
|
|
debug_config_init(); // Should read from environment |
|
|
|
ASSERT_TRUE(g_debug_config.categories & DEBUG_CATEGORY_UASYNC, "UASYNC should be enabled from env"); |
|
ASSERT_TRUE(g_debug_config.categories & DEBUG_CATEGORY_CONNECTION, "CONNECTION should be enabled from env"); |
|
ASSERT_FALSE(g_debug_config.categories & DEBUG_CATEGORY_LL_QUEUE, "LL_QUEUE should be disabled from env"); |
|
|
|
/* Clean up */ |
|
unsetenv("UTUN_DEBUG"); |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
static void test_debug_output(void) { |
|
TEST_START("Debug output functionality"); |
|
|
|
debug_config_init(); |
|
debug_set_level(DEBUG_LEVEL_DEBUG); |
|
debug_set_categories(DEBUG_CATEGORY_ALL); |
|
debug_enable_timestamp(1); |
|
debug_enable_function_name(1); |
|
debug_enable_file_line(1); |
|
|
|
printf("\n--- Sample debug output ---\n"); |
|
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "Test error message"); |
|
DEBUG_WARN(DEBUG_CATEGORY_UASYNC, "Test warning message"); |
|
DEBUG_INFO(DEBUG_CATEGORY_LL_QUEUE, "Test info message"); |
|
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "Test debug message"); |
|
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "Test trace message"); |
|
printf("--- End sample output ---\n\n"); |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
static void test_effective_level(void) { |
|
TEST_START("Effective level calculation"); |
|
|
|
debug_config_init(); |
|
debug_set_level(DEBUG_LEVEL_INFO); |
|
debug_set_categories(DEBUG_CATEGORY_UASYNC); |
|
|
|
ASSERT_EQ(debug_get_effective_level(DEBUG_CATEGORY_UASYNC), DEBUG_LEVEL_INFO, "UASYNC should have INFO level"); |
|
ASSERT_EQ(debug_get_effective_level(DEBUG_CATEGORY_LL_QUEUE), DEBUG_LEVEL_NONE, "LL_QUEUE should have NONE level"); |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
static void test_output_file(void) { |
|
TEST_START("Output file configuration"); |
|
|
|
debug_config_init(); |
|
debug_set_level(DEBUG_LEVEL_DEBUG); |
|
debug_set_categories(DEBUG_CATEGORY_ALL); |
|
|
|
/* Test file output */ |
|
const char* test_file = "/tmp/debug_test.log"; |
|
debug_set_output_file(test_file); |
|
|
|
ASSERT_TRUE(g_debug_config.output_file != NULL, "Output file should be set"); |
|
ASSERT_TRUE(strcmp(g_debug_config.output_file, test_file) == 0, "Output file path should match"); |
|
|
|
/* Output some messages */ |
|
DEBUG_INFO(DEBUG_CATEGORY_ALL, "Test message to file"); |
|
DEBUG_DEBUG(DEBUG_CATEGORY_ALL, "Another test message to file"); |
|
|
|
/* Reset to stderr */ |
|
debug_set_output_file(NULL); |
|
/* Can't directly check debug_output_file, but we can test functionality */ |
|
|
|
/* Check that file was created */ |
|
if (access(test_file, F_OK) == 0) { |
|
printf(" Debug file created successfully: %s\n", test_file); |
|
unlink(test_file); // Clean up |
|
} else { |
|
TEST_FAIL("Debug file was not created"); |
|
} |
|
|
|
TEST_PASS(); |
|
} |
|
|
|
int main(void) { |
|
printf("=== Debug Configuration System Test ===\n"); |
|
printf("Testing runtime debug control system\n\n"); |
|
|
|
/* Run all tests */ |
|
test_basic_functionality(); |
|
test_debug_levels(); |
|
test_categories(); |
|
test_output_formatting(); |
|
test_rate_limiting(); |
|
test_config_parsing(); |
|
test_environment_variable(); |
|
test_debug_output(); |
|
test_effective_level(); |
|
test_output_file(); |
|
|
|
/* Summary */ |
|
printf("\n=== Test Summary ===\n"); |
|
printf("Tests passed: %d\n", test_passed); |
|
printf("Tests failed: %d\n", test_failed); |
|
printf("Total tests: %d\n", test_passed + test_failed); |
|
|
|
if (test_failed == 0) { |
|
printf("\n✅ All tests passed! Debug configuration system is working correctly.\n"); |
|
printf("\nKey features verified:\n"); |
|
printf("- Runtime debug level control\n"); |
|
printf("- Category-based filtering\n"); |
|
printf("- Flexible output formatting (timestamps, colors, etc.)\n"); |
|
printf("- Rate limiting for high-frequency debug output\n"); |
|
printf("- Environment variable configuration\n"); |
|
printf("- File output support\n"); |
|
printf("- Backward compatibility with existing code\n"); |
|
return 0; |
|
} else { |
|
printf("\n❌ Some tests failed. Please check the implementation.\n"); |
|
return 1; |
|
} |
|
} |