24namespace fs = std::filesystem;
30#define TEST_ASSERT(condition, message) \
33 std::cerr << " ✗ FAILED: " << message << "\n"; \
39#define TEST_EXPECT_TRUE(condition, message) TEST_ASSERT(condition, message)
40#define TEST_EXPECT_FALSE(condition, message) TEST_ASSERT(!(condition), message)
50 const std::string test_log_dir =
"./test_logs";
51 if (fs::exists(test_log_dir)) {
52 fs::remove_all(test_log_dir);
60 if (!fs::exists(log_dir)) {
64 for (
const auto &entry : fs::directory_iterator(log_dir)) {
65 if (entry.is_regular_file()) {
66 std::ifstream file(entry.path());
68 while (std::getline(file, line)) {
69 if (line.find(pattern) != std::string::npos) {
86 std::cout <<
"\nTesting logger initialization and shutdown...\n";
100 "Logger should initialize successfully");
102 "Logger should be marked as initialized");
106 TEST_EXPECT_TRUE(reinit_result.is_ok(),
"Re-initialization should be safe");
109 auto shutdown_result = logger.
shutdown();
111 "Logger should shutdown successfully");
113 "Logger should not be initialized after shutdown");
116 auto reshutdown_result = logger.
shutdown();
119 std::cout <<
" ✓ Initialization and shutdown tests passed\n";
128 std::cout <<
"\nTesting basic logging...\n";
142 logger.
log(db_log_level::debug,
"Debug message");
143 logger.
log(db_log_level::info,
"Info message");
144 logger.
log(db_log_level::warning,
"Warning message");
145 logger.
log(db_log_level::error,
"Error message");
151 std::this_thread::yield();
154 if (fs::exists(
"./test_logs")) {
157 "Log file should contain logged messages");
162 std::cout <<
" ✓ Basic logging tests passed\n";
171 std::cout <<
"\nTesting query logging and SQL sanitization...\n";
186 logger.
log_query(db_log_level::info,
"SELECT * FROM users WHERE id = 123",
187 std::chrono::microseconds(1500));
191 "CREATE USER 'admin' IDENTIFIED BY PASSWORD 'secret123'",
192 std::chrono::microseconds(500));
195 std::string long_query =
"SELECT ";
196 for (
int i = 0; i < 1000; i++) {
197 long_query +=
"column" + std::to_string(i) +
", ";
199 long_query +=
"* FROM large_table";
201 logger.
log_query(db_log_level::info, long_query,
202 std::chrono::microseconds(2000));
205 std::this_thread::yield();
208 if (fs::exists(
"./test_logs")) {
210 "Password should be sanitized from logs");
215 std::cout <<
" ✓ Query logging and sanitization tests passed\n";
224 std::cout <<
"\nTesting slow query detection...\n";
240 logger.
log_query(db_log_level::info,
"SELECT * FROM fast_table",
241 std::chrono::microseconds(100000));
244 logger.
log_query(db_log_level::info,
"SELECT * FROM slow_table",
245 std::chrono::microseconds(600000));
249 std::chrono::microseconds(1200000),
250 std::chrono::milliseconds(500));
253 std::this_thread::yield();
256 if (fs::exists(
"./test_logs")) {
259 "Slow query should be detected and logged");
264 std::cout <<
" ✓ Slow query detection tests passed\n";
273 std::cout <<
"\nTesting connection event logging...\n";
298 std::this_thread::yield();
302 std::cout <<
" ✓ Connection event logging tests passed\n";
311 std::cout <<
"\nTesting transaction logging...\n";
325 logger.
log_transaction(
"begin",
true,
"Isolation level: READ COMMITTED");
330 "Constraint violation: duplicate key");
333 std::this_thread::yield();
337 std::cout <<
" ✓ Transaction logging tests passed\n";
346 std::cout <<
"\nTesting error logging...\n";
360 logger.
log_error(
"execute_query",
"Connection lost",
"08006");
361 logger.
log_error(
"connect",
"Authentication failed",
"28000");
362 logger.
log_error(
"prepare_statement",
"Syntax error",
"42601");
365 std::this_thread::yield();
369 std::cout <<
" ✓ Error logging tests passed\n";
378 std::cout <<
"\nTesting thread safety...\n";
392 const int num_threads = 4;
393 const int logs_per_thread = 50;
394 std::vector<std::thread> threads;
396 for (
int t = 0; t < num_threads; t++) {
397 threads.emplace_back([&logger, t, logs_per_thread]() {
398 for (
int i = 0; i < logs_per_thread; i++) {
399 logger.
log(db_log_level::info,
"Thread " + std::to_string(t) +
400 " message " + std::to_string(i));
406 for (
auto &thread : threads) {
411 std::this_thread::yield();
415 std::cout <<
" ✓ Thread safety tests passed (no crashes)\n";
424 std::cout <<
"\nTesting log level filtering...\n";
438 logger.
log(db_log_level::trace,
"Trace message - should not appear");
439 logger.
log(db_log_level::debug,
"Debug message - should not appear");
440 logger.
log(db_log_level::info,
"Info message - should not appear");
443 logger.
log(db_log_level::warning,
"Warning message - should appear");
444 logger.
log(db_log_level::error,
"Error message - should appear");
445 logger.
log(db_log_level::critical,
"Critical message - should appear");
448 std::this_thread::yield();
451 if (fs::exists(
"./test_logs")) {
453 "Debug/Info logs should be filtered out");
456 "Warning/Error logs should appear");
461 std::cout <<
" ✓ Log level filtering tests passed\n";
471 std::cout <<
"=== Running Logger Adapter Tests ===\n";
472 std::cout <<
"\nMode: Backend pattern with runtime selection\n";
474 <<
"Backend will be auto-selected (common_logger -> fallback_logger)\n";
491 std::cout <<
"\n=== Test Summary ===\n";
496 std::cout <<
"\n=== All tests passed! ✓ ===\n";
499 std::cout <<
"\n=== Some tests failed! ✗ ===\n";
Unified logging adapter for database operations.
void log_query(db_log_level level, const std::string &query, std::chrono::microseconds duration)
Log a SQL query execution.
common::VoidResult initialize()
Initialize the logger.
void log_slow_query(const std::string &query, std::chrono::microseconds duration, std::chrono::milliseconds threshold)
Log a slow query with warning.
void log_transaction(const std::string &operation, bool success, const std::string &details)
Log a transaction operation.
void log_connection_event(const std::string &event, const std::string &details)
Log a connection pool event.
common::VoidResult shutdown()
Shutdown the logger gracefully.
void log_pool_event(const std::string &event, std::size_t active, std::size_t idle)
Log a connection pool state change.
void log(db_log_level level, const std::string &message)
Generic log message.
void flush()
Flush pending log messages.
void log_error(const std::string &operation, const std::string &error_msg, const std::string &sql_state="")
Log a database error.
bool is_initialized() const
Check if logger is initialized.
Database logging adapter with runtime backend selection.
bool enable_query_logging
Log all SQL queries executed.
bool enable_file_logging
Enable logging to file (in addition to console)
std::string log_directory
Directory for log files.
std::chrono::milliseconds slow_query_threshold
Threshold for considering a query "slow".
bool enable_connection_logging
Log connection pool events (acquire, release, etc.)
bool log_slow_queries
Automatically detect and log slow queries.
db_log_level min_log_level
Minimum log level to output.
bool test_query_logging()
Test query logging and SQL sanitization.
bool test_log_level_filtering()
Test log level filtering.
#define TEST_EXPECT_FALSE(condition, message)
bool test_error_logging()
Test error logging.
bool test_transaction_logging()
Test transaction logging.
bool test_connection_logging()
Test connection event logging.
bool test_initialization()
Test logger initialization and shutdown.
bool log_file_contains(const std::string &log_dir, const std::string &pattern)
Check if a log file contains a specific string.
bool test_slow_query_detection()
Test slow query detection.
void cleanup_test_logs()
Clean up test log directory.
bool test_basic_logging()
Test basic logging functionality.
bool test_thread_safety()
Test thread safety (basic concurrency test)
#define TEST_EXPECT_TRUE(condition, message)