v0.1.2-pre.004

This commit is contained in:
2026-08-14 18:43:54 +02:00
parent 488d8ae0a8
commit 151590422d
12 changed files with 803 additions and 91 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-logging-lib/tests/public_api.rs
// version: 3
// version: 4
//! Integration tests for the public crate-root surface of `ksp-logging-lib`.
@@ -59,4 +59,9 @@ fn public_runtime_surface_is_addressable_without_installing_it() {
let _reinitialize = ksp_logging_lib::reinitialize;
let _already_initialized = ksp_logging_lib::ERROR_CODE_ALREADY_INITIALIZED;
let _reload_failed = ksp_logging_lib::ERROR_CODE_RELOAD_FAILED;
let _file_initialization_failed = ksp_logging_lib::ERROR_CODE_FILE_OUTPUT_INITIALIZATION_FAILED;
let dropped = ksp_logging_lib::DroppedLines::zero();
assert_eq!(dropped.console(), 0);
assert_eq!(dropped.file(), 0);
assert_eq!(dropped.total(), 0);
}

View File

@@ -1,7 +1,7 @@
// file: crates/ksp-logging-lib/tests/runtime.rs
// version: 1
// version: 2
//! Integration tests for global initialization, takeover filtering and hot reload.
//! Integration tests for global initialization, takeover filtering, non-blocking outputs and hot reload.
const LOGGING_TARGET: &str = "ksp-logging-lib";
const OTHER_KSP_TARGET: &str = "ksp-store-lib";
@@ -23,8 +23,49 @@ fn external_error_enabled() -> bool {
return tracing::enabled!(target: EXTERNAL_TARGET, tracing::Level::ERROR);
}
fn test_root_directory() -> std::path::PathBuf {
return std::env::temp_dir().join(format!("ksp-logging-lib-runtime-{}", std::process::id()));
}
fn reset_directory(path: &std::path::Path) {
if path.exists() {
let remove_result = std::fs::remove_dir_all(path);
assert!(remove_result.is_ok());
}
}
fn read_directory_text(path: &std::path::Path) -> std::string::String {
let read_result = std::fs::read_dir(path);
let entries = match read_result {
std::result::Result::Ok(entries) => entries,
std::result::Result::Err(_) => return std::string::String::new(),
};
let mut output = std::string::String::new();
for entry_result in entries {
let entry = match entry_result {
std::result::Result::Ok(entry) => entry,
std::result::Result::Err(_) => continue,
};
let file_type = match entry.file_type() {
std::result::Result::Ok(file_type) => file_type,
std::result::Result::Err(_) => continue,
};
if !file_type.is_file() {
continue;
}
let content = match std::fs::read_to_string(entry.path()) {
std::result::Result::Ok(content) => content,
std::result::Result::Err(_) => continue,
};
output.push_str(content.as_str());
}
return output;
}
#[test]
fn global_runtime_supports_takeover_hot_reload_and_single_initialization() {
fn global_runtime_supports_takeover_non_blocking_outputs_hot_reload_and_single_initialization() {
let root = test_root_directory();
reset_directory(root.as_path());
let disabled = ksp_logging_lib::LoggingSettings::new(
ksp_logging_lib::LogFilterLevel::Info,
ksp_logging_lib::SpanEvents::Off,
@@ -37,34 +78,66 @@ fn global_runtime_supports_takeover_hot_reload_and_single_initialization() {
std::result::Result::Ok(guard) => guard,
std::result::Result::Err(_) => return,
};
assert_eq!(guard.dropped_lines(), ksp_logging_lib::DroppedLines::zero());
assert!(!logging_trace_enabled());
assert!(!other_ksp_info_enabled());
assert!(!external_error_enabled());
let enabled = ksp_logging_lib::LoggingSettings::new(
let console_enabled = ksp_logging_lib::LoggingSettings::new(
ksp_logging_lib::LogFilterLevel::Info,
ksp_logging_lib::SpanEvents::NewAndClose,
std::option::Option::Some(ksp_logging_lib::ConsoleSettings::stderr()),
std::option::Option::None,
)
.with_target_filter(ksp_logging_lib::TargetFilter::new(LOGGING_TARGET, ksp_logging_lib::LogFilterLevel::Trace));
let reload_result = ksp_logging_lib::reinitialize(&mut guard, &enabled);
let reload_result = ksp_logging_lib::reinitialize(&mut guard, &console_enabled);
assert!(reload_result.is_ok());
assert_eq!(guard.settings(), &enabled);
assert_eq!(guard.settings(), &console_enabled);
assert!(logging_trace_enabled());
assert!(other_ksp_info_enabled());
assert!(!other_ksp_debug_enabled());
assert!(!external_error_enabled());
let unsupported_file = ksp_logging_lib::LoggingSettings::new(
let blocked_directory = root.join("not-a-directory");
let create_root = std::fs::create_dir_all(root.as_path());
assert!(create_root.is_ok());
let create_blocker = std::fs::write(blocked_directory.as_path(), b"file blocks directory creation");
assert!(create_blocker.is_ok());
let invalid_file = ksp_logging_lib::LoggingSettings::new(
ksp_logging_lib::LogFilterLevel::Error,
ksp_logging_lib::SpanEvents::Full,
std::option::Option::None,
std::option::Option::Some(ksp_logging_lib::FileSettings::new("logs", "ksp", ksp_logging_lib::FileRotation::Daily)),
std::option::Option::Some(ksp_logging_lib::FileSettings::new(blocked_directory.as_path(), "invalid", ksp_logging_lib::FileRotation::Daily)),
);
let failed_reload = ksp_logging_lib::reinitialize(&mut guard, &unsupported_file);
let failed_reload = ksp_logging_lib::reinitialize(&mut guard, &invalid_file);
assert!(failed_reload.is_err());
assert_eq!(guard.settings(), &enabled);
let file_error = match failed_reload {
std::result::Result::Ok(()) => return,
std::result::Result::Err(error) => error,
};
assert_eq!(file_error.code(), ksp_logging_lib::ERROR_CODE_FILE_OUTPUT_INITIALIZATION_FAILED);
assert_eq!(guard.settings(), &console_enabled);
assert!(logging_trace_enabled());
assert!(!external_error_enabled());
let log_directory = root.join("logs");
let file_enabled = ksp_logging_lib::LoggingSettings::new(
ksp_logging_lib::LogFilterLevel::Info,
ksp_logging_lib::SpanEvents::Off,
std::option::Option::None,
std::option::Option::Some(ksp_logging_lib::FileSettings::new(log_directory.as_path(), "runtime-test.log", ksp_logging_lib::FileRotation::Never)),
);
let file_reload = ksp_logging_lib::reinitialize(&mut guard, &file_enabled);
assert!(file_reload.is_ok());
ksp_logging_lib::info!(target: LOGGING_TARGET, "file \x1b[31moutput\x1b[0m marker");
tracing::error!(target: EXTERNAL_TARGET, "external marker must remain silent");
let disable_after_file = ksp_logging_lib::reinitialize(&mut guard, &disabled);
assert!(disable_after_file.is_ok());
let file_text = read_directory_text(log_directory.as_path());
assert!(file_text.contains("file output marker"));
assert!(file_text.contains(LOGGING_TARGET));
assert!(file_text.contains("runtime.rs"));
assert!(!file_text.contains("\x1b["));
assert!(!file_text.contains("external marker must remain silent"));
let dropped = guard.dropped_lines();
assert_eq!(dropped.total(), dropped.console().saturating_add(dropped.file()));
let second_initialize = ksp_logging_lib::initialize(&disabled);
assert!(second_initialize.is_err());
let error = match second_initialize {
@@ -72,4 +145,5 @@ fn global_runtime_supports_takeover_hot_reload_and_single_initialization() {
std::result::Result::Err(error) => error,
};
assert_eq!(error.code(), ksp_logging_lib::ERROR_CODE_ALREADY_INITIALIZED);
reset_directory(root.as_path());
}