v0.1.4-pre.003
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/management.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
static NEXT_FIXTURE_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
|
||||
|
||||
@@ -41,6 +41,176 @@ fn raw_management_read_remains_available_for_schema_invalid_source() {
|
||||
cleanup_fixture(&fixture);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_raw_source_candidate_is_persisted_exactly_and_reports_reload() {
|
||||
let fixture = management_fixture();
|
||||
let fixture = match fixture {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let original = std::fs::read_to_string(fixture.config_path.as_path());
|
||||
let original = match original {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let candidate = original.replace(" \"logs_directory\":", " \"logs_directory\":");
|
||||
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");
|
||||
let file_id = crate::ConfigFileId::new(crate::FILE_ID_STD_LOGGING);
|
||||
let file_id = match file_id {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let saved = fixture.management.save_source_candidate(&file_id, candidate.as_str());
|
||||
assert!(saved.is_ok(), "valid raw source candidate should persist: {saved:?}");
|
||||
if let std::result::Result::Ok(saved) = saved {
|
||||
assert!(saved.source_changed());
|
||||
assert!(saved.reload_required());
|
||||
}
|
||||
assert_eq!(std::fs::read_to_string(fixture.config_path.as_path()).ok(), std::option::Option::Some(candidate.clone()));
|
||||
let reloaded = fixture.management.load_logging_document();
|
||||
assert!(reloaded.is_ok(), "raw source persistence must leave a valid managed document: {reloaded:?}");
|
||||
let unchanged = fixture.management.save_source_candidate(&file_id, candidate.as_str());
|
||||
assert!(unchanged.is_ok(), "identical raw source candidate should succeed: {unchanged:?}");
|
||||
if let std::result::Result::Ok(unchanged) = unchanged {
|
||||
assert!(!unchanged.source_changed());
|
||||
assert!(!unchanged.reload_required());
|
||||
}
|
||||
cleanup_fixture(&fixture);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_json_source_candidate_is_rejected_without_modifying_existing_file() {
|
||||
let fixture = management_fixture();
|
||||
let fixture = match fixture {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let before = std::fs::read(fixture.config_path.as_path());
|
||||
let before = match before {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let file_id = crate::ConfigFileId::new(crate::FILE_ID_STD_LOGGING);
|
||||
let file_id = match file_id {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let saved = fixture.management.save_source_candidate(&file_id, "{");
|
||||
assert!(saved.is_err(), "invalid JSON candidate must be rejected");
|
||||
if let std::result::Result::Err(error) = saved {
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_JSON_SYNTAX_INVALID);
|
||||
}
|
||||
assert_eq!(std::fs::read(fixture.config_path.as_path()).ok(), std::option::Option::Some(before));
|
||||
cleanup_fixture(&fixture);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn schema_invalid_source_candidate_is_rejected_without_modifying_existing_file() {
|
||||
let fixture = management_fixture();
|
||||
let fixture = match fixture {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let before = std::fs::read(fixture.config_path.as_path());
|
||||
let before = match before {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let file_id = crate::ConfigFileId::new(crate::FILE_ID_STD_LOGGING);
|
||||
let file_id = match file_id {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let saved = fixture.management.save_source_candidate(&file_id, "{\"format_version\":1}");
|
||||
assert!(saved.is_err(), "schema-invalid candidate must be rejected");
|
||||
if let std::result::Result::Err(error) = saved {
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_SCHEMA_VALIDATION_FAILED);
|
||||
}
|
||||
assert_eq!(std::fs::read(fixture.config_path.as_path()).ok(), std::option::Option::Some(before));
|
||||
cleanup_fixture(&fixture);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn semantic_invalid_source_candidate_is_rejected_without_modifying_existing_file() {
|
||||
let fixture = management_fixture();
|
||||
let fixture = match fixture {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let before = std::fs::read_to_string(fixture.config_path.as_path());
|
||||
let before = match before {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let candidate = before.replace("\"default_profile\": \"local_dev\"", "\"default_profile\": \"missing\"");
|
||||
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 {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => {
|
||||
cleanup_fixture(&fixture);
|
||||
return;
|
||||
},
|
||||
};
|
||||
let saved = fixture.management.save_source_candidate(&file_id, candidate.as_str());
|
||||
assert!(saved.is_err(), "semantic-invalid candidate must be rejected");
|
||||
if let std::result::Result::Err(error) = saved {
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_DOCUMENT_SEMANTIC_INVALID);
|
||||
}
|
||||
assert_eq!(std::fs::read_to_string(fixture.config_path.as_path()).ok(), std::option::Option::Some(before));
|
||||
cleanup_fixture(&fixture);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_source_candidate_rejects_schema_and_unknown_file_ids_without_filesystem_escape() {
|
||||
let fixture = management_fixture();
|
||||
let fixture = match fixture {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let schema_file_id = crate::ConfigFileId::new(crate::FILE_ID_SCHEMA_STD_LOGGING);
|
||||
if let std::result::Result::Ok(schema_file_id) = schema_file_id {
|
||||
let saved = fixture.management.save_source_candidate(&schema_file_id, "{}");
|
||||
assert!(saved.is_err(), "schema file_id must not be writable through Config source management");
|
||||
if let std::result::Result::Err(error) = saved {
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_MANAGEMENT_OPERATION_INVALID);
|
||||
}
|
||||
}
|
||||
let unknown_file_id = crate::ConfigFileId::new("cfg.not.registered");
|
||||
if let std::result::Result::Ok(unknown_file_id) = unknown_file_id {
|
||||
let saved = fixture.management.save_source_candidate(&unknown_file_id, "{}");
|
||||
assert!(saved.is_err(), "unknown Config file_id must not become an arbitrary filesystem write");
|
||||
if let std::result::Result::Err(error) = saved {
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_FILE_ID_UNKNOWN);
|
||||
}
|
||||
}
|
||||
assert!(!fixture.root.join("not.registered").exists());
|
||||
cleanup_fixture(&fixture);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_logging_document_can_be_mutated_validated_and_persisted_atomically() {
|
||||
let fixture = management_fixture();
|
||||
|
||||
Reference in New Issue
Block a user