use std::sync::Arc;
use tracing_subscriber::prelude::*;
use trait_kit::AsyncKit;
use super::LoggerModule;
macro_rules! build_detached {
($config:expr) => {{
#[cfg(any(feature = "sqlite", feature = "postgres"))]
{
inklog::LoggerManager::build_detached($config, None).await
}
#[cfg(not(any(feature = "sqlite", feature = "postgres")))]
{
inklog::LoggerManager::build_detached($config).await
}
}};
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_logger_module_build_returns_manager() {
let config = inklog::InklogConfig {
console_sink: None,
..Default::default()
};
let (manager, _subscriber, _filter) = build_detached!(config).expect("build_detached");
let manager = Arc::new(manager);
let mut kit = AsyncKit::new();
kit.set_config(manager.clone());
kit.register::<LoggerModule>().expect("register");
let kit = kit.build().await.expect("build");
let capability: Arc<inklog::LoggerManager> = kit.require::<LoggerModule>().expect("require");
assert!(
Arc::ptr_eq(&capability, &manager),
"LoggerModule::build should return the injected Arc<LoggerManager>"
);
manager.shutdown().expect("shutdown");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_logger_writes_to_file() {
let dir = tempfile::tempdir().expect("temp dir");
let log_path = dir.path().join("test.log");
let config = inklog::InklogConfig {
global: inklog::GlobalConfig {
level: "info".to_string(),
..Default::default()
},
console_sink: None,
file_sink: Some(inklog::FileSinkConfig {
enabled: true,
path: log_path.clone(),
compress: false,
..Default::default()
}),
..Default::default()
};
let (manager, subscriber, _filter) = build_detached!(config).expect("build_detached");
let handle = tokio::spawn(async move {
let registry = tracing_subscriber::registry().with(subscriber);
tracing::subscriber::with_default(registry, || {
tracing::info!("test log message for file sink verification");
});
});
handle.await.expect("spawn task completed");
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
manager.shutdown().expect("shutdown");
assert!(log_path.exists(), "log file should exist at {:?}", log_path);
let content = std::fs::read_to_string(&log_path).unwrap_or_default();
assert!(
content.contains("test log message for file sink verification"),
"log file should contain the message, got: {}",
content
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_log_macro_works() {
let config = inklog::InklogConfig {
global: inklog::GlobalConfig {
level: "info".to_string(),
..Default::default()
},
console_sink: None,
..Default::default()
};
let (manager, subscriber, _filter) = build_detached!(config).expect("build_detached");
let handle = tokio::spawn(async move {
let registry = tracing_subscriber::registry().with(subscriber);
tracing::subscriber::with_default(registry, || {
tracing::info!("tracing info macro test");
tracing::warn!("tracing warn macro test");
tracing::error!("tracing error macro test");
});
});
handle.await.expect("spawn task completed");
manager.shutdown().expect("shutdown");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_logger_console_output() {
let config = inklog::InklogConfig {
global: inklog::GlobalConfig {
level: "info".to_string(),
..Default::default()
},
console_sink: Some(inklog::ConsoleSinkConfig {
enabled: true,
..Default::default()
}),
..Default::default()
};
let (manager, subscriber, _filter) = build_detached!(config).expect("build_detached");
let handle = tokio::spawn(async move {
let registry = tracing_subscriber::registry().with(subscriber);
tracing::subscriber::with_default(registry, || {
tracing::info!("console output test message");
});
});
handle.await.expect("spawn task completed");
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
manager.shutdown().expect("shutdown");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_logger_module_missing_config_fails() {
let mut kit = AsyncKit::new();
kit.register::<LoggerModule>().expect("register");
let result = kit.build().await;
assert!(
result.is_err(),
"build should fail when LoggerManager config is not injected"
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_logger_module_contains_after_register() {
let config = inklog::InklogConfig {
console_sink: None,
..Default::default()
};
let (manager, _subscriber, _filter) = build_detached!(config).expect("build_detached");
let manager = Arc::new(manager);
let mut kit = AsyncKit::new();
kit.set_config(manager.clone());
kit.register::<LoggerModule>().expect("register");
let kit = kit.build().await.expect("build");
assert!(
kit.contains::<LoggerModule>(),
"contains should be true after build"
);
let capability: Arc<inklog::LoggerManager> = kit.require::<LoggerModule>().expect("require");
assert!(Arc::ptr_eq(&capability, &manager));
manager.shutdown().expect("shutdown");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_logger_module_coexists_with_other_modules() {
use crate::registry::EmbeddingModule;
let config = inklog::InklogConfig {
console_sink: None,
..Default::default()
};
let (manager, _subscriber, _filter) = build_detached!(config).expect("build_detached");
let manager = Arc::new(manager);
let mut kit = AsyncKit::new();
kit.set_config(manager.clone());
kit.register::<LoggerModule>().expect("register logger");
kit.register::<EmbeddingModule>()
.expect("register embedding");
let result = kit.build().await;
assert!(
result.is_err(),
"build should fail due to missing EmbeddingModule config"
);
manager.shutdown().expect("shutdown");
}