Files
khadhroony-solana-project/crates/ksp-config-lib/unit_tests/packaging.rs
2026-08-22 10:56:26 +02:00

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);
}
}
}