v0.1.4-pre.015-fix.002
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/composite.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
const TEST_COMPOSITE_FILE_ID: &str = "cfg.composite.test";
|
||||
const TEST_COMPOSITE_FILENAME: &str = "examples/composite.example.json";
|
||||
|
||||
#[test]
|
||||
fn committed_composite_example_resolves_default_document_profile() {
|
||||
let engine = committed_engine();
|
||||
fn fixture_composite_example_resolves_default_document_profile() {
|
||||
let engine = fixture_example_engine();
|
||||
let file_id = crate::ConfigFileId::new(TEST_COMPOSITE_FILE_ID);
|
||||
assert!(engine.is_ok(), "composite test engine should be constructible: {engine:?}");
|
||||
assert!(file_id.is_ok(), "composite test file_id should be valid: {file_id:?}");
|
||||
if let (std::result::Result::Ok(engine), std::result::Result::Ok(file_id)) = (engine, file_id) {
|
||||
let resolved = engine.load_resolved_composite(&file_id, std::option::Option::None);
|
||||
assert!(resolved.is_ok(), "committed composite example should resolve: {resolved:?}");
|
||||
assert!(resolved.is_ok(), "fixture composite example should resolve: {resolved:?}");
|
||||
if let std::result::Result::Ok(resolved) = resolved {
|
||||
assert_eq!(resolved.profile_id(), "local_default");
|
||||
assert_eq!(resolved.selection_source(), crate::ConfigProfileSelectionSource::DefaultProfile);
|
||||
@@ -20,7 +20,12 @@ fn committed_composite_example_resolves_default_document_profile() {
|
||||
assert!(logging.is_some(), "logging component should be resolved");
|
||||
if let std::option::Option::Some(logging) = logging {
|
||||
assert_eq!(logging.resolved().file_id().as_str(), crate::FILE_ID_STD_LOGGING);
|
||||
assert_eq!(logging.resolved().profile_id(), "local_dev");
|
||||
let logging_document = engine.load_validated_document(logging.resolved().file_id());
|
||||
assert!(logging_document.is_ok(), "referenced Logging document should validate: {logging_document:?}");
|
||||
if let std::result::Result::Ok(logging_document) = logging_document {
|
||||
let default_profile = logging_document.value().get("default_profile").and_then(serde_json::Value::as_str);
|
||||
assert_eq!(default_profile, std::option::Option::Some(logging.resolved().profile_id()));
|
||||
}
|
||||
assert_eq!(logging.resolved().selection_source(), crate::ConfigProfileSelectionSource::DefaultProfile);
|
||||
assert_eq!(logging.resolved().origin("logs_directory"), std::option::Option::Some(crate::ConfigValueOrigin::Global));
|
||||
}
|
||||
@@ -30,7 +35,7 @@ fn committed_composite_example_resolves_default_document_profile() {
|
||||
|
||||
#[test]
|
||||
fn composite_profile_override_marks_referenced_profile_selection_as_composite() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_example_engine();
|
||||
let file_id = crate::ConfigFileId::new(TEST_COMPOSITE_FILE_ID);
|
||||
assert!(engine.is_ok(), "composite test engine should be constructible: {engine:?}");
|
||||
assert!(file_id.is_ok(), "composite test file_id should be valid: {file_id:?}");
|
||||
@@ -51,7 +56,7 @@ fn composite_profile_override_marks_referenced_profile_selection_as_composite()
|
||||
|
||||
#[test]
|
||||
fn unknown_composite_profile_has_profile_not_found_error() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_example_engine();
|
||||
let file_id = crate::ConfigFileId::new(TEST_COMPOSITE_FILE_ID);
|
||||
assert!(engine.is_ok(), "composite test engine should be constructible: {engine:?}");
|
||||
assert!(file_id.is_ok(), "composite test file_id should be valid: {file_id:?}");
|
||||
@@ -123,9 +128,10 @@ fn duplicate_component_ids_are_rejected_inside_one_composite_profile() {
|
||||
cleanup_fixture(&fixture);
|
||||
}
|
||||
|
||||
fn committed_engine() -> ksp_core_lib::Result<crate::ConfigDocumentEngine> {
|
||||
fn fixture_example_engine() -> ksp_core_lib::Result<crate::ConfigDocumentEngine> {
|
||||
let workspace = workspace_root();
|
||||
let bootstrap = crate::ConfigBootstrapOptions::from_paths(workspace.join("config"), workspace.join("config/schemas"));
|
||||
let fixture_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("unit_tests/fixtures");
|
||||
let bootstrap = crate::ConfigBootstrapOptions::from_paths(fixture_root, workspace.join("config/schemas"));
|
||||
let bootstrap = match bootstrap {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
@@ -205,7 +211,8 @@ fn prepare_fixture(fixture: &FixtureRoots, composite: &str) -> std::io::Result<(
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
let workspace = workspace_root();
|
||||
let logging = std::fs::copy(workspace.join("config/std.logging.json"), fixture.config.join(crate::DEFAULT_STD_LOGGING_FILENAME));
|
||||
let stable_logging = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("unit_tests/fixtures/std.logging.json");
|
||||
let logging = std::fs::copy(stable_logging, fixture.config.join(crate::DEFAULT_STD_LOGGING_FILENAME));
|
||||
if let std::result::Result::Err(error) = logging {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/document.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
#[test]
|
||||
fn committed_logging_document_passes_registered_schema_and_semantic_validation() {
|
||||
@@ -17,10 +17,16 @@ fn committed_logging_document_passes_registered_schema_and_semantic_validation()
|
||||
if let std::result::Result::Ok(document) = document {
|
||||
assert_eq!(document.file_id(), &file_id);
|
||||
assert_eq!(document.path(), workspace.join("config/std.logging.json").as_path());
|
||||
let default_profile = document.value().get("default_profile");
|
||||
let default_profile = document.value().get("default_profile").and_then(serde_json::Value::as_str);
|
||||
assert!(default_profile.is_some(), "validated Logging document should retain default_profile");
|
||||
if let std::option::Option::Some(default_profile) = default_profile {
|
||||
assert_eq!(default_profile.as_str(), std::option::Option::Some("local_dev"));
|
||||
let profiles = document.value().get("profiles").and_then(serde_json::Value::as_array);
|
||||
assert!(profiles.is_some(), "validated Logging document should retain profiles");
|
||||
if let std::option::Option::Some(profiles) = profiles {
|
||||
assert!(profiles.iter().any(|profile| -> bool {
|
||||
return profile.get("profile_id").and_then(serde_json::Value::as_str) == std::option::Option::Some(default_profile);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/environment.rs
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
#[test]
|
||||
fn process_environment_wins_over_dotenv_and_fallback_even_when_empty() {
|
||||
@@ -174,9 +174,8 @@ fn fake_process_collection_filters_unrelated_names_without_mutating_real_environ
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn committed_logging_profile_resolves_environment_fallback_without_changing_source_profile() {
|
||||
let workspace = workspace_root();
|
||||
let bootstrap = crate::ConfigBootstrapOptions::from_paths(workspace.join("config"), workspace.join("config/schemas"));
|
||||
fn logging_fixture_profile_resolves_environment_fallback_without_changing_source_profile() {
|
||||
let bootstrap = logging_fixture_bootstrap();
|
||||
assert!(bootstrap.is_ok(), "bootstrap should resolve committed roots");
|
||||
let bootstrap = match bootstrap {
|
||||
std::result::Result::Ok(value) => value,
|
||||
@@ -235,6 +234,12 @@ fn workspace_root() -> std::path::PathBuf {
|
||||
return std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
|
||||
}
|
||||
|
||||
fn logging_fixture_bootstrap() -> ksp_core_lib::Result<crate::ConfigBootstrapOptions> {
|
||||
let fixture_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("unit_tests/fixtures");
|
||||
let workspace = workspace_root();
|
||||
return crate::ConfigBootstrapOptions::from_paths(fixture_root, workspace.join("config/schemas"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secret_environment_value_keeps_real_value_but_redacts_safe_and_debug_views() {
|
||||
let canary = "KSP_SECRET_CANARY_91b7c6";
|
||||
@@ -322,9 +327,8 @@ fn detailed_json_preserves_safe_tree_sensitivity_and_pointer_provenance() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detailed_profile_environment_keeps_global_origin_and_adds_environment_provenance() {
|
||||
let workspace = workspace_root();
|
||||
let bootstrap = crate::ConfigBootstrapOptions::from_paths(workspace.join("config"), workspace.join("config/schemas"));
|
||||
fn detailed_fixture_profile_environment_keeps_global_origin_and_adds_environment_provenance() {
|
||||
let bootstrap = logging_fixture_bootstrap();
|
||||
let bootstrap = match bootstrap {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"format_version": 1,
|
||||
"default_profile": "local_default",
|
||||
"profiles": [
|
||||
{
|
||||
"profile_id": "local_default",
|
||||
"documents": [
|
||||
{
|
||||
"component_id": "logging",
|
||||
"file_id": "cfg.std.logging"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"profile_id": "local_explicit",
|
||||
"documents": [
|
||||
{
|
||||
"component_id": "logging",
|
||||
"file_id": "cfg.std.logging",
|
||||
"profile_id": "local_dev"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
77
crates/ksp-config-lib/unit_tests/fixtures/std.logging.json
Normal file
77
crates/ksp-config-lib/unit_tests/fixtures/std.logging.json
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"format_version": 1,
|
||||
"logs_directory": "${KSP_LOGS_DIRECTORY:-logs}",
|
||||
"default_profile": "local_dev",
|
||||
"profiles": [
|
||||
{
|
||||
"profile_id": "local_dev",
|
||||
"default_filter": "warn",
|
||||
"span_events": "new_and_close",
|
||||
"console": {
|
||||
"enabled": true,
|
||||
"output": "stderr",
|
||||
"ansi": true,
|
||||
"format": "compact",
|
||||
"filter": {
|
||||
"level": "debug",
|
||||
"targets": [
|
||||
"*"
|
||||
],
|
||||
"domains": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
{
|
||||
"output_id": "file.all.debug",
|
||||
"enabled": true,
|
||||
"path": "debug/ksp-debug.log",
|
||||
"rotation": "daily",
|
||||
"format": "human",
|
||||
"ansi": false,
|
||||
"filter": {
|
||||
"level": "debug",
|
||||
"targets": [
|
||||
"*"
|
||||
],
|
||||
"domains": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"output_id": "file.config.error",
|
||||
"enabled": true,
|
||||
"path": "config/ksp-config-errors.jsonl",
|
||||
"rotation": "daily",
|
||||
"format": "json",
|
||||
"ansi": false,
|
||||
"filter": {
|
||||
"level": "error",
|
||||
"targets": [
|
||||
"ksp-config-lib"
|
||||
],
|
||||
"domains": [
|
||||
"config"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"target_filters": [
|
||||
{
|
||||
"target_prefix": "ksp-config-lib",
|
||||
"level": "trace"
|
||||
},
|
||||
{
|
||||
"target_prefix": "ksp-logging-lib",
|
||||
"level": "debug"
|
||||
},
|
||||
{
|
||||
"target_prefix": "ksp-app-config-desk",
|
||||
"level": "debug"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,76 +1,145 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/logging.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
#[test]
|
||||
fn committed_logging_profile_maps_complete_runtime_contract() {
|
||||
let engine = committed_engine();
|
||||
fn fixture_logging_profile_maps_complete_runtime_contract() {
|
||||
let engine = fixture_engine();
|
||||
let engine = match engine {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let environment = crate::ConfigEnvironment::from_maps(std::collections::BTreeMap::new(), std::collections::BTreeMap::new());
|
||||
let resolved = engine.load_resolved_logging_config(std::option::Option::None, &environment);
|
||||
assert!(resolved.is_ok(), "committed Logging Config should map");
|
||||
assert!(resolved.is_ok(), "fixture Logging Config should map");
|
||||
let resolved = match resolved {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
assert_eq!(resolved.file_id().as_str(), crate::FILE_ID_STD_LOGGING);
|
||||
assert_eq!(resolved.profile_id(), "local_dev");
|
||||
assert_eq!(resolved.selection_source(), crate::ConfigProfileSelectionSource::DefaultProfile);
|
||||
assert_eq!(resolved.logs_directory(), current_directory().join("logs").as_path());
|
||||
assert_eq!(resolved.effective().value()["logs_directory"], serde_json::Value::String("logs".to_owned()));
|
||||
let effective = resolved.effective().value();
|
||||
let effective_logs_directory = effective.get("logs_directory").and_then(serde_json::Value::as_str);
|
||||
assert!(effective_logs_directory.is_some(), "effective Logging Config should expose logs_directory");
|
||||
if let std::option::Option::Some(effective_logs_directory) = effective_logs_directory {
|
||||
let source_path = std::path::Path::new(effective_logs_directory);
|
||||
let expected = if source_path.is_absolute() { source_path.to_path_buf() } else { current_directory().join(source_path) };
|
||||
assert_eq!(resolved.logs_directory(), expected.as_path());
|
||||
}
|
||||
let settings = resolved.settings();
|
||||
assert_eq!(settings.default_filter(), ksp_logging_lib::LogFilterLevel::Warn);
|
||||
assert_eq!(settings.span_events(), ksp_logging_lib::SpanEvents::NewAndClose);
|
||||
assert_eq!(settings.target_filters().len(), 3);
|
||||
assert_eq!(settings.target_filters()[0].target_prefix(), "ksp-config-lib");
|
||||
assert_eq!(settings.target_filters()[0].level(), ksp_logging_lib::LogFilterLevel::Trace);
|
||||
assert_eq!(settings.target_filters()[1].target_prefix(), "ksp-logging-lib");
|
||||
assert_eq!(settings.target_filters()[1].level(), ksp_logging_lib::LogFilterLevel::Debug);
|
||||
assert_eq!(settings.target_filters()[2].target_prefix(), "ksp-app-config-desk");
|
||||
assert_eq!(settings.target_filters()[2].level(), ksp_logging_lib::LogFilterLevel::Debug);
|
||||
let default_filter = effective.get("default_filter").and_then(serde_json::Value::as_str);
|
||||
let span_events = effective.get("span_events").and_then(serde_json::Value::as_str);
|
||||
assert_eq!(default_filter.and_then(test_level), std::option::Option::Some(settings.default_filter()));
|
||||
assert_eq!(span_events.and_then(test_span_events), std::option::Option::Some(settings.span_events()));
|
||||
let source_target_filters = effective.get("target_filters").and_then(serde_json::Value::as_array);
|
||||
assert!(source_target_filters.is_some(), "effective Logging Config should expose target_filters");
|
||||
if let std::option::Option::Some(source_target_filters) = source_target_filters {
|
||||
assert_eq!(settings.target_filters().len(), source_target_filters.len());
|
||||
for (runtime, source) in settings.target_filters().iter().zip(source_target_filters) {
|
||||
assert_eq!(source.get("target_prefix").and_then(serde_json::Value::as_str), std::option::Option::Some(runtime.target_prefix()));
|
||||
assert_eq!(source.get("level").and_then(serde_json::Value::as_str).and_then(test_level), std::option::Option::Some(runtime.level()));
|
||||
}
|
||||
}
|
||||
let console = settings.console();
|
||||
assert!(console.is_some(), "committed Logging Config declares console settings");
|
||||
let console = match console {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
let source_console = effective.get("console");
|
||||
assert!(console.is_some(), "effective Logging Config declares console settings");
|
||||
assert!(source_console.is_some(), "effective Logging Config should expose console settings");
|
||||
if let (std::option::Option::Some(console), std::option::Option::Some(source_console)) = (console, source_console) {
|
||||
assert_eq!(source_console.get("enabled").and_then(serde_json::Value::as_bool), std::option::Option::Some(console.enabled()));
|
||||
assert_eq!(source_console.get("ansi").and_then(serde_json::Value::as_bool), std::option::Option::Some(console.ansi()));
|
||||
assert_eq!(source_console.get("output").and_then(serde_json::Value::as_str).and_then(test_console_output), std::option::Option::Some(console.output()));
|
||||
assert_eq!(source_console.get("format").and_then(serde_json::Value::as_str).and_then(test_format), std::option::Option::Some(console.format()));
|
||||
let filter = source_console.get("filter");
|
||||
assert!(filter.is_some(), "effective console should expose filter");
|
||||
if let std::option::Option::Some(filter) = filter {
|
||||
assert_eq!(filter.get("level").and_then(serde_json::Value::as_str).and_then(test_level), std::option::Option::Some(console.filter().level()));
|
||||
assert_eq!(json_string_array(filter.get("targets")), console.filter().targets().to_vec());
|
||||
assert_eq!(json_string_array(filter.get("domains")), console.filter().domains().to_vec());
|
||||
}
|
||||
}
|
||||
let source_files = effective.get("files").and_then(serde_json::Value::as_array);
|
||||
assert!(source_files.is_some(), "effective Logging Config should expose files");
|
||||
if let std::option::Option::Some(source_files) = source_files {
|
||||
assert_eq!(settings.files().len(), source_files.len());
|
||||
for (runtime, source) in settings.files().iter().zip(source_files) {
|
||||
assert_eq!(source.get("output_id").and_then(serde_json::Value::as_str), std::option::Option::Some(runtime.output_id()));
|
||||
assert_eq!(source.get("enabled").and_then(serde_json::Value::as_bool), std::option::Option::Some(runtime.enabled()));
|
||||
assert_eq!(source.get("rotation").and_then(serde_json::Value::as_str).and_then(test_rotation), std::option::Option::Some(runtime.rotation()));
|
||||
assert_eq!(source.get("format").and_then(serde_json::Value::as_str).and_then(test_format), std::option::Option::Some(runtime.format()));
|
||||
assert_eq!(source.get("ansi").and_then(serde_json::Value::as_bool), std::option::Option::Some(runtime.ansi()));
|
||||
let filter = source.get("filter");
|
||||
assert!(filter.is_some(), "effective file should expose filter");
|
||||
if let std::option::Option::Some(filter) = filter {
|
||||
assert_eq!(filter.get("level").and_then(serde_json::Value::as_str).and_then(test_level), std::option::Option::Some(runtime.filter().level()));
|
||||
assert_eq!(json_string_array(filter.get("targets")), runtime.filter().targets().to_vec());
|
||||
assert_eq!(json_string_array(filter.get("domains")), runtime.filter().domains().to_vec());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_level(value: &str) -> std::option::Option<ksp_logging_lib::LogFilterLevel> {
|
||||
return match value {
|
||||
"off" => std::option::Option::Some(ksp_logging_lib::LogFilterLevel::Off),
|
||||
"error" => std::option::Option::Some(ksp_logging_lib::LogFilterLevel::Error),
|
||||
"warn" => std::option::Option::Some(ksp_logging_lib::LogFilterLevel::Warn),
|
||||
"info" => std::option::Option::Some(ksp_logging_lib::LogFilterLevel::Info),
|
||||
"debug" => std::option::Option::Some(ksp_logging_lib::LogFilterLevel::Debug),
|
||||
"trace" => std::option::Option::Some(ksp_logging_lib::LogFilterLevel::Trace),
|
||||
_ => std::option::Option::None,
|
||||
};
|
||||
assert!(console.enabled());
|
||||
assert_eq!(console.output(), ksp_logging_lib::ConsoleOutput::Stderr);
|
||||
assert!(console.ansi());
|
||||
assert_eq!(console.format(), ksp_logging_lib::LogFormat::Compact);
|
||||
assert_eq!(console.filter().level(), ksp_logging_lib::LogFilterLevel::Debug);
|
||||
assert_eq!(console.filter().targets(), &["*".to_owned()]);
|
||||
assert_eq!(console.filter().domains(), &["*".to_owned()]);
|
||||
assert_eq!(settings.files().len(), 2);
|
||||
assert_file(
|
||||
&settings.files()[0],
|
||||
"file.all.debug",
|
||||
current_directory().join("logs/debug").as_path(),
|
||||
"ksp-debug.log",
|
||||
ksp_logging_lib::FileRotation::Daily,
|
||||
ksp_logging_lib::LogFormat::Human,
|
||||
ksp_logging_lib::LogFilterLevel::Debug,
|
||||
&["*"],
|
||||
&["*"],
|
||||
);
|
||||
assert_file(
|
||||
&settings.files()[1],
|
||||
"file.config.error",
|
||||
current_directory().join("logs/config").as_path(),
|
||||
"ksp-config-errors.jsonl",
|
||||
ksp_logging_lib::FileRotation::Daily,
|
||||
ksp_logging_lib::LogFormat::Json,
|
||||
ksp_logging_lib::LogFilterLevel::Error,
|
||||
&["ksp-config-lib"],
|
||||
&["config"],
|
||||
);
|
||||
}
|
||||
|
||||
fn test_span_events(value: &str) -> std::option::Option<ksp_logging_lib::SpanEvents> {
|
||||
return match value {
|
||||
"off" => std::option::Option::Some(ksp_logging_lib::SpanEvents::Off),
|
||||
"new_and_close" => std::option::Option::Some(ksp_logging_lib::SpanEvents::NewAndClose),
|
||||
"full" => std::option::Option::Some(ksp_logging_lib::SpanEvents::Full),
|
||||
_ => std::option::Option::None,
|
||||
};
|
||||
}
|
||||
|
||||
fn test_console_output(value: &str) -> std::option::Option<ksp_logging_lib::ConsoleOutput> {
|
||||
return match value {
|
||||
"stdout" => std::option::Option::Some(ksp_logging_lib::ConsoleOutput::Stdout),
|
||||
"stderr" => std::option::Option::Some(ksp_logging_lib::ConsoleOutput::Stderr),
|
||||
_ => std::option::Option::None,
|
||||
};
|
||||
}
|
||||
|
||||
fn test_format(value: &str) -> std::option::Option<ksp_logging_lib::LogFormat> {
|
||||
return match value {
|
||||
"human" => std::option::Option::Some(ksp_logging_lib::LogFormat::Human),
|
||||
"compact" => std::option::Option::Some(ksp_logging_lib::LogFormat::Compact),
|
||||
"pretty" => std::option::Option::Some(ksp_logging_lib::LogFormat::Pretty),
|
||||
"json" => std::option::Option::Some(ksp_logging_lib::LogFormat::Json),
|
||||
_ => std::option::Option::None,
|
||||
};
|
||||
}
|
||||
|
||||
fn test_rotation(value: &str) -> std::option::Option<ksp_logging_lib::FileRotation> {
|
||||
return match value {
|
||||
"never" => std::option::Option::Some(ksp_logging_lib::FileRotation::Never),
|
||||
"hourly" => std::option::Option::Some(ksp_logging_lib::FileRotation::Hourly),
|
||||
"daily" => std::option::Option::Some(ksp_logging_lib::FileRotation::Daily),
|
||||
_ => std::option::Option::None,
|
||||
};
|
||||
}
|
||||
|
||||
fn json_string_array(value: std::option::Option<&serde_json::Value>) -> std::vec::Vec<String> {
|
||||
let mut result = std::vec::Vec::<String>::new();
|
||||
if let std::option::Option::Some(values) = value.and_then(serde_json::Value::as_array) {
|
||||
for value in values {
|
||||
if let std::option::Option::Some(value) = value.as_str() {
|
||||
result.push(value.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relative_logs_directory_is_anchored_to_process_current_directory() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_engine();
|
||||
let engine = match engine {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
@@ -86,7 +155,7 @@ fn relative_logs_directory_is_anchored_to_process_current_directory() {
|
||||
|
||||
#[test]
|
||||
fn absolute_logs_directory_is_preserved() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_engine();
|
||||
let engine = match engine {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
@@ -111,7 +180,7 @@ fn effective_file_paths_cannot_escape_logging_root() {
|
||||
|
||||
#[test]
|
||||
fn explicit_empty_logs_directory_is_invalid_instead_of_using_fallback() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_engine();
|
||||
let engine = match engine {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
@@ -130,7 +199,7 @@ fn explicit_empty_logs_directory_is_invalid_instead_of_using_fallback() {
|
||||
|
||||
#[test]
|
||||
fn existing_non_directory_logging_root_is_rejected_without_secret_leak() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_engine();
|
||||
let engine = match engine {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
@@ -139,7 +208,7 @@ fn existing_non_directory_logging_root_is_rejected_without_secret_leak() {
|
||||
let path = std::env::temp_dir().join(secret.as_str());
|
||||
let write = std::fs::write(path.as_path(), b"not a directory");
|
||||
assert!(write.is_ok(), "secret canary file should be created");
|
||||
let profile = load_committed_profile(&engine);
|
||||
let profile = load_fixture_profile(&engine);
|
||||
let profile = match profile {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
@@ -161,12 +230,12 @@ fn existing_non_directory_logging_root_is_rejected_without_secret_leak() {
|
||||
|
||||
#[test]
|
||||
fn logging_adapter_rejects_secret_effective_values_without_exposing_canary() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_engine();
|
||||
let engine = match engine {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let profile = load_committed_profile(&engine);
|
||||
let profile = load_fixture_profile(&engine);
|
||||
let profile = match profile {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
@@ -193,7 +262,7 @@ fn logging_adapter_rejects_secret_effective_values_without_exposing_canary() {
|
||||
|
||||
#[test]
|
||||
fn mapped_logging_settings_can_initialize_and_reinitialize_runtime() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_engine();
|
||||
let engine = match engine {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
@@ -231,7 +300,7 @@ fn mapped_logging_settings_can_initialize_and_reinitialize_runtime() {
|
||||
|
||||
#[test]
|
||||
fn resolved_logging_debug_uses_safe_effective_view() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_engine();
|
||||
let engine = match engine {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
@@ -270,9 +339,10 @@ fn assert_file(
|
||||
assert_eq!(file.filter().domains().iter().map(String::as_str).collect::<std::vec::Vec<&str>>(), domains.to_vec());
|
||||
}
|
||||
|
||||
fn committed_engine() -> ksp_core_lib::Result<crate::ConfigDocumentEngine> {
|
||||
fn fixture_engine() -> ksp_core_lib::Result<crate::ConfigDocumentEngine> {
|
||||
let workspace = workspace_root();
|
||||
let bootstrap = crate::ConfigBootstrapOptions::from_paths(workspace.join("config"), workspace.join("config/schemas"));
|
||||
let fixture_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("unit_tests/fixtures");
|
||||
let bootstrap = crate::ConfigBootstrapOptions::from_paths(fixture_root, workspace.join("config/schemas"));
|
||||
let bootstrap = match bootstrap {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
@@ -285,7 +355,7 @@ fn committed_engine() -> ksp_core_lib::Result<crate::ConfigDocumentEngine> {
|
||||
return std::result::Result::Ok(crate::ConfigDocumentEngine::new(bootstrap, registry));
|
||||
}
|
||||
|
||||
fn load_committed_profile(engine: &crate::ConfigDocumentEngine) -> ksp_core_lib::Result<crate::ResolvedConfigProfile> {
|
||||
fn load_fixture_profile(engine: &crate::ConfigDocumentEngine) -> ksp_core_lib::Result<crate::ResolvedConfigProfile> {
|
||||
let file_id = crate::ConfigFileId::new(crate::FILE_ID_STD_LOGGING);
|
||||
let file_id = match file_id {
|
||||
std::result::Result::Ok(value) => value,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/management.rs
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
static NEXT_FIXTURE_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
|
||||
|
||||
@@ -56,7 +56,7 @@ fn valid_raw_source_candidate_is_persisted_exactly_and_reports_reload() {
|
||||
return;
|
||||
},
|
||||
};
|
||||
let candidate = original.replace(" \"logs_directory\":", " \"logs_directory\":");
|
||||
let candidate = format!("{original} \n");
|
||||
assert_ne!(candidate, original, "raw source candidate fixture must change the persisted bytes");
|
||||
let corrupt = std::fs::write(fixture.config_path.as_path(), b"{\n");
|
||||
assert!(corrupt.is_ok(), "existing managed source should be corruptible for repair test");
|
||||
@@ -165,7 +165,23 @@ fn semantic_invalid_source_candidate_is_rejected_without_modifying_existing_file
|
||||
return;
|
||||
},
|
||||
};
|
||||
let candidate = before.replace("\"default_profile\": \"local_dev\"", "\"default_profile\": \"missing\"");
|
||||
let candidate_value = serde_json::from_str::<serde_json::Value>(before.as_str());
|
||||
let mut candidate_value = match candidate_value {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
candidate_value["default_profile"] = serde_json::Value::String("missing".to_owned());
|
||||
let candidate = serde_json::to_string_pretty(&candidate_value);
|
||||
let candidate = match candidate {
|
||||
std::result::Result::Ok(value) => format!("{value}\n"),
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
assert_ne!(candidate, before, "semantic-invalid fixture must alter the default profile");
|
||||
let file_id = crate::ConfigFileId::new(crate::FILE_ID_STD_LOGGING);
|
||||
let file_id = match file_id {
|
||||
@@ -237,10 +253,8 @@ fn typed_logging_document_can_be_mutated_validated_and_persisted_atomically() {
|
||||
},
|
||||
};
|
||||
assert_eq!(document.format_version(), 1);
|
||||
assert_eq!(document.default_profile(), "local_dev");
|
||||
assert_eq!(document.profiles().len(), 1);
|
||||
assert_eq!(document.profiles()[0].files().len(), 2);
|
||||
assert!(!document.profiles()[0].files()[0].ansi());
|
||||
assert!(!document.default_profile().is_empty());
|
||||
assert!(!document.profiles().is_empty());
|
||||
document.set_logs_directory("managed-logs");
|
||||
if let std::option::Option::Some(profile) = document.profiles_mut().first_mut() {
|
||||
profile.set_default_filter("info");
|
||||
@@ -496,7 +510,7 @@ fn management_fixture() -> ksp_core_lib::Result<ManagementFixture> {
|
||||
);
|
||||
}
|
||||
let workspace = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
|
||||
let source_config = workspace.join("config/std.logging.json");
|
||||
let source_config = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("unit_tests/fixtures/std.logging.json");
|
||||
let source_schema = workspace.join("config/schemas/std.logging.schema.json");
|
||||
let config_path = config_root.join("std.logging.json");
|
||||
let schema_path = schema_root.join("std.logging.schema.json");
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/profile.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
#[test]
|
||||
fn committed_default_profile_resolves_globals_profile_and_provenance() {
|
||||
let engine = committed_engine();
|
||||
fn fixture_default_profile_resolves_globals_profile_and_provenance() {
|
||||
let engine = fixture_engine();
|
||||
let file_id = crate::ConfigFileId::new(crate::FILE_ID_STD_LOGGING);
|
||||
assert!(engine.is_ok(), "committed Config engine should be constructible: {engine:?}");
|
||||
assert!(engine.is_ok(), "fixture Config engine should be constructible: {engine:?}");
|
||||
assert!(file_id.is_ok(), "logging file_id should be valid: {file_id:?}");
|
||||
if let (std::result::Result::Ok(engine), std::result::Result::Ok(file_id)) = (engine, file_id) {
|
||||
let document = engine.load_validated_document(&file_id);
|
||||
assert!(document.is_ok(), "committed Logging document should validate: {document:?}");
|
||||
let resolved = engine.load_resolved_profile(&file_id, std::option::Option::None);
|
||||
assert!(resolved.is_ok(), "default profile should resolve: {resolved:?}");
|
||||
if let std::result::Result::Ok(resolved) = resolved {
|
||||
assert_eq!(resolved.profile_id(), "local_dev");
|
||||
if let (std::result::Result::Ok(document), std::result::Result::Ok(resolved)) = (document, resolved) {
|
||||
let default_profile = document.value().get("default_profile").and_then(serde_json::Value::as_str);
|
||||
assert_eq!(default_profile, std::option::Option::Some(resolved.profile_id()));
|
||||
assert_eq!(resolved.selection_source(), super::ConfigProfileSelectionSource::DefaultProfile);
|
||||
assert_eq!(resolved.globals().get("logs_directory").and_then(serde_json::Value::as_str), std::option::Option::Some("${KSP_LOGS_DIRECTORY:-logs}"));
|
||||
assert_eq!(resolved.profile().get("default_filter").and_then(serde_json::Value::as_str), std::option::Option::Some("warn"));
|
||||
assert_eq!(resolved.effective().get("default_filter").and_then(serde_json::Value::as_str), std::option::Option::Some("warn"));
|
||||
assert_eq!(resolved.origin("logs_directory"), std::option::Option::Some(super::ConfigValueOrigin::Global));
|
||||
assert_eq!(resolved.origin("default_filter"), std::option::Option::Some(super::ConfigValueOrigin::Profile));
|
||||
assert_eq!(
|
||||
resolved.profile().get("default_filter").and_then(serde_json::Value::as_str),
|
||||
resolved.effective().get("default_filter").and_then(serde_json::Value::as_str),
|
||||
);
|
||||
assert!(!resolved.effective().contains_key("default_profile"));
|
||||
assert!(!resolved.effective().contains_key("profiles"));
|
||||
}
|
||||
@@ -26,25 +30,33 @@ fn committed_default_profile_resolves_globals_profile_and_provenance() {
|
||||
|
||||
#[test]
|
||||
fn explicit_profile_selection_is_distinct_from_default_selection() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_engine();
|
||||
let file_id = crate::ConfigFileId::new(crate::FILE_ID_STD_LOGGING);
|
||||
assert!(engine.is_ok(), "committed Config engine should be constructible: {engine:?}");
|
||||
assert!(engine.is_ok(), "fixture Config engine should be constructible: {engine:?}");
|
||||
assert!(file_id.is_ok(), "logging file_id should be valid: {file_id:?}");
|
||||
if let (std::result::Result::Ok(engine), std::result::Result::Ok(file_id)) = (engine, file_id) {
|
||||
let resolved = engine.load_resolved_profile(&file_id, std::option::Option::Some("local_dev"));
|
||||
assert!(resolved.is_ok(), "explicit committed profile should resolve: {resolved:?}");
|
||||
if let std::result::Result::Ok(resolved) = resolved {
|
||||
assert_eq!(resolved.profile_id(), "local_dev");
|
||||
assert_eq!(resolved.selection_source(), super::ConfigProfileSelectionSource::Explicit);
|
||||
let document = engine.load_validated_document(&file_id);
|
||||
assert!(document.is_ok(), "committed Logging document should validate: {document:?}");
|
||||
if let std::result::Result::Ok(document) = document {
|
||||
let profile_id = document.value().get("default_profile").and_then(serde_json::Value::as_str);
|
||||
assert!(profile_id.is_some(), "validated Logging document should expose default_profile");
|
||||
if let std::option::Option::Some(profile_id) = profile_id {
|
||||
let resolved = engine.load_resolved_profile(&file_id, std::option::Option::Some(profile_id));
|
||||
assert!(resolved.is_ok(), "explicit committed profile should resolve: {resolved:?}");
|
||||
if let std::result::Result::Ok(resolved) = resolved {
|
||||
assert_eq!(resolved.profile_id(), profile_id);
|
||||
assert_eq!(resolved.selection_source(), super::ConfigProfileSelectionSource::Explicit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_explicit_profile_has_distinct_error_code() {
|
||||
let engine = committed_engine();
|
||||
let engine = fixture_engine();
|
||||
let file_id = crate::ConfigFileId::new(crate::FILE_ID_STD_LOGGING);
|
||||
assert!(engine.is_ok(), "committed Config engine should be constructible: {engine:?}");
|
||||
assert!(engine.is_ok(), "fixture Config engine should be constructible: {engine:?}");
|
||||
assert!(file_id.is_ok(), "logging file_id should be valid: {file_id:?}");
|
||||
if let (std::result::Result::Ok(engine), std::result::Result::Ok(file_id)) = (engine, file_id) {
|
||||
let result = engine.load_resolved_profile(&file_id, std::option::Option::Some("does-not-exist"));
|
||||
@@ -55,9 +67,10 @@ fn unknown_explicit_profile_has_distinct_error_code() {
|
||||
}
|
||||
}
|
||||
|
||||
fn committed_engine() -> ksp_core_lib::Result<crate::ConfigDocumentEngine> {
|
||||
fn fixture_engine() -> ksp_core_lib::Result<crate::ConfigDocumentEngine> {
|
||||
let workspace = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
|
||||
let bootstrap = crate::ConfigBootstrapOptions::from_paths(workspace.join("config"), workspace.join("config/schemas"));
|
||||
let fixture_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("unit_tests/fixtures");
|
||||
let bootstrap = crate::ConfigBootstrapOptions::from_paths(fixture_root, workspace.join("config/schemas"));
|
||||
let bootstrap = match bootstrap {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
|
||||
Reference in New Issue
Block a user