From 5abcd400d44e38a78b236203998f8297914f9c7b Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 28 Sep 2025 20:27:43 +0300 Subject: [PATCH] refactor(tests): fix clippy warnings --- src/trace.rs | 2 +- tests/common.rs | 27 ---------- tests/common/host.rs | 14 ++++++ tests/common/manifest.rs | 9 ++++ tests/common/mod.rs | 6 +++ tests/common/wasm.rs | 14 ++++++ tests/manifest.rs | 103 +++++++++++++++++++++++---------------- tests/wasm.rs | 5 +- 8 files changed, 106 insertions(+), 74 deletions(-) delete mode 100644 tests/common.rs create mode 100644 tests/common/host.rs create mode 100644 tests/common/manifest.rs create mode 100644 tests/common/mod.rs create mode 100644 tests/common/wasm.rs diff --git a/src/trace.rs b/src/trace.rs index f98801f..5c42f6b 100644 --- a/src/trace.rs +++ b/src/trace.rs @@ -82,7 +82,7 @@ pub fn save_trace>(trace: &[TraceEvent], path: P) -> Result<(), T Ok(()) } -/// Load a trace from a JSON file to Vec. +/// Load a trace from a JSON file to [`Vec`]. /// /// # Errors /// diff --git a/tests/common.rs b/tests/common.rs deleted file mode 100644 index 6ab46d1..0000000 --- a/tests/common.rs +++ /dev/null @@ -1,27 +0,0 @@ -use captra::{CapabilityManifest, HostState, add_wasm_linker_funcs, load_manifest}; -use ed25519_dalek::SigningKey; -use rand::rngs::OsRng; -use wasmtime::{Engine, Linker, Store}; - -/// Load the example manifest bundled with the repo. -pub fn load_example_manifest() -> CapabilityManifest { - load_manifest("examples/manifest.json").expect("examples/manifest.json must exists") -} - -/// Build a HostState with a fixed seed and a fresh SigningKey (OsRng). -pub fn make_host_with_seed(seed: u64) -> HostState { - let manifest = load_example_manifest(); - let mut csprng = OsRng; - let keypair = SigningKey::generate(&mut csprng); - HostState::new(manifest, seed, keypair) -} - -/// Create a wasmtime engine + linker with your host functions registered, -/// and a Store that owns the given HostState. -pub fn wasm_store_with_hosts(host: HostState) -> (Engine, Linker, Store) { - let engine = Engine::default(); - let mut linker = Linker::new(&engine); - add_wasm_linker_funcs(&mut linker).expect("linker registration"); - let store = Store::new(&engine, host); - (engine, linker, store) -} diff --git a/tests/common/host.rs b/tests/common/host.rs new file mode 100644 index 0000000..efb7955 --- /dev/null +++ b/tests/common/host.rs @@ -0,0 +1,14 @@ +use crate::common::manifest::load_example_manifest; +use captra::HostState; +use ed25519_dalek::SigningKey; +use rand::rngs::OsRng; + +/// Build a [`HostState`] with a fixed seed and a fresh [`SigningKey`] (`OsRng`). +/// # Panics +#[must_use] +pub fn make_host_with_seed(seed: u64) -> HostState { + let manifest = load_example_manifest(); + let mut csprng = OsRng; + let keypair = SigningKey::generate(&mut csprng); + HostState::new(manifest, seed, keypair) +} diff --git a/tests/common/manifest.rs b/tests/common/manifest.rs new file mode 100644 index 0000000..017d1c5 --- /dev/null +++ b/tests/common/manifest.rs @@ -0,0 +1,9 @@ +use captra::{CapabilityManifest, load_manifest}; + +/// Load the example manifest bundled with the repo. +/// # Panics +#[inline] +#[must_use] +pub fn load_example_manifest() -> CapabilityManifest { + load_manifest("examples/manifest.json").expect("examples/manifest.json must exists") +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..315f78a --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,6 @@ +#[allow(dead_code)] +pub mod host; +#[allow(dead_code)] +pub mod manifest; +#[allow(dead_code)] +pub mod wasm; diff --git a/tests/common/wasm.rs b/tests/common/wasm.rs new file mode 100644 index 0000000..5f8124f --- /dev/null +++ b/tests/common/wasm.rs @@ -0,0 +1,14 @@ +use captra::{HostState, add_wasm_linker_funcs}; +use wasmtime::{Engine, Linker, Store}; + +/// Create a wasmtime engine + linker with your host functions registered, +/// and a [`Store`] that owns the given [`HostState`]. +/// # Panics +#[must_use] +pub fn wasm_store_with_hosts(host: HostState) -> (Engine, Linker, Store) { + let engine = Engine::default(); + let mut linker = Linker::new(&engine); + add_wasm_linker_funcs(&mut linker).expect("linker registration"); + let store = Store::new(&engine, host); + (engine, linker, store) +} diff --git a/tests/manifest.rs b/tests/manifest.rs index fad8cc1..e83f824 100644 --- a/tests/manifest.rs +++ b/tests/manifest.rs @@ -1,3 +1,6 @@ +mod common; + +use crate::common::host::make_host_with_seed; use base64::{Engine, engine::general_purpose::STANDARD}; use captra::{ CapError, EventType, HostState, ManifestError, TraceEvent, init_tracing, load_manifest, @@ -83,67 +86,81 @@ fn manifest_validation_invalid() { } #[test] -fn host_enforcement_with_trace() { +fn host_enforcement_allowed() { init_tracing(); + let mut host = make_host_with_seed(12_345); - let manifest = assert_ok!(load_manifest("examples/manifest.json"), "Load failed"); - let fixed_seed = 12345; - let mut csprng = OsRng; - let keypair = SigningKey::generate(&mut csprng); - let mut host = HostState::new(manifest, fixed_seed, keypair); + let result = assert_ok!(host.execute_plugin("./workspace/config.toml")); + assert!(result); - assert_eq!(host.run_id(), "captra-run-12345"); + assert_eq!(host.trace().len(), 1); + let ev = assert_some!(host.trace().first()); - // allowed - expect a tracing event - let out1 = assert_ok!(host.execute_plugin("./workspace/config.toml")); - assert!(out1); - // denied - event + entry - let out2 = assert_err!(host.execute_plugin("/etc/passwd")); - assert_eq!(out2, CapError::GlobMismatch); + assert_eq!(ev.run_id, "captra-run-12345"); + assert_eq!(ev.seq, 1); + assert_matches!(ev.event_type, EventType::CapCall); + assert_eq!(ev.input, "./workspace/config.toml"); + assert!(ev.outcome); + assert_eq!(ev.ts_seed, 8_166_419_713_379_829_776); +} - { - assert_eq!(host.trace().len(), 2); // Both allowed/denied log to trace. +#[test] +fn host_enforcement_denied() { + init_tracing(); + let mut host = make_host_with_seed(12_345); - let trace1 = assert_some!(host.trace().get(0)); - assert_eq!(trace1.seq, 1); - assert_eq!(trace1.event_type, EventType::CapCall); - assert_eq!(trace1.input, "./workspace/config.toml"); - assert!(trace1.outcome); - assert_eq!(trace1.ts_seed, 8_166_419_713_379_829_776); - assert_ne!(trace1.ts_seed, 0); + let err = assert_err!(host.execute_plugin("/etc/passwd")); + assert_matches!(err, CapError::GlobMismatch); - let trace2 = assert_some!(host.trace().get(1)); - assert_eq!(trace2.run_id, "captra-run-12345"); - assert_eq!(trace2.seq, 2); - assert_eq!(trace2.event_type, EventType::CapCall); - assert!(!trace2.outcome); - assert!(trace2.input.starts_with("glob_mismatch: ")); - assert_eq!(trace2.ts_seed, 10_553_447_931_939_622_718); - assert_ne!(trace1.ts_seed, trace2.ts_seed); - } + assert_eq!(host.trace().len(), 1); + let ev = assert_some!(host.trace().first()); + + assert_eq!(ev.run_id, "captra-run-12345"); + assert_eq!(ev.seq, 1); + assert_matches!(ev.event_type, EventType::CapCall); + assert!(!ev.outcome); + assert!(ev.input.starts_with("glob_mismatch: ")); + assert_eq!(ev.ts_seed, 8_166_419_713_379_829_776); +} + +#[test] +fn host_enforcement_signed() { + init_tracing(); + let mut host = make_host_with_seed(12_345); + + let _ = assert_ok!(host.execute_plugin("./workspace/config.toml")); let signed = assert_ok!(host.sign_current_trace()); assert_eq!(signed.run_id, "captra-run-12345"); - let sig_bytes = STANDARD.decode(&signed.signature).expect("Base64 decode"); + let sig_bytes = STANDARD.decode(&signed.signature).expect("base64 decode"); assert_eq!(sig_bytes.len(), 64); assert!(!signed.trace_json.is_empty()); // Nonempty JSON +} - // Save/load roundtrip - let tmp_dir = tempdir().expect("Temp dir failed"); +#[test] +fn host_enforcement_save_round_trip() { + init_tracing(); + let mut host = make_host_with_seed(12_345); + + let _ = assert_ok!(host.execute_plugin("./workspace/config.toml")); + let _ = assert_err!(host.execute_plugin("/etc/passwd")); + + let tmp_dir = tempdir().expect("tempdir"); let tmp_path = tmp_dir.as_ref().join("trace.json"); + + // Save and laod assert_ok!(host.save_current_trace(&tmp_path), "Save failed"); - let loaded_trace = assert_ok!(load_trace(tmp_path), "Load failed"); - assert_eq!(loaded_trace.len(), 2); + let loaded = assert_ok!(load_trace(tmp_path), "Load failed"); + assert_eq!(loaded.len(), 2); - let trace1_refetched = assert_some!(host.trace().get(0)); - let trace2_refetched = assert_some!(host.trace().get(1)); - let loaded_trace1 = assert_some!(loaded_trace.get(0)); - let loaded_trace2 = assert_some!(loaded_trace.get(1)); + let current_trace = host.trace(); + assert_eq!(loaded, current_trace); - assert_eq!(trace1_refetched, loaded_trace1); - assert_eq!(trace2_refetched, loaded_trace2); + let loaded_first = assert_some!(loaded.first()); + let current_first = assert_some!(current_trace.first()); + assert_eq!(loaded_first, current_first); } #[test] @@ -152,7 +169,7 @@ fn trace_reproducibility() { let manifest = assert_ok!(load_manifest("examples/manifest.json"), "Load failed"); - let fixed_seed = 12345; + let fixed_seed = 12_345; let mut csprng1 = OsRng; let keypair1 = SigningKey::generate(&mut csprng1); diff --git a/tests/wasm.rs b/tests/wasm.rs index 5b21cfb..1bea031 100644 --- a/tests/wasm.rs +++ b/tests/wasm.rs @@ -1,11 +1,10 @@ mod common; +use crate::common::{host::make_host_with_seed, wasm::wasm_store_with_hosts}; use captra::HostStatus; use claims::{assert_ok, assert_some}; use wasmtime::Module; -use crate::common::{make_host_with_seed, wasm_store_with_hosts}; - #[test] fn wasm_integration_allowed() { let host = make_host_with_seed(12345); @@ -28,7 +27,7 @@ fn wasm_integration_allowed() { ) ) "#, - len = path.as_bytes().len() + len = path.len() ); let module = assert_ok!(Module::new(&engine, &wat));