v0.2.6-pre.004
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/unit_tests/wallet_config.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
#[test]
|
||||
fn directory_preparation_creates_missing_root_and_nested_profile_path() {
|
||||
@@ -37,6 +37,30 @@ fn directory_preparation_rejects_existing_non_directory_root() {
|
||||
cleanup_fixture(root.as_path());
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn global_wallet_root_rejects_symbolic_link() {
|
||||
let root = fixture_path("root-symlink");
|
||||
let outside = fixture_path("root-symlink-outside");
|
||||
cleanup_fixture(root.as_path());
|
||||
cleanup_fixture(outside.as_path());
|
||||
let outside_created = std::fs::create_dir_all(outside.as_path());
|
||||
assert!(outside_created.is_ok());
|
||||
if outside_created.is_ok() {
|
||||
let linked = std::os::unix::fs::symlink(outside.as_path(), root.as_path());
|
||||
assert!(linked.is_ok());
|
||||
if linked.is_ok() {
|
||||
let result = super::ensure_global_wallet_root(root.as_path());
|
||||
assert!(result.is_err());
|
||||
if let std::result::Result::Err(error) = result {
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_WALLET_DIRECTORY_INVALID);
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanup_fixture(root.as_path());
|
||||
cleanup_fixture(outside.as_path());
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn profile_directory_preparation_rejects_symbolic_link_components() {
|
||||
|
||||
124
crates/ksp-app-wallet-desk/unit_tests/wallet_inventory.rs
Normal file
124
crates/ksp-app-wallet-desk/unit_tests/wallet_inventory.rs
Normal file
@@ -0,0 +1,124 @@
|
||||
// file: crates/ksp-app-wallet-desk/unit_tests/wallet_inventory.rs
|
||||
// version: 1
|
||||
|
||||
const VALID_WALLET: &[u8] = include_bytes!("../../ksp-wallet-lib/tests/fixtures/kspwallet_v1_full_vector.json");
|
||||
|
||||
#[test]
|
||||
fn inventory_lists_regular_wallets_reports_invalid_candidates_and_ignores_other_entries() {
|
||||
let root = fixture_path("inventory");
|
||||
cleanup_fixture(root.as_path());
|
||||
let created = std::fs::create_dir_all(root.as_path());
|
||||
assert!(created.is_ok(), "inventory fixture root should be creatable: {created:?}");
|
||||
if created.is_ok() {
|
||||
assert!(std::fs::write(root.join("beta.kspwallet"), VALID_WALLET).is_ok());
|
||||
assert!(std::fs::write(root.join("alpha.kspwallet"), b"not-json").is_ok());
|
||||
assert!(std::fs::write(root.join("ignored.txt"), VALID_WALLET).is_ok());
|
||||
assert!(std::fs::create_dir(root.join("directory.kspwallet")).is_ok());
|
||||
let runtime = tokio::runtime::Builder::new_current_thread().build();
|
||||
assert!(runtime.is_ok(), "test runtime should be constructible: {runtime:?}");
|
||||
if let std::result::Result::Ok(runtime) = runtime {
|
||||
let inventory = runtime.block_on(crate::list_wallet_inventory(root.as_path()));
|
||||
assert!(inventory.is_ok(), "inventory should complete: {inventory:?}");
|
||||
if let std::result::Result::Ok(entries) = inventory {
|
||||
assert_eq!(entries.len(), 2);
|
||||
assert_eq!(entries[0].filename, "alpha.kspwallet");
|
||||
assert_eq!(entries[0].inspection_status, crate::WalletInspectionStatusDto::Invalid);
|
||||
assert_eq!(entries[0].state, crate::WalletInventoryStateDto::Error);
|
||||
assert!(entries[0].diagnostic.is_some());
|
||||
assert_eq!(entries[1].filename, "beta.kspwallet");
|
||||
assert_eq!(entries[1].inspection_status, crate::WalletInspectionStatusDto::Valid);
|
||||
assert_eq!(entries[1].state, crate::WalletInventoryStateDto::Locked);
|
||||
assert_eq!(entries[1].format_version, std::option::Option::Some(1));
|
||||
assert!(entries[1].view_enabled.is_some());
|
||||
assert!(entries[1].diagnostic.is_none());
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanup_fixture(root.as_path());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selection_rejects_traversal_and_reinspects_one_valid_locked_wallet() {
|
||||
let root = fixture_path("selection");
|
||||
cleanup_fixture(root.as_path());
|
||||
let created = std::fs::create_dir_all(root.as_path());
|
||||
assert!(created.is_ok(), "selection fixture root should be creatable: {created:?}");
|
||||
if created.is_ok() {
|
||||
assert!(std::fs::write(root.join("selected.kspwallet"), VALID_WALLET).is_ok());
|
||||
let runtime = tokio::runtime::Builder::new_current_thread().build();
|
||||
assert!(runtime.is_ok(), "test runtime should be constructible: {runtime:?}");
|
||||
if let std::result::Result::Ok(runtime) = runtime {
|
||||
let rejected = runtime
|
||||
.block_on(crate::select_locked_wallet(root.as_path(), crate::WalletSelectionRequestDto { wallet_id: "../selected.kspwallet".to_owned() }));
|
||||
assert!(rejected.is_err());
|
||||
if let std::result::Result::Err(error) = rejected {
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_WALLET_SELECTION_INVALID);
|
||||
}
|
||||
let rejected_backslash = runtime
|
||||
.block_on(crate::select_locked_wallet(root.as_path(), crate::WalletSelectionRequestDto { wallet_id: "..\\selected.kspwallet".to_owned() }));
|
||||
assert!(rejected_backslash.is_err());
|
||||
if let std::result::Result::Err(error) = rejected_backslash {
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_WALLET_SELECTION_INVALID);
|
||||
}
|
||||
let selected =
|
||||
runtime.block_on(crate::select_locked_wallet(root.as_path(), crate::WalletSelectionRequestDto { wallet_id: "selected.kspwallet".to_owned() }));
|
||||
assert!(selected.is_ok(), "valid locked Wallet should be selectable: {selected:?}");
|
||||
if let std::result::Result::Ok(selected) = selected {
|
||||
assert_eq!(selected.wallet_id, "selected.kspwallet");
|
||||
assert_eq!(selected.filename, "selected.kspwallet");
|
||||
assert_eq!(selected.format_version, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanup_fixture(root.as_path());
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn inventory_and_selection_exclude_symbolic_link_wallet_entries() {
|
||||
let root = fixture_path("symlink-inventory");
|
||||
let outside = fixture_path("symlink-wallet");
|
||||
cleanup_fixture(root.as_path());
|
||||
cleanup_fixture(outside.as_path());
|
||||
let root_created = std::fs::create_dir_all(root.as_path());
|
||||
let outside_written = std::fs::write(outside.as_path(), VALID_WALLET);
|
||||
assert!(root_created.is_ok());
|
||||
assert!(outside_written.is_ok());
|
||||
if root_created.is_ok() && outside_written.is_ok() {
|
||||
let linked = std::os::unix::fs::symlink(outside.as_path(), root.join("linked.kspwallet"));
|
||||
assert!(linked.is_ok());
|
||||
if linked.is_ok() {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread().build();
|
||||
assert!(runtime.is_ok());
|
||||
if let std::result::Result::Ok(runtime) = runtime {
|
||||
let inventory = runtime.block_on(crate::list_wallet_inventory(root.as_path()));
|
||||
assert_eq!(inventory.as_ref().ok().map(std::vec::Vec::len), std::option::Option::Some(0));
|
||||
let selected = runtime
|
||||
.block_on(crate::select_locked_wallet(root.as_path(), crate::WalletSelectionRequestDto { wallet_id: "linked.kspwallet".to_owned() }));
|
||||
assert!(selected.is_err());
|
||||
if let std::result::Result::Err(error) = selected {
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_WALLET_SELECTION_INVALID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanup_fixture(root.as_path());
|
||||
cleanup_fixture(outside.as_path());
|
||||
}
|
||||
|
||||
fn fixture_path(name: &str) -> std::path::PathBuf {
|
||||
return std::env::temp_dir().join(std::format!("ksp-wallet-desk-{name}-{}", std::process::id()));
|
||||
}
|
||||
|
||||
fn cleanup_fixture(path: &std::path::Path) {
|
||||
let metadata = std::fs::symlink_metadata(path);
|
||||
match metadata {
|
||||
std::result::Result::Ok(metadata) if metadata.is_dir() && !metadata.file_type().is_symlink() => {
|
||||
let _ = std::fs::remove_dir_all(path);
|
||||
},
|
||||
std::result::Result::Ok(_) => {
|
||||
let _ = std::fs::remove_file(path);
|
||||
},
|
||||
std::result::Result::Err(_) => {},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user