91 lines
5.3 KiB
Rust
91 lines
5.3 KiB
Rust
// file: crates/ksp-config-lib/unit_tests/packaging.rs
|
|
// version: 2
|
|
|
|
fn write_packaged_registry(resource_root: &std::path::Path, marker: &str) -> std::io::Result<()> {
|
|
let registry = crate::ConfigFileRegistry::defaults();
|
|
assert!(registry.is_ok(), "Config registry fixture should be constructible: {registry:?}");
|
|
if let std::result::Result::Ok(registry) = registry {
|
|
for descriptor in registry.descriptors() {
|
|
let root = match descriptor.kind() {
|
|
crate::ConfigFileKind::Config => resource_root.join(crate::DEFAULT_CFG_PATH),
|
|
crate::ConfigFileKind::Schema => resource_root.join(crate::DEFAULT_SCHEMA_PATH),
|
|
};
|
|
let create = std::fs::create_dir_all(root.as_path());
|
|
if let std::result::Result::Err(error) = create {
|
|
return std::result::Result::Err(error);
|
|
}
|
|
let path = root.join(descriptor.filename());
|
|
let content = format!("{marker}:{}", descriptor.file_id().as_str());
|
|
let write = std::fs::write(path, content.as_bytes());
|
|
if let std::result::Result::Err(error) = write {
|
|
return std::result::Result::Err(error);
|
|
}
|
|
}
|
|
}
|
|
return std::result::Result::Ok(());
|
|
}
|
|
|
|
#[test]
|
|
fn packaged_runtime_seeds_configs_and_synchronizes_schemas_without_overwriting_user_config() {
|
|
let resource = tempfile::tempdir();
|
|
assert!(resource.is_ok(), "resource fixture should be creatable: {resource:?}");
|
|
let runtime = tempfile::tempdir();
|
|
assert!(runtime.is_ok(), "runtime fixture should be creatable: {runtime:?}");
|
|
if let (std::result::Result::Ok(resource), std::result::Result::Ok(runtime)) = (resource, runtime) {
|
|
let packaged = write_packaged_registry(resource.path(), "first");
|
|
assert!(packaged.is_ok(), "packaged Config fixture should be writable: {packaged:?}");
|
|
let first = super::prepare_packaged_runtime_at(resource.path(), runtime.path());
|
|
assert!(first.is_ok(), "first packaged runtime should prepare: {first:?}");
|
|
if let std::result::Result::Ok(first) = first {
|
|
assert_eq!(first.runtime_root(), runtime.path());
|
|
assert_eq!(first.cfg_path(), runtime.path().join(crate::DEFAULT_CFG_PATH));
|
|
assert_eq!(first.schema_path(), runtime.path().join(crate::DEFAULT_SCHEMA_PATH));
|
|
let user_logging = first.cfg_path().join(crate::DEFAULT_STD_LOGGING_FILENAME);
|
|
let user_write = std::fs::write(user_logging.as_path(), b"user-owned-config");
|
|
assert!(user_write.is_ok(), "Config fixture should be replaceable: {user_write:?}");
|
|
let packaged = write_packaged_registry(resource.path(), "second");
|
|
assert!(packaged.is_ok(), "updated packaged fixture should be writable: {packaged:?}");
|
|
let second = super::prepare_packaged_runtime_at(resource.path(), runtime.path());
|
|
assert!(second.is_ok(), "second packaged runtime should prepare: {second:?}");
|
|
let retained = std::fs::read(user_logging.as_path());
|
|
assert!(retained.is_ok(), "retained Config fixture should remain readable: {retained:?}");
|
|
if let std::result::Result::Ok(retained) = retained {
|
|
assert_eq!(retained, b"user-owned-config");
|
|
}
|
|
let schema = first.schema_path().join(crate::DEFAULT_STD_LOGGING_SCHEMA_FILENAME);
|
|
let synchronized = std::fs::read_to_string(schema.as_path());
|
|
assert!(synchronized.is_ok(), "synchronized schema fixture should be readable: {synchronized:?}");
|
|
if let std::result::Result::Ok(synchronized) = synchronized {
|
|
assert!(synchronized.starts_with("second:"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[test]
|
|
fn packaged_runtime_rejects_symlink_destination() {
|
|
let resource = tempfile::tempdir();
|
|
assert!(resource.is_ok(), "resource fixture should be creatable: {resource:?}");
|
|
let runtime = tempfile::tempdir();
|
|
assert!(runtime.is_ok(), "runtime fixture should be creatable: {runtime:?}");
|
|
if let (std::result::Result::Ok(resource), std::result::Result::Ok(runtime)) = (resource, runtime) {
|
|
let packaged = write_packaged_registry(resource.path(), "packaged");
|
|
assert!(packaged.is_ok(), "packaged Config fixture should be writable: {packaged:?}");
|
|
let cfg = runtime.path().join(crate::DEFAULT_CFG_PATH);
|
|
let create = std::fs::create_dir_all(cfg.as_path());
|
|
assert!(create.is_ok(), "runtime Config root should be creatable: {create:?}");
|
|
let outside = runtime.path().join("outside.json");
|
|
let outside_write = std::fs::write(outside.as_path(), b"outside");
|
|
assert!(outside_write.is_ok(), "symlink target should be creatable: {outside_write:?}");
|
|
let link = cfg.join(crate::DEFAULT_STD_LOGGING_FILENAME);
|
|
let link_result = std::os::unix::fs::symlink(outside.as_path(), link.as_path());
|
|
assert!(link_result.is_ok(), "symlink fixture should be creatable: {link_result:?}");
|
|
let result = super::prepare_packaged_runtime_at(resource.path(), runtime.path());
|
|
assert!(result.is_err(), "symlink destination must be rejected");
|
|
if let std::result::Result::Err(error) = result {
|
|
assert_eq!(error.code(), crate::ERROR_CODE_PACKAGED_RUNTIME_PREPARATION_FAILED);
|
|
}
|
|
}
|
|
}
|