From 3ddfb7933836b78393d55b101a8c4384cd3a3f2b Mon Sep 17 00:00:00 2001 From: Evgeny Date: Mon, 26 Jan 2026 17:52:50 +0300 Subject: [PATCH] Backup before replacing all printf with DEBUG_ macros in tests --- clean_newlines.py | 44 - replace_printf.py | 173 -- replace_remaining.py | 119 - src/etcp_connections.c | 1 - tests/Makefile.am | 6 +- tests/debug_full_test.c | 359 ++- tests/debug_full_test.c.backup | 234 -- tests/debug_performance.c | 75 +- tests/debug_performance.c.backup | 47 - tests/detailed_test.c | 145 +- tests/detailed_test.c.backup | 86 - tests/simple_test.c | 55 +- tests/simple_test.c.backup | 37 - tests/test_config_debug | Bin 0 -> 89936 bytes tests/test_config_debug.c | 98 +- tests/test_config_debug.c.backup | 59 - tests/test_crypto | Bin 0 -> 65936 bytes tests/test_crypto.c | 107 +- tests/test_crypto.c.backup | 62 - tests/test_debug.c | 77 +- tests/test_debug.c.backup | 49 - tests/test_debug_categories | Bin 0 -> 42536 bytes tests/test_debug_categories.c | 194 +- tests/test_debug_categories.c.backup | 106 - tests/test_ecc_encrypt | Bin 0 -> 208968 bytes tests/test_ecc_encrypt.c | 253 ++- tests/test_ecc_encrypt.c.backup | 179 -- tests/test_etcp_crypto | Bin 0 -> 200640 bytes tests/test_etcp_crypto.c | 130 +- tests/test_etcp_crypto.c.backup | 79 - tests/test_etcp_minimal | Bin 0 -> 404688 bytes tests/test_etcp_minimal.c | 368 +-- tests/test_etcp_minimal.c.backup | 207 -- tests/test_etcp_simple_traffic | Bin 572384 -> 572160 bytes tests/test_etcp_simple_traffic.c | 730 +++--- tests/test_etcp_simple_traffic.c.backup | 880 ++++---- tests/test_etcp_two_instances | Bin 0 -> 554984 bytes tests/test_etcp_two_instances.c | 511 +++-- tests/test_etcp_two_instances.c.backup | 157 +- tests/test_fix.patch | 26 + tests/test_intensive_memory_pool | Bin 0 -> 104568 bytes tests/test_intensive_memory_pool.c | 252 +-- tests/test_intensive_memory_pool.c.backup | 153 -- tests/test_intensive_memory_pool_backup.c | 256 +-- ...test_intensive_memory_pool_backup.c.backup | 157 -- tests/test_intensive_memory_pool_new.c | 252 +-- tests/test_intensive_memory_pool_new.c.backup | 153 -- tests/test_ll_queue | Bin 0 -> 171040 bytes tests/test_ll_queue.c | 1988 +++++++++-------- tests/test_ll_queue.c.backup | 1126 ---------- tests/test_memory_pool_and_config | Bin 0 -> 109000 bytes tests/test_memory_pool_and_config.c | 223 +- tests/test_memory_pool_and_config.c.backup | 133 -- tests/test_packet_dump | Bin 0 -> 19248 bytes tests/test_packet_dump.c | 28 +- tests/test_packet_dump.c.backup | 22 - tests/test_u_async_comprehensive | Bin 0 -> 99936 bytes tests/test_u_async_comprehensive.c | 801 ++++--- tests/test_u_async_comprehensive.c.backup | 493 ---- tests/test_u_async_performance | Bin 0 -> 90112 bytes tests/test_u_async_performance.c | 508 ++--- tests/test_u_async_performance.c.backup | 290 --- tests/track_test | Bin 0 -> 41304 bytes tests/track_test.c | 225 +- tests/track_test.c.backup | 154 -- tests/working_crypto_test.c | 191 +- tests/working_crypto_test.c.backup | 104 - 67 files changed, 4486 insertions(+), 8676 deletions(-) delete mode 100644 clean_newlines.py delete mode 100644 replace_printf.py delete mode 100644 replace_remaining.py delete mode 100644 tests/debug_full_test.c.backup delete mode 100644 tests/debug_performance.c.backup delete mode 100644 tests/detailed_test.c.backup delete mode 100644 tests/simple_test.c.backup create mode 100755 tests/test_config_debug delete mode 100644 tests/test_config_debug.c.backup create mode 100755 tests/test_crypto delete mode 100644 tests/test_crypto.c.backup delete mode 100644 tests/test_debug.c.backup create mode 100755 tests/test_debug_categories delete mode 100644 tests/test_debug_categories.c.backup create mode 100755 tests/test_ecc_encrypt delete mode 100644 tests/test_ecc_encrypt.c.backup create mode 100755 tests/test_etcp_crypto delete mode 100644 tests/test_etcp_crypto.c.backup create mode 100755 tests/test_etcp_minimal delete mode 100644 tests/test_etcp_minimal.c.backup create mode 100755 tests/test_etcp_two_instances create mode 100644 tests/test_fix.patch create mode 100755 tests/test_intensive_memory_pool delete mode 100644 tests/test_intensive_memory_pool.c.backup delete mode 100644 tests/test_intensive_memory_pool_backup.c.backup delete mode 100644 tests/test_intensive_memory_pool_new.c.backup create mode 100755 tests/test_ll_queue delete mode 100644 tests/test_ll_queue.c.backup create mode 100755 tests/test_memory_pool_and_config delete mode 100644 tests/test_memory_pool_and_config.c.backup create mode 100755 tests/test_packet_dump delete mode 100644 tests/test_packet_dump.c.backup create mode 100755 tests/test_u_async_comprehensive delete mode 100644 tests/test_u_async_comprehensive.c.backup create mode 100755 tests/test_u_async_performance delete mode 100644 tests/test_u_async_performance.c.backup create mode 100755 tests/track_test delete mode 100644 tests/track_test.c.backup delete mode 100644 tests/working_crypto_test.c.backup diff --git a/clean_newlines.py b/clean_newlines.py deleted file mode 100644 index 5d409310..00000000 --- a/clean_newlines.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python3 -""" -Remove trailing \\n from format strings in DEBUG_ macros. -""" - -import os -import re -import sys - -def clean_file(filepath): - with open(filepath, 'r') as f: - content = f.read() - - original = content - - # Pattern to match DEBUG_(ERROR|WARN|INFO|DEBUG|TRACE)\([^)]*\"([^"]*)\\n\"[^)]*\) - # We'll process line by line - lines = content.split('\n') - new_lines = [] - for line in lines: - # Look for DEBUG_ macros with \n in format string - # Simple replacement for \"...\\n\" -> \"...\" - line = re.sub(r'(DEBUG_(ERROR|WARN|INFO|DEBUG|TRACE)\([^,]+,\s*")([^"]*)\\n(")', r'\1\3\4', line) - # Also remove emojis ❌✅ℹ️ - line = line.replace('❌', '').replace('✅', '').replace('ℹ️', '').strip() - new_lines.append(line) - - content = '\n'.join(new_lines) - - if content != original: - with open(filepath, 'w') as f: - f.write(content) - print(f"Cleaned {filepath}") - -def main(): - test_dir = 'tests' - for root, dirs, files in os.walk(test_dir): - for file in files: - if file.endswith('.c'): - filepath = os.path.join(root, file) - clean_file(filepath) - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/replace_printf.py b/replace_printf.py deleted file mode 100644 index 9b2be984..00000000 --- a/replace_printf.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python3 -""" -Replace printf with DEBUG_ macros in test files. -""" - -import os -import re -import sys - -def add_debug_include(content): - """Add #include \"../lib/debug_config.h\" if not present.""" - if '#include "../lib/debug_config.h"' in content: - return content - # Find position after last #include - lines = content.split('\n') - new_lines = [] - include_added = False - for line in lines: - new_lines.append(line) - if line.strip().startswith('#include') and not include_added: - # Add our include after the last #include block - # Check if next line is not #include - pass - # Simpler: insert after first #include line that includes something from ../lib or ../src - # Actually, just insert after the first #include line - for i, line in enumerate(lines): - if line.strip().startswith('#include'): - # Insert after this line - lines.insert(i + 1, '#include "../lib/debug_config.h"') - break - return '\n'.join(lines) - -def add_debug_init(content): - """Add debug initialization at the beginning of main().""" - if 'debug_config_init();' in content: - return content - # Find int main() { - pattern = r'int main\s*\(\s*\)\s*\{' - match = re.search(pattern, content) - if not match: - return content - start = match.end() - # Insert after the opening brace - # Find the next newline after brace - newline_pos = content.find('\n', start) - if newline_pos == -1: - return content - insertion_point = newline_pos + 1 - init_code = '\n debug_config_init();\n debug_set_level(DEBUG_LEVEL_TRACE);\n debug_set_categories(DEBUG_CATEGORY_ALL);\n' - content = content[:insertion_point] + init_code + content[insertion_point:] - return content - -def determine_category(filename, line): - """Determine debug category based on filename and line content.""" - filename_lower = filename.lower() - if 'crypto' in filename_lower: - return 'DEBUG_CATEGORY_CRYPTO' - elif 'etcp' in filename_lower: - return 'DEBUG_CATEGORY_ETCP' - elif 'memory' in filename_lower: - return 'DEBUG_CATEGORY_MEMORY' - elif 'u_async' in filename_lower: - return 'DEBUG_CATEGORY_UASYNC' - elif 'll_queue' in filename_lower: - return 'DEBUG_CATEGORY_LL_QUEUE' - elif 'config' in filename_lower: - return 'DEBUG_CATEGORY_CONFIG' - else: - return 'DEBUG_CATEGORY_ALL' - -def determine_level(line): - """Determine debug level based on line content.""" - line_lower = line.lower() - if '❌' in line or 'error' in line_lower or 'failed' in line_lower: - return 'DEBUG_ERROR' - elif 'warn' in line_lower: - return 'DEBUG_WARN' - elif '✅' in line_lower or 'success' in line_lower or 'passed' in line_lower: - return 'DEBUG_INFO' - elif '[debug]' in line_lower: - return 'DEBUG_DEBUG' - elif 'info' in line_lower: - return 'DEBUG_INFO' - else: - return 'DEBUG_INFO' - -def replace_printf(content, filename): - """Replace printf calls with DEBUG_ macros.""" - # Pattern to match printf("...", ...); - # Simple approach: replace line by line - lines = content.split('\n') - new_lines = [] - i = 0 - while i < len(lines): - line = lines[i] - stripped = line.strip() - - # Check for printf - if stripped.startswith('printf('): - # Extract format string and arguments - # Simple regex to capture printf("format", args); - match = re.match(r'printf\("([^"]*)"\s*,?(.*)\);', stripped) - if match: - fmt = match.group(1) - args = match.group(2).strip() - # Remove ❌ and ✅ symbols - fmt = fmt.replace('❌', '').replace('✅', '').strip() - # Determine category and level - category = determine_category(filename, line) - level = determine_level(line) - # Build new macro call - if args: - new_line = line.replace(stripped, f'{level}({category}, "{fmt}", {args});') - else: - new_line = line.replace(stripped, f'{level}({category}, "{fmt}");') - new_lines.append(new_line) - # Check if next line is fflush(stdout); - if i + 1 < len(lines) and 'fflush(stdout);' in lines[i + 1]: - i += 1 # Skip fflush line - else: - # Keep original if pattern doesn't match - new_lines.append(line) - elif stripped.startswith('fprintf(') and 'stderr' in stripped: - # Replace fprintf(stderr, ...) with DEBUG_ERROR - match = re.match(r'fprintf\s*\(\s*stderr\s*,\s*"([^"]*)"\s*,?(.*)\);', stripped) - if match: - fmt = match.group(1) - args = match.group(2).strip() - category = determine_category(filename, line) - new_line = line.replace(stripped, f'DEBUG_ERROR({category}, "{fmt}", {args});') - new_lines.append(new_line) - else: - new_lines.append(line) - else: - new_lines.append(line) - i += 1 - - return '\n'.join(new_lines) - -def process_file(filepath): - """Process a single file.""" - print(f"Processing {filepath}") - with open(filepath, 'r') as f: - content = f.read() - - original = content - - # Step 1: Add debug include - content = add_debug_include(content) - - # Step 2: Add debug initialization in main() - content = add_debug_init(content) - - # Step 3: Replace printf calls - content = replace_printf(content, os.path.basename(filepath)) - - if content != original: - with open(filepath, 'w') as f: - f.write(content) - print(f" Updated {filepath}") - else: - print(f" No changes needed") - -def main(): - test_dir = 'tests' - for root, dirs, files in os.walk(test_dir): - for file in files: - if file.endswith('.c'): - filepath = os.path.join(root, file) - process_file(filepath) - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/replace_remaining.py b/replace_remaining.py deleted file mode 100644 index 64c746ba..00000000 --- a/replace_remaining.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python3 -""" -Replace remaining printf calls in test files. -""" - -import os -import re -import sys - -def process_file(filepath): - with open(filepath, 'r') as f: - content = f.read() - - original = content - - # Determine category based on filename - filename = os.path.basename(filepath).lower() - if 'crypto' in filename or 'ecc' in filename: - category = 'DEBUG_CATEGORY_CRYPTO' - elif 'etcp' in filename: - category = 'DEBUG_CATEGORY_ETCP' - elif 'memory' in filename: - category = 'DEBUG_CATEGORY_MEMORY' - elif 'u_async' in filename: - category = 'DEBUG_CATEGORY_UASYNC' - elif 'll_queue' in filename: - category = 'DEBUG_CATEGORY_LL_QUEUE' - elif 'config' in filename: - category = 'DEBUG_CATEGORY_CONFIG' - else: - category = 'DEBUG_CATEGORY_ALL' - - # Replace printf calls - simple pattern for single line printf - lines = content.split('\n') - new_lines = [] - i = 0 - while i < len(lines): - line = lines[i] - stripped = line.strip() - - # Look for printf - if stripped.startswith('printf('): - # Try to capture the whole printf call (may span multiple lines) - # Collect lines until we find semicolon - printf_lines = [line] - j = i + 1 - while j < len(lines) and ';' not in lines[j-1]: - printf_lines.append(lines[j]) - j += 1 - # Now we have block of lines - block = '\n'.join(printf_lines) - # Simple regex for single line printf with arguments on same line - # Match printf("format", args...); - match = re.search(r'printf\s*\(\s*"([^"]*)"\s*,?(.*)\)\s*;', block, re.DOTALL) - if match: - fmt = match.group(1).replace('\n', '').replace('\\n', '') - args = match.group(2).strip() - # Determine level - fmt_lower = fmt.lower() - if '❌' in fmt or 'error' in fmt_lower or 'failed' in fmt_lower: - level = 'DEBUG_ERROR' - elif 'warn' in fmt_lower: - level = 'DEBUG_WARN' - elif '✅' in fmt_lower or 'success' in fmt_lower or 'passed' in fmt_lower: - level = 'DEBUG_INFO' - elif '[debug]' in fmt_lower: - level = 'DEBUG_DEBUG' - else: - level = 'DEBUG_INFO' - # Remove emojis - fmt = fmt.replace('❌', '').replace('✅', '').replace('ℹ️', '').strip() - # Build new line - if args: - new_line = line.replace(stripped, f'{level}({category}, "{fmt}", {args});') - else: - new_line = line.replace(stripped, f'{level}({category}, "{fmt}");') - new_lines.append(new_line) - i = j # Skip the lines we consumed - continue - else: - # Fallback: just remove printf line - new_lines.append(line) - else: - new_lines.append(line) - i += 1 - - content = '\n'.join(new_lines) - - # Remove fflush(stdout) lines - content = re.sub(r'^\s*fflush\s*\(\s*stdout\s*\)\s*;\s*$', '', content, flags=re.MULTILINE) - - if content != original: - with open(filepath, 'w') as f: - f.write(content) - print(f"Updated {filepath}") - else: - print(f"No changes in {filepath}") - -def main(): - # Files that still have printf according to grep - files = [ - 'tests/test_ll_queue.c', - 'tests/test_ecc_encrypt.c', - 'tests/test_debug_categories.c', - 'tests/test_etcp_two_instances.c', - 'tests/test_packet_dump.c', - 'tests/test_memory_pool_and_config.c', - 'tests/test_u_async_performance.c', - 'tests/test_etcp_minimal.c' - ] - - for filepath in files: - if os.path.exists(filepath): - process_file(filepath) - else: - print(f"File not found: {filepath}") - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/src/etcp_connections.c b/src/etcp_connections.c index f8a6a2e7..02535a3e 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -634,7 +634,6 @@ static void etcp_connections_read_callback(int fd, void* arg) { } struct ETCP_LINK* link = etcp_link_new(conn, e_sock, &addr, 1); if (!link) { if (new_conn) etcp_connection_close(conn); errorcode=66; DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "etcp_connections_read_callback: failed to create link for connection"); goto ec_fr; }// облом - if (ack_hdr->code==0x02) etcp_conn_reset(conn); struct { diff --git a/tests/Makefile.am b/tests/Makefile.am index fd7d47d5..fd0caa3b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -38,8 +38,8 @@ test_etcp_minimal_LDADD = $(top_builddir)/src/utun-etcp.o $(top_builddir)/src/ut # Basic crypto test test_crypto_SOURCES = test_crypto.c -test_crypto_CFLAGS = -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source -I$(top_srcdir)/lib -test_crypto_LDADD = $(top_builddir)/tinycrypt/lib/source/utun-aes_encrypt.o $(top_builddir)/tinycrypt/lib/source/utun-aes_decrypt.o $(top_builddir)/tinycrypt/lib/source/utun-ccm_mode.o $(top_builddir)/tinycrypt/lib/source/utun-cmac_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ctr_mode.o $(top_builddir)/tinycrypt/lib/source/utun-sha256.o $(top_builddir)/tinycrypt/lib/source/utun-utils.o $(top_builddir)/lib/libuasync.a -lpthread -lcrypto +test_crypto_CFLAGS = -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source +test_crypto_LDADD = $(top_builddir)/tinycrypt/lib/source/utun-aes_encrypt.o $(top_builddir)/tinycrypt/lib/source/utun-aes_decrypt.o $(top_builddir)/tinycrypt/lib/source/utun-ccm_mode.o $(top_builddir)/tinycrypt/lib/source/utun-cmac_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ctr_mode.o $(top_builddir)/tinycrypt/lib/source/utun-sha256.o $(top_builddir)/tinycrypt/lib/source/utun-utils.o -lpthread -lcrypto # New comprehensive ll_queue test with current API test_ll_queue_SOURCES = test_ll_queue.c @@ -48,7 +48,7 @@ test_ll_queue_LDADD = $(top_builddir)/lib/libuasync.a -lpthread -lcrypto # ECC encryption test test_ecc_encrypt_SOURCES = test_ecc_encrypt.c -test_ecc_encrypt_CFLAGS = -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source -I$(top_srcdir)/lib +test_ecc_encrypt_CFLAGS = -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source test_ecc_encrypt_LDADD = $(top_builddir)/src/utun-secure_channel.o $(top_builddir)/src/utun-crc32.o $(top_builddir)/tinycrypt/lib/source/utun-aes_encrypt.o $(top_builddir)/tinycrypt/lib/source/utun-aes_decrypt.o $(top_builddir)/tinycrypt/lib/source/utun-ccm_mode.o $(top_builddir)/tinycrypt/lib/source/utun-cmac_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ctr_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ecc.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dh.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dsa.o $(top_builddir)/tinycrypt/lib/source/utun-sha256.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_platform_specific.o $(top_builddir)/tinycrypt/lib/source/utun-utils.o $(top_builddir)/lib/libuasync.a -lpthread -lcrypto # Intensive memory pool test diff --git a/tests/debug_full_test.c b/tests/debug_full_test.c index 42ddd471..456f8f53 100644 --- a/tests/debug_full_test.c +++ b/tests/debug_full_test.c @@ -1,6 +1,5 @@ // Copy the original test file but add debugging #include -#include "../lib/debug_config.h" #include #include #include @@ -11,225 +10,225 @@ #include #include -#include "../lib/u_async.h" -#include "../lib/timeout_heap.h" +#include "u_async.h" +#include "timeout_heap.h" /* Test statistics */ static struct { -int tests_run; -int tests_passed; -int tests_failed; - -/* Timer statistics */ -int timer_callbacks; -int timer_cancellations; -int immediate_timeouts; - -/* Socket statistics */ -int socket_events; -int socket_errors; - -/* Error statistics */ -int memory_allocation_errors; -int invalid_parameter_errors; -int race_condition_errors; + int tests_run; + int tests_passed; + int tests_failed; + + /* Timer statistics */ + int timer_callbacks; + int timer_cancellations; + int immediate_timeouts; + + /* Socket statistics */ + int socket_events; + int socket_errors; + + /* Error statistics */ + int memory_allocation_errors; + int invalid_parameter_errors; + int race_condition_errors; } test_stats = {0}; /* Test result tracking */ #define TEST_START(name) do { \ -DEBUG_INFO(DEBUG_CATEGORY_ALL, "TEST: %s... ", name); \ -DEBUG_INFO(DEBUG_CATEGORY_ALL, "immediate_timeouts before: %d", test_stats.immediate_timeouts); \ -test_stats.tests_run++; \ + printf("TEST: %s... \n", name); \ + printf(" immediate_timeouts before: %d\n", test_stats.immediate_timeouts); \ + test_stats.tests_run++; \ } while(0) #define TEST_PASS() do { \ -DEBUG_INFO(DEBUG_CATEGORY_ALL, "immediate_timeouts after: %d", test_stats.immediate_timeouts); \ -DEBUG_INFO(DEBUG_CATEGORY_ALL, "PASS"); \ -test_stats.tests_passed++; \ + printf(" immediate_timeouts after: %d\n", test_stats.immediate_timeouts); \ + printf("PASS\n"); \ + test_stats.tests_passed++; \ } while(0) #define TEST_FAIL(msg) do { \ -DEBUG_INFO(DEBUG_CATEGORY_ALL, "immediate_timeouts after: %d", test_stats.immediate_timeouts); \ -DEBUG_INFO(DEBUG_CATEGORY_ALL, "FAIL: %s", msg); \ -test_stats.tests_failed++; \ + printf(" immediate_timeouts after: %d\n", test_stats.immediate_timeouts); \ + printf("FAIL: %s\n", msg); \ + test_stats.tests_failed++; \ } while(0) #define ASSERT_EQ(a, b, msg) do { \ -if ((a) != (b)) { \ -TEST_FAIL(msg); \ -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Expected: %ld, Got: %ld", (long)(b), (long)(a)); \ -return; \ -} \ + if ((a) != (b)) { \ + TEST_FAIL(msg); \ + printf(" Expected: %ld, Got: %ld\n", (long)(b), (long)(a)); \ + return; \ + } \ } while(0) #define ASSERT_NOT_NULL(ptr, msg) do { \ -if ((ptr) == NULL) { \ -TEST_FAIL(msg); \ -return; \ -} \ + if ((ptr) == NULL) { \ + TEST_FAIL(msg); \ + return; \ + } \ } while(0) /* Test context for callbacks */ typedef struct { -int callback_count; -int expected_count; -int callback_arg; -int timeout_ms; -uasync_t* ua; -void* timer_id; + int callback_count; + int expected_count; + int callback_arg; + int timeout_ms; + uasync_t* ua; + void* timer_id; } test_context_t; /* Timer callback for testing */ static void test_timer_callback(void* arg) { -test_context_t* ctx = (test_context_t*)arg; -ctx->callback_count++; -test_stats.timer_callbacks++; - -if (ctx->timeout_ms == 0) { -test_stats.immediate_timeouts++; -DEBUG_INFO(DEBUG_CATEGORY_ALL, "IMMEDIATE TIMEOUT: immediate_timeouts now = %d", test_stats.immediate_timeouts); -} + test_context_t* ctx = (test_context_t*)arg; + ctx->callback_count++; + test_stats.timer_callbacks++; + + if (ctx->timeout_ms == 0) { + test_stats.immediate_timeouts++; + printf(" IMMEDIATE TIMEOUT: immediate_timeouts now = %d\n", test_stats.immediate_timeouts); + } } /* Test 1: Basic timer functionality */ static void test_basic_timers(void) { -TEST_START("Basic timer functionality"); - -uasync_t* ua = uasync_create(); -ASSERT_NOT_NULL(ua, "Failed to create uasync instance"); - -test_context_t ctx = {0}; -ctx.expected_count = 3; -ctx.timeout_ms = 10; // Non-zero to avoid immediate timeout counting - -/* Set multiple timers with different timeouts */ -void* timer1 = uasync_set_timeout(ua, 10, &ctx, test_timer_callback); /* 1ms */ -void* timer2 = uasync_set_timeout(ua, 20, &ctx, test_timer_callback); /* 2ms */ -void* timer3 = uasync_set_timeout(ua, 30, &ctx, test_timer_callback); /* 3ms */ - -ASSERT_NOT_NULL(timer1, "Failed to set timer 1"); -ASSERT_NOT_NULL(timer2, "Failed to set timer 2"); -ASSERT_NOT_NULL(timer3, "Failed to set timer 3"); - -/* Poll and verify timers fire in order */ -int poll_count = 0; -while (ctx.callback_count < ctx.expected_count && poll_count < 100) { -uasync_poll(ua, 10); /* 1ms poll */ -poll_count++; -} - -ASSERT_EQ(ctx.callback_count, ctx.expected_count, "Not all timers fired"); - -/* Cleanup */ -uasync_destroy(ua, 0); -TEST_PASS(); + TEST_START("Basic timer functionality"); + + uasync_t* ua = uasync_create(); + ASSERT_NOT_NULL(ua, "Failed to create uasync instance"); + + test_context_t ctx = {0}; + ctx.expected_count = 3; + ctx.timeout_ms = 10; // Non-zero to avoid immediate timeout counting + + /* Set multiple timers with different timeouts */ + void* timer1 = uasync_set_timeout(ua, 10, &ctx, test_timer_callback); /* 1ms */ + void* timer2 = uasync_set_timeout(ua, 20, &ctx, test_timer_callback); /* 2ms */ + void* timer3 = uasync_set_timeout(ua, 30, &ctx, test_timer_callback); /* 3ms */ + + ASSERT_NOT_NULL(timer1, "Failed to set timer 1"); + ASSERT_NOT_NULL(timer2, "Failed to set timer 2"); + ASSERT_NOT_NULL(timer3, "Failed to set timer 3"); + + /* Poll and verify timers fire in order */ + int poll_count = 0; + while (ctx.callback_count < ctx.expected_count && poll_count < 100) { + uasync_poll(ua, 10); /* 1ms poll */ + poll_count++; + } + + ASSERT_EQ(ctx.callback_count, ctx.expected_count, "Not all timers fired"); + + /* Cleanup */ + uasync_destroy(ua, 0); + TEST_PASS(); } /* Test 2: Timer cancellation race conditions */ static void test_timer_cancellation_races(void) { -TEST_START("Timer cancellation race conditions"); - -uasync_t* ua = uasync_create(); -ASSERT_NOT_NULL(ua, "Failed to create uasync instance"); - -test_context_t ctx = {0}; -ctx.expected_count = 2; -ctx.timeout_ms = 5; // Non-zero to avoid immediate timeout counting - -/* Create timers that will be cancelled at different stages */ -void* timer1 = uasync_set_timeout(ua, 5, &ctx, test_timer_callback); /* 0.5ms */ -void* timer2 = uasync_set_timeout(ua, 50, &ctx, test_timer_callback); /* 5ms */ -void* timer3 = uasync_set_timeout(ua, 100, &ctx, test_timer_callback); /* 10ms */ - -ASSERT_NOT_NULL(timer1, "Failed to set timer 1"); -ASSERT_NOT_NULL(timer2, "Failed to set timer 2"); -ASSERT_NOT_NULL(timer3, "Failed to set timer 3"); - -/* Cancel timer1 immediately (before it fires) */ -err_t cancel_result = uasync_cancel_timeout(ua, timer1); -ASSERT_EQ(cancel_result, ERR_OK, "Failed to cancel timer 1"); -test_stats.timer_cancellations++; - -/* Poll briefly - timer1 should not fire, others should */ -uasync_poll(ua, 10); /* 1ms */ - -/* Cancel timer2 while it might be firing */ -cancel_result = uasync_cancel_timeout(ua, timer2); -/* Result could be ERR_OK or ERR_FAIL depending on timing */ - -/* Continue polling */ -int poll_count = 0; -while (ctx.callback_count < 2 && poll_count < 50) { -uasync_poll(ua, 10); -poll_count++; -} - -/* Verify we got expected callbacks (timer3 + possibly timer2) */ -if (ctx.callback_count < 1 || ctx.callback_count > 2) { -TEST_FAIL("Wrong number of timers fired"); -return; -} - -/* Cleanup remaining timer */ -if (timer3) { -uasync_cancel_timeout(ua, timer3); -timer3 = NULL; -} - -uasync_destroy(ua, 0); -TEST_PASS(); + TEST_START("Timer cancellation race conditions"); + + uasync_t* ua = uasync_create(); + ASSERT_NOT_NULL(ua, "Failed to create uasync instance"); + + test_context_t ctx = {0}; + ctx.expected_count = 2; + ctx.timeout_ms = 5; // Non-zero to avoid immediate timeout counting + + /* Create timers that will be cancelled at different stages */ + void* timer1 = uasync_set_timeout(ua, 5, &ctx, test_timer_callback); /* 0.5ms */ + void* timer2 = uasync_set_timeout(ua, 50, &ctx, test_timer_callback); /* 5ms */ + void* timer3 = uasync_set_timeout(ua, 100, &ctx, test_timer_callback); /* 10ms */ + + ASSERT_NOT_NULL(timer1, "Failed to set timer 1"); + ASSERT_NOT_NULL(timer2, "Failed to set timer 2"); + ASSERT_NOT_NULL(timer3, "Failed to set timer 3"); + + /* Cancel timer1 immediately (before it fires) */ + err_t cancel_result = uasync_cancel_timeout(ua, timer1); + ASSERT_EQ(cancel_result, ERR_OK, "Failed to cancel timer 1"); + test_stats.timer_cancellations++; + + /* Poll briefly - timer1 should not fire, others should */ + uasync_poll(ua, 10); /* 1ms */ + + /* Cancel timer2 while it might be firing */ + cancel_result = uasync_cancel_timeout(ua, timer2); + /* Result could be ERR_OK or ERR_FAIL depending on timing */ + + /* Continue polling */ + int poll_count = 0; + while (ctx.callback_count < 2 && poll_count < 50) { + uasync_poll(ua, 10); + poll_count++; + } + + /* Verify we got expected callbacks (timer3 + possibly timer2) */ + if (ctx.callback_count < 1 || ctx.callback_count > 2) { + TEST_FAIL("Wrong number of timers fired"); + return; + } + + /* Cleanup remaining timer */ + if (timer3) { + uasync_cancel_timeout(ua, timer3); + timer3 = NULL; + } + + uasync_destroy(ua, 0); + TEST_PASS(); } /* Test 3: Immediate timeout handling */ static void test_immediate_timeouts(void) { -TEST_START("Immediate timeout handling"); - -uasync_t* ua = uasync_create(); -ASSERT_NOT_NULL(ua, "Failed to create uasync instance"); - -test_context_t ctx = {0}; -ctx.expected_count = 5; -ctx.timeout_ms = 0; // This should trigger immediate timeout counting - -/* Set multiple immediate timeouts (0ms) */ -for (int i = 0; i < 5; i++) { -void* timer = uasync_set_timeout(ua, 0, &ctx, test_timer_callback); -ASSERT_NOT_NULL(timer, "Failed to set immediate timer"); -} - -/* Immediate timeouts should fire during next poll */ -ASSERT_EQ(ctx.callback_count, 0, "Callbacks fired too early"); - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "About to call uasync_poll, immediate_timeouts = %d", test_stats.immediate_timeouts); -uasync_poll(ua, 1); /* Minimal poll */ -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After uasync_poll, immediate_timeouts = %d", test_stats.immediate_timeouts); - -ASSERT_EQ(ctx.callback_count, ctx.expected_count, "Immediate timeouts didn't fire correctly"); -ASSERT_EQ(test_stats.immediate_timeouts, 5, "Immediate timeout counter incorrect"); - -uasync_destroy(ua, 0); -TEST_PASS(); + TEST_START("Immediate timeout handling"); + + uasync_t* ua = uasync_create(); + ASSERT_NOT_NULL(ua, "Failed to create uasync instance"); + + test_context_t ctx = {0}; + ctx.expected_count = 5; + ctx.timeout_ms = 0; // This should trigger immediate timeout counting + + /* Set multiple immediate timeouts (0ms) */ + for (int i = 0; i < 5; i++) { + void* timer = uasync_set_timeout(ua, 0, &ctx, test_timer_callback); + ASSERT_NOT_NULL(timer, "Failed to set immediate timer"); + } + + /* Immediate timeouts should fire during next poll */ + ASSERT_EQ(ctx.callback_count, 0, "Callbacks fired too early"); + + printf(" About to call uasync_poll, immediate_timeouts = %d\n", test_stats.immediate_timeouts); + uasync_poll(ua, 1); /* Minimal poll */ + printf(" After uasync_poll, immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + ASSERT_EQ(ctx.callback_count, ctx.expected_count, "Immediate timeouts didn't fire correctly"); + ASSERT_EQ(test_stats.immediate_timeouts, 5, "Immediate timeout counter incorrect"); + + uasync_destroy(ua, 0); + TEST_PASS(); } int main(void) { -DEBUG_INFO(DEBUG_CATEGORY_ALL, "=== lib Comprehensive Unit Tests ==="); -DEBUG_ERROR(DEBUG_CATEGORY_ALL, "Testing race conditions, memory management, and error handling\n"); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Initial immediate_timeouts: %d", test_stats.immediate_timeouts); - -/* Run all tests */ -test_basic_timers(); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After basic_timers: immediate_timeouts = %d", test_stats.immediate_timeouts); - -test_timer_cancellation_races(); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After timer_cancellation_races: immediate_timeouts = %d", test_stats.immediate_timeouts); - -test_immediate_timeouts(); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After immediate_timeouts: immediate_timeouts = %d", test_stats.immediate_timeouts); - -/* Print final statistics */ -DEBUG_INFO(DEBUG_CATEGORY_ALL, "\n=== Final Statistics ==="); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Timer callbacks: %d", test_stats.timer_callbacks); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Immediate timeouts: %d", test_stats.immediate_timeouts); - -return (test_stats.tests_failed > 0) ? 1 : 0; + printf("=== lib Comprehensive Unit Tests ===\n"); + printf("Testing race conditions, memory management, and error handling\n\n"); + printf("Initial immediate_timeouts: %d\n", test_stats.immediate_timeouts); + + /* Run all tests */ + test_basic_timers(); + printf("After basic_timers: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + test_timer_cancellation_races(); + printf("After timer_cancellation_races: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + test_immediate_timeouts(); + printf("After immediate_timeouts: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + /* Print final statistics */ + printf("\n=== Final Statistics ===\n"); + printf("Timer callbacks: %d\n", test_stats.timer_callbacks); + printf("Immediate timeouts: %d\n", test_stats.immediate_timeouts); + + return (test_stats.tests_failed > 0) ? 1 : 0; } diff --git a/tests/debug_full_test.c.backup b/tests/debug_full_test.c.backup deleted file mode 100644 index 456f8f53..00000000 --- a/tests/debug_full_test.c.backup +++ /dev/null @@ -1,234 +0,0 @@ -// Copy the original test file but add debugging -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "u_async.h" -#include "timeout_heap.h" - -/* Test statistics */ -static struct { - int tests_run; - int tests_passed; - int tests_failed; - - /* Timer statistics */ - int timer_callbacks; - int timer_cancellations; - int immediate_timeouts; - - /* Socket statistics */ - int socket_events; - int socket_errors; - - /* Error statistics */ - int memory_allocation_errors; - int invalid_parameter_errors; - int race_condition_errors; -} test_stats = {0}; - -/* Test result tracking */ -#define TEST_START(name) do { \ - printf("TEST: %s... \n", name); \ - printf(" immediate_timeouts before: %d\n", test_stats.immediate_timeouts); \ - test_stats.tests_run++; \ -} while(0) - -#define TEST_PASS() do { \ - printf(" immediate_timeouts after: %d\n", test_stats.immediate_timeouts); \ - printf("PASS\n"); \ - test_stats.tests_passed++; \ -} while(0) - -#define TEST_FAIL(msg) do { \ - printf(" immediate_timeouts after: %d\n", test_stats.immediate_timeouts); \ - printf("FAIL: %s\n", msg); \ - test_stats.tests_failed++; \ -} while(0) - -#define ASSERT_EQ(a, b, msg) do { \ - if ((a) != (b)) { \ - TEST_FAIL(msg); \ - printf(" Expected: %ld, Got: %ld\n", (long)(b), (long)(a)); \ - return; \ - } \ -} while(0) - -#define ASSERT_NOT_NULL(ptr, msg) do { \ - if ((ptr) == NULL) { \ - TEST_FAIL(msg); \ - return; \ - } \ -} while(0) - -/* Test context for callbacks */ -typedef struct { - int callback_count; - int expected_count; - int callback_arg; - int timeout_ms; - uasync_t* ua; - void* timer_id; -} test_context_t; - -/* Timer callback for testing */ -static void test_timer_callback(void* arg) { - test_context_t* ctx = (test_context_t*)arg; - ctx->callback_count++; - test_stats.timer_callbacks++; - - if (ctx->timeout_ms == 0) { - test_stats.immediate_timeouts++; - printf(" IMMEDIATE TIMEOUT: immediate_timeouts now = %d\n", test_stats.immediate_timeouts); - } -} - -/* Test 1: Basic timer functionality */ -static void test_basic_timers(void) { - TEST_START("Basic timer functionality"); - - uasync_t* ua = uasync_create(); - ASSERT_NOT_NULL(ua, "Failed to create uasync instance"); - - test_context_t ctx = {0}; - ctx.expected_count = 3; - ctx.timeout_ms = 10; // Non-zero to avoid immediate timeout counting - - /* Set multiple timers with different timeouts */ - void* timer1 = uasync_set_timeout(ua, 10, &ctx, test_timer_callback); /* 1ms */ - void* timer2 = uasync_set_timeout(ua, 20, &ctx, test_timer_callback); /* 2ms */ - void* timer3 = uasync_set_timeout(ua, 30, &ctx, test_timer_callback); /* 3ms */ - - ASSERT_NOT_NULL(timer1, "Failed to set timer 1"); - ASSERT_NOT_NULL(timer2, "Failed to set timer 2"); - ASSERT_NOT_NULL(timer3, "Failed to set timer 3"); - - /* Poll and verify timers fire in order */ - int poll_count = 0; - while (ctx.callback_count < ctx.expected_count && poll_count < 100) { - uasync_poll(ua, 10); /* 1ms poll */ - poll_count++; - } - - ASSERT_EQ(ctx.callback_count, ctx.expected_count, "Not all timers fired"); - - /* Cleanup */ - uasync_destroy(ua, 0); - TEST_PASS(); -} - -/* Test 2: Timer cancellation race conditions */ -static void test_timer_cancellation_races(void) { - TEST_START("Timer cancellation race conditions"); - - uasync_t* ua = uasync_create(); - ASSERT_NOT_NULL(ua, "Failed to create uasync instance"); - - test_context_t ctx = {0}; - ctx.expected_count = 2; - ctx.timeout_ms = 5; // Non-zero to avoid immediate timeout counting - - /* Create timers that will be cancelled at different stages */ - void* timer1 = uasync_set_timeout(ua, 5, &ctx, test_timer_callback); /* 0.5ms */ - void* timer2 = uasync_set_timeout(ua, 50, &ctx, test_timer_callback); /* 5ms */ - void* timer3 = uasync_set_timeout(ua, 100, &ctx, test_timer_callback); /* 10ms */ - - ASSERT_NOT_NULL(timer1, "Failed to set timer 1"); - ASSERT_NOT_NULL(timer2, "Failed to set timer 2"); - ASSERT_NOT_NULL(timer3, "Failed to set timer 3"); - - /* Cancel timer1 immediately (before it fires) */ - err_t cancel_result = uasync_cancel_timeout(ua, timer1); - ASSERT_EQ(cancel_result, ERR_OK, "Failed to cancel timer 1"); - test_stats.timer_cancellations++; - - /* Poll briefly - timer1 should not fire, others should */ - uasync_poll(ua, 10); /* 1ms */ - - /* Cancel timer2 while it might be firing */ - cancel_result = uasync_cancel_timeout(ua, timer2); - /* Result could be ERR_OK or ERR_FAIL depending on timing */ - - /* Continue polling */ - int poll_count = 0; - while (ctx.callback_count < 2 && poll_count < 50) { - uasync_poll(ua, 10); - poll_count++; - } - - /* Verify we got expected callbacks (timer3 + possibly timer2) */ - if (ctx.callback_count < 1 || ctx.callback_count > 2) { - TEST_FAIL("Wrong number of timers fired"); - return; - } - - /* Cleanup remaining timer */ - if (timer3) { - uasync_cancel_timeout(ua, timer3); - timer3 = NULL; - } - - uasync_destroy(ua, 0); - TEST_PASS(); -} - -/* Test 3: Immediate timeout handling */ -static void test_immediate_timeouts(void) { - TEST_START("Immediate timeout handling"); - - uasync_t* ua = uasync_create(); - ASSERT_NOT_NULL(ua, "Failed to create uasync instance"); - - test_context_t ctx = {0}; - ctx.expected_count = 5; - ctx.timeout_ms = 0; // This should trigger immediate timeout counting - - /* Set multiple immediate timeouts (0ms) */ - for (int i = 0; i < 5; i++) { - void* timer = uasync_set_timeout(ua, 0, &ctx, test_timer_callback); - ASSERT_NOT_NULL(timer, "Failed to set immediate timer"); - } - - /* Immediate timeouts should fire during next poll */ - ASSERT_EQ(ctx.callback_count, 0, "Callbacks fired too early"); - - printf(" About to call uasync_poll, immediate_timeouts = %d\n", test_stats.immediate_timeouts); - uasync_poll(ua, 1); /* Minimal poll */ - printf(" After uasync_poll, immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - ASSERT_EQ(ctx.callback_count, ctx.expected_count, "Immediate timeouts didn't fire correctly"); - ASSERT_EQ(test_stats.immediate_timeouts, 5, "Immediate timeout counter incorrect"); - - uasync_destroy(ua, 0); - TEST_PASS(); -} - -int main(void) { - printf("=== lib Comprehensive Unit Tests ===\n"); - printf("Testing race conditions, memory management, and error handling\n\n"); - printf("Initial immediate_timeouts: %d\n", test_stats.immediate_timeouts); - - /* Run all tests */ - test_basic_timers(); - printf("After basic_timers: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - test_timer_cancellation_races(); - printf("After timer_cancellation_races: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - test_immediate_timeouts(); - printf("After immediate_timeouts: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - /* Print final statistics */ - printf("\n=== Final Statistics ===\n"); - printf("Timer callbacks: %d\n", test_stats.timer_callbacks); - printf("Immediate timeouts: %d\n", test_stats.immediate_timeouts); - - return (test_stats.tests_failed > 0) ? 1 : 0; -} diff --git a/tests/debug_performance.c b/tests/debug_performance.c index 52faf560..8c6c7001 100644 --- a/tests/debug_performance.c +++ b/tests/debug_performance.c @@ -1,5 +1,4 @@ #include "../lib/u_async.h" -#include "../lib/debug_config.h" #include #include #include @@ -7,46 +6,42 @@ #include static void test_callback(int fd, void* arg) { -(void)fd; (void)arg; + (void)fd; (void)arg; } int main() { - -debug_config_init(); -debug_set_level(DEBUG_LEVEL_TRACE); -debug_set_categories(DEBUG_CATEGORY_ALL); -uasync_t* ua = uasync_create(); -if (!ua) return 1; - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "=== Debug Performance Test ==="); - -// Test 1: Normal add/remove -int sock1 = socket(AF_INET, SOCK_DGRAM, 0); -void* id1 = uasync_add_socket(ua, sock1, test_callback, NULL, NULL, NULL); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Added socket %d: id=%p", sock1, id1); - -size_t alloc1, free1, alloc2, free2; -uasync_get_stats(ua, &alloc1, &free1, &alloc2, &free2); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After add: timers %zu/%zu, sockets %zu/%zu", alloc1, free1, alloc2, free2); - -uasync_remove_socket(ua, id1); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Removed socket %d", sock1); - -uasync_get_stats(ua, &alloc1, &free1, &alloc2, &free2); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After remove: timers %zu/%zu, sockets %zu/%zu", alloc1, free1, alloc2, free2); - -close(sock1); - -// Test 2: Failed add -int sock2 = 9999; // Invalid socket -void* id2 = uasync_add_socket(ua, sock2, test_callback, NULL, NULL, NULL); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Tried to add invalid socket %d: id=%p", sock2, id2); - -uasync_get_stats(ua, &alloc1, &free1, &alloc2, &free2); -DEBUG_ERROR(DEBUG_CATEGORY_ALL, "After failed add: timers %zu/%zu, sockets %zu/%zu", alloc1, free1, alloc2, free2); - -uasync_destroy(ua, 0); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Destroyed uasync"); - -return 0; + uasync_t* ua = uasync_create(); + if (!ua) return 1; + + printf("=== Debug Performance Test ===\n"); + + // Test 1: Normal add/remove + int sock1 = socket(AF_INET, SOCK_DGRAM, 0); + void* id1 = uasync_add_socket(ua, sock1, test_callback, NULL, NULL, NULL); + printf("Added socket %d: id=%p\n", sock1, id1); + + size_t alloc1, free1, alloc2, free2; + uasync_get_stats(ua, &alloc1, &free1, &alloc2, &free2); + printf("After add: timers %zu/%zu, sockets %zu/%zu\n", alloc1, free1, alloc2, free2); + + uasync_remove_socket(ua, id1); + printf("Removed socket %d\n", sock1); + + uasync_get_stats(ua, &alloc1, &free1, &alloc2, &free2); + printf("After remove: timers %zu/%zu, sockets %zu/%zu\n", alloc1, free1, alloc2, free2); + + close(sock1); + + // Test 2: Failed add + int sock2 = 9999; // Invalid socket + void* id2 = uasync_add_socket(ua, sock2, test_callback, NULL, NULL, NULL); + printf("Tried to add invalid socket %d: id=%p\n", sock2, id2); + + uasync_get_stats(ua, &alloc1, &free1, &alloc2, &free2); + printf("After failed add: timers %zu/%zu, sockets %zu/%zu\n", alloc1, free1, alloc2, free2); + + uasync_destroy(ua, 0); + printf("Destroyed uasync\n"); + + return 0; } diff --git a/tests/debug_performance.c.backup b/tests/debug_performance.c.backup deleted file mode 100644 index 8c6c7001..00000000 --- a/tests/debug_performance.c.backup +++ /dev/null @@ -1,47 +0,0 @@ -#include "../lib/u_async.h" -#include -#include -#include -#include -#include - -static void test_callback(int fd, void* arg) { - (void)fd; (void)arg; -} - -int main() { - uasync_t* ua = uasync_create(); - if (!ua) return 1; - - printf("=== Debug Performance Test ===\n"); - - // Test 1: Normal add/remove - int sock1 = socket(AF_INET, SOCK_DGRAM, 0); - void* id1 = uasync_add_socket(ua, sock1, test_callback, NULL, NULL, NULL); - printf("Added socket %d: id=%p\n", sock1, id1); - - size_t alloc1, free1, alloc2, free2; - uasync_get_stats(ua, &alloc1, &free1, &alloc2, &free2); - printf("After add: timers %zu/%zu, sockets %zu/%zu\n", alloc1, free1, alloc2, free2); - - uasync_remove_socket(ua, id1); - printf("Removed socket %d\n", sock1); - - uasync_get_stats(ua, &alloc1, &free1, &alloc2, &free2); - printf("After remove: timers %zu/%zu, sockets %zu/%zu\n", alloc1, free1, alloc2, free2); - - close(sock1); - - // Test 2: Failed add - int sock2 = 9999; // Invalid socket - void* id2 = uasync_add_socket(ua, sock2, test_callback, NULL, NULL, NULL); - printf("Tried to add invalid socket %d: id=%p\n", sock2, id2); - - uasync_get_stats(ua, &alloc1, &free1, &alloc2, &free2); - printf("After failed add: timers %zu/%zu, sockets %zu/%zu\n", alloc1, free1, alloc2, free2); - - uasync_destroy(ua, 0); - printf("Destroyed uasync\n"); - - return 0; -} diff --git a/tests/detailed_test.c b/tests/detailed_test.c index 15d9e4f9..f4835552 100644 --- a/tests/detailed_test.c +++ b/tests/detailed_test.c @@ -1,91 +1,86 @@ #include "u_async.h" -#include "../lib/debug_config.h" #include /* Test statistics */ static struct { -int timer_callbacks; -int immediate_timeouts; + int timer_callbacks; + int immediate_timeouts; } test_stats = {0}; typedef struct { -int callback_count; -int timeout_ms; + int callback_count; + int timeout_ms; } test_context_t; /* Timer callback for testing */ static void test_timer_callback(void* arg) { -test_context_t* ctx = (test_context_t*)arg; -ctx->callback_count++; -test_stats.timer_callbacks++; - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Callback fired: ctx->timeout_ms=%d, immediate_timeouts before=%d", ctx->timeout_ms, test_stats.immediate_timeouts); - -if (ctx->timeout_ms == 0) { -test_stats.immediate_timeouts++; -DEBUG_INFO(DEBUG_CATEGORY_ALL, "-> INCREMENTED to %d", test_stats.immediate_timeouts); -} else { -DEBUG_INFO(DEBUG_CATEGORY_ALL, "-> NOT incremented"); -} + test_context_t* ctx = (test_context_t*)arg; + ctx->callback_count++; + test_stats.timer_callbacks++; + + printf("Callback fired: ctx->timeout_ms=%d, immediate_timeouts before=%d", ctx->timeout_ms, test_stats.immediate_timeouts); + + if (ctx->timeout_ms == 0) { + test_stats.immediate_timeouts++; + printf(" -> INCREMENTED to %d\n", test_stats.immediate_timeouts); + } else { + printf(" -> NOT incremented\n"); + } } int main() { - -debug_config_init(); -debug_set_level(DEBUG_LEVEL_TRACE); -debug_set_categories(DEBUG_CATEGORY_ALL); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "=== Test 1: Basic timers (non-zero timeouts) ==="); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Before test 1: immediate_timeouts = %d", test_stats.immediate_timeouts); - -uasync_t* ua1 = uasync_create(); -test_context_t ctx1 = {.timeout_ms = 10}; - -for (int i = 0; i < 3; i++) { -uasync_set_timeout(ua1, 10 + i*10, &ctx1, test_timer_callback); -} - -int polls = 0; -while (ctx1.callback_count < 3 && polls < 10) { -uasync_poll(ua1, 10); -polls++; -} - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After test 1: immediate_timeouts = %d", test_stats.immediate_timeouts); -uasync_destroy(ua1); - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "\n=== Test 2: Immediate timeouts (zero timeouts) ==="); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Before test 2: immediate_timeouts = %d", test_stats.immediate_timeouts); - -uasync_t* ua2 = uasync_create(); -test_context_t ctx2 = {.timeout_ms = 0}; - -for (int i = 0; i < 5; i++) { -uasync_set_timeout(ua2, 0, &ctx2, test_timer_callback); -} - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Before poll: ctx2.callback_count = %d, immediate_timeouts = %d", ctx2.callback_count, test_stats.immediate_timeouts); - -uasync_poll(ua2, 1); - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After poll: ctx2.callback_count = %d, immediate_timeouts = %d", ctx2.callback_count, test_stats.immediate_timeouts); - -uasync_destroy(ua2); - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "\n=== Test 3: Another immediate timeout test ==="); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Before test 3: immediate_timeouts = %d", test_stats.immediate_timeouts); - -uasync_t* ua3 = uasync_create(); -test_context_t ctx3 = {.timeout_ms = 0}; - -for (int i = 0; i < 2; i++) { -uasync_set_timeout(ua3, 0, &ctx3, test_timer_callback); -} - -uasync_poll(ua3, 1); - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After test 3: immediate_timeouts = %d", test_stats.immediate_timeouts); - -uasync_destroy(ua3); - -return 0; + printf("=== Test 1: Basic timers (non-zero timeouts) ===\n"); + printf("Before test 1: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + uasync_t* ua1 = uasync_create(); + test_context_t ctx1 = {.timeout_ms = 10}; + + for (int i = 0; i < 3; i++) { + uasync_set_timeout(ua1, 10 + i*10, &ctx1, test_timer_callback); + } + + int polls = 0; + while (ctx1.callback_count < 3 && polls < 10) { + uasync_poll(ua1, 10); + polls++; + } + + printf("After test 1: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + uasync_destroy(ua1); + + printf("\n=== Test 2: Immediate timeouts (zero timeouts) ===\n"); + printf("Before test 2: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + uasync_t* ua2 = uasync_create(); + test_context_t ctx2 = {.timeout_ms = 0}; + + for (int i = 0; i < 5; i++) { + uasync_set_timeout(ua2, 0, &ctx2, test_timer_callback); + } + + printf("Before poll: ctx2.callback_count = %d, immediate_timeouts = %d\n", ctx2.callback_count, test_stats.immediate_timeouts); + + uasync_poll(ua2, 1); + + printf("After poll: ctx2.callback_count = %d, immediate_timeouts = %d\n", ctx2.callback_count, test_stats.immediate_timeouts); + + uasync_destroy(ua2); + + printf("\n=== Test 3: Another immediate timeout test ===\n"); + printf("Before test 3: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + uasync_t* ua3 = uasync_create(); + test_context_t ctx3 = {.timeout_ms = 0}; + + for (int i = 0; i < 2; i++) { + uasync_set_timeout(ua3, 0, &ctx3, test_timer_callback); + } + + uasync_poll(ua3, 1); + + printf("After test 3: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + uasync_destroy(ua3); + + return 0; } diff --git a/tests/detailed_test.c.backup b/tests/detailed_test.c.backup deleted file mode 100644 index f4835552..00000000 --- a/tests/detailed_test.c.backup +++ /dev/null @@ -1,86 +0,0 @@ -#include "u_async.h" -#include - -/* Test statistics */ -static struct { - int timer_callbacks; - int immediate_timeouts; -} test_stats = {0}; - -typedef struct { - int callback_count; - int timeout_ms; -} test_context_t; - -/* Timer callback for testing */ -static void test_timer_callback(void* arg) { - test_context_t* ctx = (test_context_t*)arg; - ctx->callback_count++; - test_stats.timer_callbacks++; - - printf("Callback fired: ctx->timeout_ms=%d, immediate_timeouts before=%d", ctx->timeout_ms, test_stats.immediate_timeouts); - - if (ctx->timeout_ms == 0) { - test_stats.immediate_timeouts++; - printf(" -> INCREMENTED to %d\n", test_stats.immediate_timeouts); - } else { - printf(" -> NOT incremented\n"); - } -} - -int main() { - printf("=== Test 1: Basic timers (non-zero timeouts) ===\n"); - printf("Before test 1: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - uasync_t* ua1 = uasync_create(); - test_context_t ctx1 = {.timeout_ms = 10}; - - for (int i = 0; i < 3; i++) { - uasync_set_timeout(ua1, 10 + i*10, &ctx1, test_timer_callback); - } - - int polls = 0; - while (ctx1.callback_count < 3 && polls < 10) { - uasync_poll(ua1, 10); - polls++; - } - - printf("After test 1: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - uasync_destroy(ua1); - - printf("\n=== Test 2: Immediate timeouts (zero timeouts) ===\n"); - printf("Before test 2: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - uasync_t* ua2 = uasync_create(); - test_context_t ctx2 = {.timeout_ms = 0}; - - for (int i = 0; i < 5; i++) { - uasync_set_timeout(ua2, 0, &ctx2, test_timer_callback); - } - - printf("Before poll: ctx2.callback_count = %d, immediate_timeouts = %d\n", ctx2.callback_count, test_stats.immediate_timeouts); - - uasync_poll(ua2, 1); - - printf("After poll: ctx2.callback_count = %d, immediate_timeouts = %d\n", ctx2.callback_count, test_stats.immediate_timeouts); - - uasync_destroy(ua2); - - printf("\n=== Test 3: Another immediate timeout test ===\n"); - printf("Before test 3: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - uasync_t* ua3 = uasync_create(); - test_context_t ctx3 = {.timeout_ms = 0}; - - for (int i = 0; i < 2; i++) { - uasync_set_timeout(ua3, 0, &ctx3, test_timer_callback); - } - - uasync_poll(ua3, 1); - - printf("After test 3: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - uasync_destroy(ua3); - - return 0; -} diff --git a/tests/simple_test.c b/tests/simple_test.c index 289b67c6..fd68f787 100644 --- a/tests/simple_test.c +++ b/tests/simple_test.c @@ -1,5 +1,4 @@ #include "../lib/u_async.h" -#include "../lib/debug_config.h" #include #include #include @@ -7,36 +6,32 @@ #include static void test_callback(int fd, void* arg) { -(void)fd; (void)arg; + (void)fd; (void)arg; } int main() { - -debug_config_init(); -debug_set_level(DEBUG_LEVEL_TRACE); -debug_set_categories(DEBUG_CATEGORY_ALL); -uasync_t* ua = uasync_create(); -if (!ua) return 1; - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "=== Simple Corruption Test ==="); - -// Create just one socket -int sock = socket(AF_INET, SOCK_DGRAM, 0); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Created socket with fd=%d", sock); - -void* id = uasync_add_socket(ua, sock, test_callback, NULL, NULL, NULL); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Added socket: fd=%d, id=%p", sock, id); - -// Check if fd is still correct -struct socket_node* node = (struct socket_node*)id; -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Node fd after add: %d", node->fd); - -// Try to remove immediately (no polling) -int result = uasync_remove_socket(ua, id); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Remove result: %d", result); - -close(sock); -uasync_destroy(ua, 0); - -return 0; + uasync_t* ua = uasync_create(); + if (!ua) return 1; + + printf("=== Simple Corruption Test ===\n"); + + // Create just one socket + int sock = socket(AF_INET, SOCK_DGRAM, 0); + printf("Created socket with fd=%d\n", sock); + + void* id = uasync_add_socket(ua, sock, test_callback, NULL, NULL, NULL); + printf("Added socket: fd=%d, id=%p\n", sock, id); + + // Check if fd is still correct + struct socket_node* node = (struct socket_node*)id; + printf("Node fd after add: %d\n", node->fd); + + // Try to remove immediately (no polling) + int result = uasync_remove_socket(ua, id); + printf("Remove result: %d\n", result); + + close(sock); + uasync_destroy(ua, 0); + + return 0; } diff --git a/tests/simple_test.c.backup b/tests/simple_test.c.backup deleted file mode 100644 index fd68f787..00000000 --- a/tests/simple_test.c.backup +++ /dev/null @@ -1,37 +0,0 @@ -#include "../lib/u_async.h" -#include -#include -#include -#include -#include - -static void test_callback(int fd, void* arg) { - (void)fd; (void)arg; -} - -int main() { - uasync_t* ua = uasync_create(); - if (!ua) return 1; - - printf("=== Simple Corruption Test ===\n"); - - // Create just one socket - int sock = socket(AF_INET, SOCK_DGRAM, 0); - printf("Created socket with fd=%d\n", sock); - - void* id = uasync_add_socket(ua, sock, test_callback, NULL, NULL, NULL); - printf("Added socket: fd=%d, id=%p\n", sock, id); - - // Check if fd is still correct - struct socket_node* node = (struct socket_node*)id; - printf("Node fd after add: %d\n", node->fd); - - // Try to remove immediately (no polling) - int result = uasync_remove_socket(ua, id); - printf("Remove result: %d\n", result); - - close(sock); - uasync_destroy(ua, 0); - - return 0; -} diff --git a/tests/test_config_debug b/tests/test_config_debug new file mode 100755 index 0000000000000000000000000000000000000000..a6732f6109f0c83145882101b505965c4af4706e GIT binary patch literal 89936 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 #include @@ -9,51 +9,51 @@ #include "../src/config_parser.h" int main() { -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "=== Тест загрузки debug настроек из конфигурационного файла ==="); - -// Инициализация отладки по умолчанию -debug_config_init(); -debug_set_level(DEBUG_LEVEL_ERROR); // Начальный уровень - -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "\n1. До загрузки конфигурации:"); -DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "ERROR сообщение до загрузки конфигурации"); -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "INFO сообщение до загрузки конфигурации (не должно выводиться)"); - -// Загрузка конфигурации из файла -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "\n2. Загрузка конфигурации из файла: test_config_with_debug.conf"); -struct utun_config *config = parse_config("test_config_with_debug.conf"); - -if (!config) { -DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Ошибка загрузки конфигурации"); -return 1; -} - -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Конфигурация загружена успешно"); -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Log file: %s", config->global.log_file[0] ? config->global.log_file : "(none)"); -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Debug level: %s", config->global.debug_level[0] ? config->global.debug_level : "(none)"); -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Debug categories: 0x%X", config->global.debug_categories); -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Enable timestamp: %d", config->global.enable_timestamp); -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Enable colors: %d", config->global.enable_colors); - -// Тестирование новых настроек -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "\n4. Тестирование после применения настроек:"); -DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "ERROR от ETCP (должен выводиться)"); -DEBUG_INFO(DEBUG_CATEGORY_ETCP, "INFO от ETCP (должен выводиться - уровень debug)"); -DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "DEBUG от ETCP (должен выводиться - уровень debug)"); -DEBUG_INFO(DEBUG_CATEGORY_LL_QUEUE, "INFO от LL_QUEUE (должен выводиться)"); -DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "INFO от MEMORY (должен выводиться)"); -DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "INFO от CONNECTION (НЕ должен выводиться - категория не включена)"); -DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "INFO от CRYPTO (НЕ должен выводиться - категория не включена)"); - -// Проверка работы с файлом -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "\n5. Проверка вывода в файл:"); -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Это сообщение должно быть записано в файл: /tmp/utun_debug.log"); - -// Освобождение ресурсов -free_config(config); - -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "\n=== Тест завершен ==="); -DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Проверьте файл /tmp/utun_debug.log для записанных сообщений"); - -return 0; + printf("=== Тест загрузки debug настроек из конфигурационного файла ===\n"); + + // Инициализация отладки по умолчанию + debug_config_init(); + debug_set_level(DEBUG_LEVEL_ERROR); // Начальный уровень + + printf("\n1. До загрузки конфигурации:\n"); + DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "ERROR сообщение до загрузки конфигурации"); + DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "INFO сообщение до загрузки конфигурации (не должно выводиться)"); + + // Загрузка конфигурации из файла + printf("\n2. Загрузка конфигурации из файла: test_config_with_debug.conf\n"); + struct utun_config *config = parse_config("test_config_with_debug.conf"); + + if (!config) { + printf("❌ Ошибка загрузки конфигурации\n"); + return 1; + } + + printf("✅ Конфигурация загружена успешно\n"); + printf(" Log file: %s\n", config->global.log_file[0] ? config->global.log_file : "(none)"); + printf(" Debug level: %s\n", config->global.debug_level[0] ? config->global.debug_level : "(none)"); + printf(" Debug categories: 0x%X\n", config->global.debug_categories); + printf(" Enable timestamp: %d\n", config->global.enable_timestamp); + printf(" Enable colors: %d\n", config->global.enable_colors); + + // Тестирование новых настроек + printf("\n4. Тестирование после применения настроек:\n"); + DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "ERROR от ETCP (должен выводиться)"); + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "INFO от ETCP (должен выводиться - уровень debug)"); + DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "DEBUG от ETCP (должен выводиться - уровень debug)"); + DEBUG_INFO(DEBUG_CATEGORY_LL_QUEUE, "INFO от LL_QUEUE (должен выводиться)"); + DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "INFO от MEMORY (должен выводиться)"); + DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "INFO от CONNECTION (НЕ должен выводиться - категория не включена)"); + DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "INFO от CRYPTO (НЕ должен выводиться - категория не включена)"); + + // Проверка работы с файлом + printf("\n5. Проверка вывода в файл:\n"); + DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Это сообщение должно быть записано в файл: /tmp/utun_debug.log"); + + // Освобождение ресурсов + free_config(config); + + printf("\n=== Тест завершен ===\n"); + printf("Проверьте файл /tmp/utun_debug.log для записанных сообщений\n"); + + return 0; } \ No newline at end of file diff --git a/tests/test_config_debug.c.backup b/tests/test_config_debug.c.backup deleted file mode 100644 index 1b2c72dc..00000000 --- a/tests/test_config_debug.c.backup +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Тест загрузки debug настроек из конфигурационного файла - */ - -#include -#include -#include -#include "../lib/debug_config.h" -#include "../src/config_parser.h" - -int main() { - printf("=== Тест загрузки debug настроек из конфигурационного файла ===\n"); - - // Инициализация отладки по умолчанию - debug_config_init(); - debug_set_level(DEBUG_LEVEL_ERROR); // Начальный уровень - - printf("\n1. До загрузки конфигурации:\n"); - DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "ERROR сообщение до загрузки конфигурации"); - DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "INFO сообщение до загрузки конфигурации (не должно выводиться)"); - - // Загрузка конфигурации из файла - printf("\n2. Загрузка конфигурации из файла: test_config_with_debug.conf\n"); - struct utun_config *config = parse_config("test_config_with_debug.conf"); - - if (!config) { - printf("❌ Ошибка загрузки конфигурации\n"); - return 1; - } - - printf("✅ Конфигурация загружена успешно\n"); - printf(" Log file: %s\n", config->global.log_file[0] ? config->global.log_file : "(none)"); - printf(" Debug level: %s\n", config->global.debug_level[0] ? config->global.debug_level : "(none)"); - printf(" Debug categories: 0x%X\n", config->global.debug_categories); - printf(" Enable timestamp: %d\n", config->global.enable_timestamp); - printf(" Enable colors: %d\n", config->global.enable_colors); - - // Тестирование новых настроек - printf("\n4. Тестирование после применения настроек:\n"); - DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "ERROR от ETCP (должен выводиться)"); - DEBUG_INFO(DEBUG_CATEGORY_ETCP, "INFO от ETCP (должен выводиться - уровень debug)"); - DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "DEBUG от ETCP (должен выводиться - уровень debug)"); - DEBUG_INFO(DEBUG_CATEGORY_LL_QUEUE, "INFO от LL_QUEUE (должен выводиться)"); - DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "INFO от MEMORY (должен выводиться)"); - DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "INFO от CONNECTION (НЕ должен выводиться - категория не включена)"); - DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "INFO от CRYPTO (НЕ должен выводиться - категория не включена)"); - - // Проверка работы с файлом - printf("\n5. Проверка вывода в файл:\n"); - DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Это сообщение должно быть записано в файл: /tmp/utun_debug.log"); - - // Освобождение ресурсов - free_config(config); - - printf("\n=== Тест завершен ===\n"); - printf("Проверьте файл /tmp/utun_debug.log для записанных сообщений\n"); - - return 0; -} \ No newline at end of file diff --git a/tests/test_crypto b/tests/test_crypto new file mode 100755 index 0000000000000000000000000000000000000000..21c7bbc0cdc396833daad92a701a2f80ba1b60a5 GIT binary patch literal 65936 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 literal 0 HcmV?d00001 diff --git a/tests/test_crypto.c b/tests/test_crypto.c index 47242b9d..bf79ed89 100644 --- a/tests/test_crypto.c +++ b/tests/test_crypto.c @@ -1,5 +1,4 @@ #include -#include "../lib/debug_config.h" #include #include #include @@ -9,59 +8,55 @@ #define SC_SESSION_KEY_SIZE 16 int main() { - -debug_config_init(); -debug_set_level(DEBUG_LEVEL_TRACE); -debug_set_categories(DEBUG_CATEGORY_ALL); -DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "=== Basic Crypto Test ==="); - -struct tc_aes_key_sched_struct sched; -uint8_t test_key[SC_SESSION_KEY_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, -0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10}; - -if (tc_aes128_set_encrypt_key(&sched, test_key) != TC_CRYPTO_SUCCESS) { -DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "AES key setup failed"); -return 1; -} - -DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "AES key setup successful"); - -struct tc_ccm_mode_struct ccm_state; -TCCcmMode_t c = &ccm_state; -uint8_t nonce[13] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD}; - -if (tc_ccm_config(c, &sched, nonce, 13, SC_TAG_SIZE) != TC_CRYPTO_SUCCESS) { -DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "CCM config failed"); -return 1; -} - -DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "CCM config successful"); - -uint8_t plaintext[] = "Hello, World!"; -uint8_t ciphertext[64]; -size_t plaintext_len = sizeof(plaintext) - 1; -size_t ciphertext_len = plaintext_len + SC_TAG_SIZE; - -if (tc_ccm_generation_encryption(ciphertext, ciphertext_len, NULL, 0, plaintext, plaintext_len, c) != TC_CRYPTO_SUCCESS) { -DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "Encryption failed"); -return 1; -} - -DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "Encryption successful"); - -uint8_t decrypted[64]; -if (tc_ccm_decryption_verification(decrypted, plaintext_len, NULL, 0, ciphertext, ciphertext_len, c) != TC_CRYPTO_SUCCESS) { -DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "Decryption failed"); -return 1; -} - -DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "Decryption successful"); - -if (memcmp(plaintext, decrypted, plaintext_len) == 0) { -DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "Crypto test PASSED"); -return 0; -} else { -DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "Data mismatch"); -return 1; -} + printf("=== Basic Crypto Test ===\n"); + + struct tc_aes_key_sched_struct sched; + uint8_t test_key[SC_SESSION_KEY_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10}; + + if (tc_aes128_set_encrypt_key(&sched, test_key) != TC_CRYPTO_SUCCESS) { + printf("❌ AES key setup failed\n"); + return 1; + } + + printf("✅ AES key setup successful\n"); + + struct tc_ccm_mode_struct ccm_state; + TCCcmMode_t c = &ccm_state; + uint8_t nonce[13] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD}; + + if (tc_ccm_config(c, &sched, nonce, 13, SC_TAG_SIZE) != TC_CRYPTO_SUCCESS) { + printf("❌ CCM config failed\n"); + return 1; + } + + printf("✅ CCM config successful\n"); + + uint8_t plaintext[] = "Hello, World!"; + uint8_t ciphertext[64]; + size_t plaintext_len = sizeof(plaintext) - 1; + size_t ciphertext_len = plaintext_len + SC_TAG_SIZE; + + if (tc_ccm_generation_encryption(ciphertext, ciphertext_len, NULL, 0, plaintext, plaintext_len, c) != TC_CRYPTO_SUCCESS) { + printf("❌ Encryption failed\n"); + return 1; + } + + printf("✅ Encryption successful\n"); + + uint8_t decrypted[64]; + if (tc_ccm_decryption_verification(decrypted, plaintext_len, NULL, 0, ciphertext, ciphertext_len, c) != TC_CRYPTO_SUCCESS) { + printf("❌ Decryption failed\n"); + return 1; + } + + printf("✅ Decryption successful\n"); + + if (memcmp(plaintext, decrypted, plaintext_len) == 0) { + printf("✅ Crypto test PASSED\n"); + return 0; + } else { + printf("❌ Data mismatch\n"); + return 1; + } } diff --git a/tests/test_crypto.c.backup b/tests/test_crypto.c.backup deleted file mode 100644 index bf79ed89..00000000 --- a/tests/test_crypto.c.backup +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include -#include -#include - -#define SC_TAG_SIZE 8 -#define SC_SESSION_KEY_SIZE 16 - -int main() { - printf("=== Basic Crypto Test ===\n"); - - struct tc_aes_key_sched_struct sched; - uint8_t test_key[SC_SESSION_KEY_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10}; - - if (tc_aes128_set_encrypt_key(&sched, test_key) != TC_CRYPTO_SUCCESS) { - printf("❌ AES key setup failed\n"); - return 1; - } - - printf("✅ AES key setup successful\n"); - - struct tc_ccm_mode_struct ccm_state; - TCCcmMode_t c = &ccm_state; - uint8_t nonce[13] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD}; - - if (tc_ccm_config(c, &sched, nonce, 13, SC_TAG_SIZE) != TC_CRYPTO_SUCCESS) { - printf("❌ CCM config failed\n"); - return 1; - } - - printf("✅ CCM config successful\n"); - - uint8_t plaintext[] = "Hello, World!"; - uint8_t ciphertext[64]; - size_t plaintext_len = sizeof(plaintext) - 1; - size_t ciphertext_len = plaintext_len + SC_TAG_SIZE; - - if (tc_ccm_generation_encryption(ciphertext, ciphertext_len, NULL, 0, plaintext, plaintext_len, c) != TC_CRYPTO_SUCCESS) { - printf("❌ Encryption failed\n"); - return 1; - } - - printf("✅ Encryption successful\n"); - - uint8_t decrypted[64]; - if (tc_ccm_decryption_verification(decrypted, plaintext_len, NULL, 0, ciphertext, ciphertext_len, c) != TC_CRYPTO_SUCCESS) { - printf("❌ Decryption failed\n"); - return 1; - } - - printf("✅ Decryption successful\n"); - - if (memcmp(plaintext, decrypted, plaintext_len) == 0) { - printf("✅ Crypto test PASSED\n"); - return 0; - } else { - printf("❌ Data mismatch\n"); - return 1; - } -} diff --git a/tests/test_debug.c b/tests/test_debug.c index 084f99f6..4ba0d855 100644 --- a/tests/test_debug.c +++ b/tests/test_debug.c @@ -1,54 +1,49 @@ #include "u_async.h" -#include "../lib/debug_config.h" #include /* Test statistics */ static struct { -int tests_run; -int tests_passed; -int tests_failed; - -/* Timer statistics */ -int timer_callbacks; -int timer_cancellations; -int immediate_timeouts; - -/* Socket statistics */ -int socket_events; -int socket_errors; - -/* Error statistics */ -int memory_allocation_errors; -int invalid_parameter_errors; -int race_condition_errors; + int tests_run; + int tests_passed; + int tests_failed; + + /* Timer statistics */ + int timer_callbacks; + int timer_cancellations; + int immediate_timeouts; + + /* Socket statistics */ + int socket_events; + int socket_errors; + + /* Error statistics */ + int memory_allocation_errors; + int invalid_parameter_errors; + int race_condition_errors; } test_stats = {0}; /* Timer callback for testing */ static void test_timer_callback(void* arg) { -test_stats.timer_callbacks++; -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Timer callback fired. Total callbacks: %d", test_stats.timer_callbacks); + test_stats.timer_callbacks++; + printf("Timer callback fired. Total callbacks: %d\n", test_stats.timer_callbacks); } int main() { - -debug_config_init(); -debug_set_level(DEBUG_LEVEL_TRACE); -debug_set_categories(DEBUG_CATEGORY_ALL); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Before any tests: immediate_timeouts = %d", test_stats.immediate_timeouts); - -uasync_t* ua = uasync_create(); - -/* Set 5 immediate timeouts */ -for (int i = 0; i < 5; i++) { -void* timer = uasync_set_timeout(ua, 0, NULL, test_timer_callback); -} - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After setting 5 immediate timeouts, before poll: immediate_timeouts = %d", test_stats.immediate_timeouts); - -uasync_poll(ua, 1); - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "After poll: immediate_timeouts = %d", test_stats.immediate_timeouts); - -uasync_destroy(ua, 0); -return 0; + printf("Before any tests: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + uasync_t* ua = uasync_create(); + + /* Set 5 immediate timeouts */ + for (int i = 0; i < 5; i++) { + void* timer = uasync_set_timeout(ua, 0, NULL, test_timer_callback); + } + + printf("After setting 5 immediate timeouts, before poll: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + uasync_poll(ua, 1); + + printf("After poll: immediate_timeouts = %d\n", test_stats.immediate_timeouts); + + uasync_destroy(ua, 0); + return 0; } diff --git a/tests/test_debug.c.backup b/tests/test_debug.c.backup deleted file mode 100644 index 4ba0d855..00000000 --- a/tests/test_debug.c.backup +++ /dev/null @@ -1,49 +0,0 @@ -#include "u_async.h" -#include - -/* Test statistics */ -static struct { - int tests_run; - int tests_passed; - int tests_failed; - - /* Timer statistics */ - int timer_callbacks; - int timer_cancellations; - int immediate_timeouts; - - /* Socket statistics */ - int socket_events; - int socket_errors; - - /* Error statistics */ - int memory_allocation_errors; - int invalid_parameter_errors; - int race_condition_errors; -} test_stats = {0}; - -/* Timer callback for testing */ -static void test_timer_callback(void* arg) { - test_stats.timer_callbacks++; - printf("Timer callback fired. Total callbacks: %d\n", test_stats.timer_callbacks); -} - -int main() { - printf("Before any tests: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - uasync_t* ua = uasync_create(); - - /* Set 5 immediate timeouts */ - for (int i = 0; i < 5; i++) { - void* timer = uasync_set_timeout(ua, 0, NULL, test_timer_callback); - } - - printf("After setting 5 immediate timeouts, before poll: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - uasync_poll(ua, 1); - - printf("After poll: immediate_timeouts = %d\n", test_stats.immediate_timeouts); - - uasync_destroy(ua, 0); - return 0; -} diff --git a/tests/test_debug_categories b/tests/test_debug_categories new file mode 100755 index 0000000000000000000000000000000000000000..670cc7314c0ce86090359ea71907d7cc531152d6 GIT binary patch literal 42536 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

|c@?F3`|@4@?S8QK4SH%aW1rXNct@`X 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 JKVm@ke*o0NRKWlM literal 0 HcmV?d00001 diff --git a/tests/test_debug_categories.c b/tests/test_debug_categories.c index 515bb69f..7f2ae022 100644 --- a/tests/test_debug_categories.c +++ b/tests/test_debug_categories.c @@ -1,6 +1,6 @@ /** -* Тест настройки категорий отладки из аргументов командной строки -*/ + * Тест настройки категорий отладки из аргументов командной строки + */ #include #include @@ -8,99 +8,99 @@ #include "../lib/debug_config.h" int main(int argc, char *argv[]) { -DEBUG_INFO(DEBUG_CATEGORY_ALL, "=== Тест настройки категорий из аргументов ==="); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Запуск с аргументами:"); -for (int i = 0; i < argc; i++) { -DEBUG_INFO(DEBUG_CATEGORY_ALL, "%s", argv[i]); -} -DEBUG_INFO(DEBUG_CATEGORY_ALL, "\n"); - -// Инициализация отладки -debug_config_init(); - -// Анализ аргументов командной строки -int debug_categories = 0; - -// Если есть специфические категории, сначала отключаем все -int has_specific_categories = 0; - -for (int i = 1; i < argc; i++) { -if (strcmp(argv[i], "--debug-etcp") == 0) { -has_specific_categories = 1; -} else if (strcmp(argv[i], "--debug-queue") == 0) { -has_specific_categories = 1; -} else if (strcmp(argv[i], "--debug-memory") == 0) { -has_specific_categories = 1; -} else if (strcmp(argv[i], "--debug-none") == 0) { -has_specific_categories = 1; -} -} - -// Если есть специфические категории, отключаем все по умолчанию -if (has_specific_categories) { -debug_set_categories(DEBUG_CATEGORY_NONE); -debug_categories = DEBUG_CATEGORY_NONE; -} - -// Теперь обрабатываем аргументы -for (int i = 1; i < argc; i++) { -if (strcmp(argv[i], "--debug-etcp") == 0) { -debug_enable_category(DEBUG_CATEGORY_ETCP); -debug_categories |= DEBUG_CATEGORY_ETCP; -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Включена категория ETCP"); -} else if (strcmp(argv[i], "--debug-queue") == 0) { -debug_enable_category(DEBUG_CATEGORY_LL_QUEUE); -debug_categories |= DEBUG_CATEGORY_LL_QUEUE; -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Включена категория LL_QUEUE"); -} else if (strcmp(argv[i], "--debug-memory") == 0) { -debug_enable_category(DEBUG_CATEGORY_MEMORY); -debug_categories |= DEBUG_CATEGORY_MEMORY; -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Включена категория MEMORY"); -} else if (strcmp(argv[i], "--debug-all") == 0) { -debug_set_categories(DEBUG_CATEGORY_ALL); -debug_categories = DEBUG_CATEGORY_ALL; -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Включены все категории"); -break; // Все категории уже включены -} else if (strcmp(argv[i], "--debug-none") == 0) { -debug_set_categories(DEBUG_CATEGORY_NONE); -debug_categories = DEBUG_CATEGORY_NONE; -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Выключены все категории"); -break; // Все категории уже выключены -} else if (strcmp(argv[i], "--level") == 0 && i+1 < argc) { -i++; -if (strcmp(argv[i], "error") == 0) { -debug_set_level(DEBUG_LEVEL_ERROR); -DEBUG_ERROR(DEBUG_CATEGORY_ALL, "Установлен уровень ERROR"); -} else if (strcmp(argv[i], "info") == 0) { -debug_set_level(DEBUG_LEVEL_INFO); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Установлен уровень INFO"); -} else if (strcmp(argv[i], "debug") == 0) { -debug_set_level(DEBUG_LEVEL_DEBUG); -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Установлен уровень DEBUG"); -} -} -} - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "\n=== Тестовые сообщения ==="); - -// Сообщения от разных категорий -DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Сообщение от ETCP категории"); -DEBUG_INFO(DEBUG_CATEGORY_LL_QUEUE, "Сообщение от LL_QUEUE категории"); -DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Сообщение от MEMORY категории"); -DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Сообщение от CONNECTION категории"); -DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "Сообщение от CRYPTO категории"); - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "\n=== Информация о текущих настройках ==="); - -DEBUG_INFO(DEBUG_CATEGORY_ALL, "Активные категории:"); -if (debug_categories & DEBUG_CATEGORY_ETCP) printf("ETCP "); -if (debug_categories & DEBUG_CATEGORY_LL_QUEUE) printf("LL_QUEUE "); -if (debug_categories & DEBUG_CATEGORY_MEMORY) printf("MEMORY "); -if (debug_categories & DEBUG_CATEGORY_CONNECTION) printf("CONNECTION "); -if (debug_categories & DEBUG_CATEGORY_CRYPTO) printf("CRYPTO "); -if (debug_categories == DEBUG_CATEGORY_ALL) printf("ALL "); -if (debug_categories == DEBUG_CATEGORY_NONE) printf("NONE "); -DEBUG_INFO(DEBUG_CATEGORY_ALL, ""); - -return 0; + printf("=== Тест настройки категорий из аргументов ===\n"); + printf("Запуск с аргументами: "); + for (int i = 0; i < argc; i++) { + printf("%s ", argv[i]); + } + printf("\n\n"); + + // Инициализация отладки + debug_config_init(); + + // Анализ аргументов командной строки + int debug_categories = 0; + + // Если есть специфические категории, сначала отключаем все + int has_specific_categories = 0; + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--debug-etcp") == 0) { + has_specific_categories = 1; + } else if (strcmp(argv[i], "--debug-queue") == 0) { + has_specific_categories = 1; + } else if (strcmp(argv[i], "--debug-memory") == 0) { + has_specific_categories = 1; + } else if (strcmp(argv[i], "--debug-none") == 0) { + has_specific_categories = 1; + } + } + + // Если есть специфические категории, отключаем все по умолчанию + if (has_specific_categories) { + debug_set_categories(DEBUG_CATEGORY_NONE); + debug_categories = DEBUG_CATEGORY_NONE; + } + + // Теперь обрабатываем аргументы + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--debug-etcp") == 0) { + debug_enable_category(DEBUG_CATEGORY_ETCP); + debug_categories |= DEBUG_CATEGORY_ETCP; + printf("✅ Включена категория ETCP\n"); + } else if (strcmp(argv[i], "--debug-queue") == 0) { + debug_enable_category(DEBUG_CATEGORY_LL_QUEUE); + debug_categories |= DEBUG_CATEGORY_LL_QUEUE; + printf("✅ Включена категория LL_QUEUE\n"); + } else if (strcmp(argv[i], "--debug-memory") == 0) { + debug_enable_category(DEBUG_CATEGORY_MEMORY); + debug_categories |= DEBUG_CATEGORY_MEMORY; + printf("✅ Включена категория MEMORY\n"); + } else if (strcmp(argv[i], "--debug-all") == 0) { + debug_set_categories(DEBUG_CATEGORY_ALL); + debug_categories = DEBUG_CATEGORY_ALL; + printf("✅ Включены все категории\n"); + break; // Все категории уже включены + } else if (strcmp(argv[i], "--debug-none") == 0) { + debug_set_categories(DEBUG_CATEGORY_NONE); + debug_categories = DEBUG_CATEGORY_NONE; + printf("✅ Выключены все категории\n"); + break; // Все категории уже выключены + } else if (strcmp(argv[i], "--level") == 0 && i+1 < argc) { + i++; + if (strcmp(argv[i], "error") == 0) { + debug_set_level(DEBUG_LEVEL_ERROR); + printf("✅ Установлен уровень ERROR\n"); + } else if (strcmp(argv[i], "info") == 0) { + debug_set_level(DEBUG_LEVEL_INFO); + printf("✅ Установлен уровень INFO\n"); + } else if (strcmp(argv[i], "debug") == 0) { + debug_set_level(DEBUG_LEVEL_DEBUG); + printf("✅ Установлен уровень DEBUG\n"); + } + } + } + + printf("\n=== Тестовые сообщения ===\n"); + + // Сообщения от разных категорий + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Сообщение от ETCP категории"); + DEBUG_INFO(DEBUG_CATEGORY_LL_QUEUE, "Сообщение от LL_QUEUE категории"); + DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Сообщение от MEMORY категории"); + DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Сообщение от CONNECTION категории"); + DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "Сообщение от CRYPTO категории"); + + printf("\n=== Информация о текущих настройках ===\n"); + + printf("Активные категории: "); + if (debug_categories & DEBUG_CATEGORY_ETCP) printf("ETCP "); + if (debug_categories & DEBUG_CATEGORY_LL_QUEUE) printf("LL_QUEUE "); + if (debug_categories & DEBUG_CATEGORY_MEMORY) printf("MEMORY "); + if (debug_categories & DEBUG_CATEGORY_CONNECTION) printf("CONNECTION "); + if (debug_categories & DEBUG_CATEGORY_CRYPTO) printf("CRYPTO "); + if (debug_categories == DEBUG_CATEGORY_ALL) printf("ALL "); + if (debug_categories == DEBUG_CATEGORY_NONE) printf("NONE "); + printf("\n"); + + return 0; } \ No newline at end of file diff --git a/tests/test_debug_categories.c.backup b/tests/test_debug_categories.c.backup deleted file mode 100644 index 7f2ae022..00000000 --- a/tests/test_debug_categories.c.backup +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Тест настройки категорий отладки из аргументов командной строки - */ - -#include -#include -#include -#include "../lib/debug_config.h" - -int main(int argc, char *argv[]) { - printf("=== Тест настройки категорий из аргументов ===\n"); - printf("Запуск с аргументами: "); - for (int i = 0; i < argc; i++) { - printf("%s ", argv[i]); - } - printf("\n\n"); - - // Инициализация отладки - debug_config_init(); - - // Анализ аргументов командной строки - int debug_categories = 0; - - // Если есть специфические категории, сначала отключаем все - int has_specific_categories = 0; - - for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "--debug-etcp") == 0) { - has_specific_categories = 1; - } else if (strcmp(argv[i], "--debug-queue") == 0) { - has_specific_categories = 1; - } else if (strcmp(argv[i], "--debug-memory") == 0) { - has_specific_categories = 1; - } else if (strcmp(argv[i], "--debug-none") == 0) { - has_specific_categories = 1; - } - } - - // Если есть специфические категории, отключаем все по умолчанию - if (has_specific_categories) { - debug_set_categories(DEBUG_CATEGORY_NONE); - debug_categories = DEBUG_CATEGORY_NONE; - } - - // Теперь обрабатываем аргументы - for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "--debug-etcp") == 0) { - debug_enable_category(DEBUG_CATEGORY_ETCP); - debug_categories |= DEBUG_CATEGORY_ETCP; - printf("✅ Включена категория ETCP\n"); - } else if (strcmp(argv[i], "--debug-queue") == 0) { - debug_enable_category(DEBUG_CATEGORY_LL_QUEUE); - debug_categories |= DEBUG_CATEGORY_LL_QUEUE; - printf("✅ Включена категория LL_QUEUE\n"); - } else if (strcmp(argv[i], "--debug-memory") == 0) { - debug_enable_category(DEBUG_CATEGORY_MEMORY); - debug_categories |= DEBUG_CATEGORY_MEMORY; - printf("✅ Включена категория MEMORY\n"); - } else if (strcmp(argv[i], "--debug-all") == 0) { - debug_set_categories(DEBUG_CATEGORY_ALL); - debug_categories = DEBUG_CATEGORY_ALL; - printf("✅ Включены все категории\n"); - break; // Все категории уже включены - } else if (strcmp(argv[i], "--debug-none") == 0) { - debug_set_categories(DEBUG_CATEGORY_NONE); - debug_categories = DEBUG_CATEGORY_NONE; - printf("✅ Выключены все категории\n"); - break; // Все категории уже выключены - } else if (strcmp(argv[i], "--level") == 0 && i+1 < argc) { - i++; - if (strcmp(argv[i], "error") == 0) { - debug_set_level(DEBUG_LEVEL_ERROR); - printf("✅ Установлен уровень ERROR\n"); - } else if (strcmp(argv[i], "info") == 0) { - debug_set_level(DEBUG_LEVEL_INFO); - printf("✅ Установлен уровень INFO\n"); - } else if (strcmp(argv[i], "debug") == 0) { - debug_set_level(DEBUG_LEVEL_DEBUG); - printf("✅ Установлен уровень DEBUG\n"); - } - } - } - - printf("\n=== Тестовые сообщения ===\n"); - - // Сообщения от разных категорий - DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Сообщение от ETCP категории"); - DEBUG_INFO(DEBUG_CATEGORY_LL_QUEUE, "Сообщение от LL_QUEUE категории"); - DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Сообщение от MEMORY категории"); - DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Сообщение от CONNECTION категории"); - DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "Сообщение от CRYPTO категории"); - - printf("\n=== Информация о текущих настройках ===\n"); - - printf("Активные категории: "); - if (debug_categories & DEBUG_CATEGORY_ETCP) printf("ETCP "); - if (debug_categories & DEBUG_CATEGORY_LL_QUEUE) printf("LL_QUEUE "); - if (debug_categories & DEBUG_CATEGORY_MEMORY) printf("MEMORY "); - if (debug_categories & DEBUG_CATEGORY_CONNECTION) printf("CONNECTION "); - if (debug_categories & DEBUG_CATEGORY_CRYPTO) printf("CRYPTO "); - if (debug_categories == DEBUG_CATEGORY_ALL) printf("ALL "); - if (debug_categories == DEBUG_CATEGORY_NONE) printf("NONE "); - printf("\n"); - - return 0; -} \ No newline at end of file diff --git a/tests/test_ecc_encrypt b/tests/test_ecc_encrypt new file mode 100755 index 0000000000000000000000000000000000000000..99ac109a19e854524af00065605cf7e92bc7f74e GIT binary patch literal 208968 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