From 50bc39ca80cfd38ab56515b247788c2d7e3afafc Mon Sep 17 00:00:00 2001 From: branchseer Date: Wed, 12 Nov 2025 17:04:00 +0800 Subject: [PATCH 1/2] test: trace shared_memory in fspy tests --- Cargo.lock | 2 ++ crates/fspy/Cargo.toml | 1 + crates/fspy/tests/node_fs.rs | 7 ++++--- crates/fspy/tests/rust_std.rs | 9 +++++---- crates/fspy/tests/rust_tokio.rs | 9 +++++---- crates/fspy/tests/static_executable.rs | 21 +++++++++++---------- crates/fspy_shared/Cargo.toml | 4 ++-- 7 files changed, 30 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c3764ca..d99662ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1027,6 +1027,7 @@ dependencies = [ "rand 0.9.2", "tar", "tempfile", + "test-log", "thiserror 2.0.17", "tokio", "which", @@ -2694,6 +2695,7 @@ checksum = "ba8593196da75d9dc4f69349682bd4c2099f8cde114257d1ef7ef1b33d1aba54" dependencies = [ "cfg-if", "libc", + "log", "nix 0.23.2", "rand 0.8.5", "win-sys", diff --git a/crates/fspy/Cargo.toml b/crates/fspy/Cargo.toml index 57dae313..bd517ca2 100644 --- a/crates/fspy/Cargo.toml +++ b/crates/fspy/Cargo.toml @@ -46,6 +46,7 @@ tempfile = { workspace = true } anyhow = { workspace = true } csv-async = { workspace = true } ctor = { workspace = true } +test-log = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread", "macros", "fs", "io-std"] } [target.'cfg(all(target_os = "linux", target_arch = "aarch64"))'.dev-dependencies] diff --git a/crates/fspy/tests/node_fs.rs b/crates/fspy/tests/node_fs.rs index f1563663..3bed927f 100644 --- a/crates/fspy/tests/node_fs.rs +++ b/crates/fspy/tests/node_fs.rs @@ -3,6 +3,7 @@ mod test_utils; use std::env::{current_dir, vars_os}; use fspy::{AccessMode, PathAccessIterable}; +use test_log::test; use test_utils::assert_contains; async fn track_node_script(script: &str) -> anyhow::Result { @@ -17,21 +18,21 @@ async fn track_node_script(script: &str) -> anyhow::Result { Ok(termination.path_accesses) } -#[tokio::test] +#[test(tokio::test)] async fn read_sync() -> anyhow::Result<()> { let accesses = track_node_script("try { fs.readFileSync('hello') } catch {}").await?; assert_contains(&accesses, current_dir().unwrap().join("hello").as_path(), AccessMode::Read); Ok(()) } -#[tokio::test] +#[test(tokio::test)] async fn read_dir_sync() -> anyhow::Result<()> { let accesses = track_node_script("try { fs.readdirSync('.') } catch {}").await?; assert_contains(&accesses, ¤t_dir().unwrap(), AccessMode::ReadDir); Ok(()) } -#[tokio::test] +#[test(tokio::test)] async fn subprocess() -> anyhow::Result<()> { let cmd = if cfg!(windows) { r"'cmd', ['/c', 'type hello']" diff --git a/crates/fspy/tests/rust_std.rs b/crates/fspy/tests/rust_std.rs index 7f63533b..b7cb0af2 100644 --- a/crates/fspy/tests/rust_std.rs +++ b/crates/fspy/tests/rust_std.rs @@ -8,9 +8,10 @@ use std::{ }; use fspy::AccessMode; +use test_log::test; use test_utils::assert_contains; -#[tokio::test] +#[test(tokio::test)] async fn open_read() -> anyhow::Result<()> { let accesses = track_child!({ let _ = File::open("hello"); @@ -21,7 +22,7 @@ async fn open_read() -> anyhow::Result<()> { Ok(()) } -#[tokio::test] +#[test(tokio::test)] async fn open_write() -> anyhow::Result<()> { let accesses = track_child!({ let path = format!("{}/hello", env!("CARGO_TARGET_TMPDIR")); @@ -37,7 +38,7 @@ async fn open_write() -> anyhow::Result<()> { Ok(()) } -#[tokio::test] +#[test(tokio::test)] async fn readdir() -> anyhow::Result<()> { let accesses = track_child!({ let path = format!("{}/hello", env!("CARGO_TARGET_TMPDIR")); @@ -53,7 +54,7 @@ async fn readdir() -> anyhow::Result<()> { Ok(()) } -#[tokio::test] +#[test(tokio::test)] async fn subprocess() -> anyhow::Result<()> { let accesses = track_child!({ let mut command = if cfg!(windows) { diff --git a/crates/fspy/tests/rust_tokio.rs b/crates/fspy/tests/rust_tokio.rs index c73c1514..30ab1a41 100644 --- a/crates/fspy/tests/rust_tokio.rs +++ b/crates/fspy/tests/rust_tokio.rs @@ -3,10 +3,11 @@ mod test_utils; use std::{env::current_dir, path::Path, process::Stdio}; use fspy::AccessMode; +use test_log::test; use test_utils::assert_contains; use tokio::fs::OpenOptions; -#[tokio::test] +#[test(tokio::test)] async fn open_read() -> anyhow::Result<()> { let accesses = track_child!({ tokio::runtime::Builder::new_current_thread().enable_io().build().unwrap().block_on( @@ -21,7 +22,7 @@ async fn open_read() -> anyhow::Result<()> { Ok(()) } -#[tokio::test] +#[test(tokio::test)] async fn open_write() -> anyhow::Result<()> { let accesses = track_child!({ let path = format!("{}/hello", env!("CARGO_TARGET_TMPDIR")); @@ -42,7 +43,7 @@ async fn open_write() -> anyhow::Result<()> { Ok(()) } -#[tokio::test] +#[test(tokio::test)] async fn readdir() -> anyhow::Result<()> { let accesses = track_child!({ let path = format!("{}/hello", env!("CARGO_TARGET_TMPDIR")); @@ -63,7 +64,7 @@ async fn readdir() -> anyhow::Result<()> { Ok(()) } -#[tokio::test] +#[test(tokio::test)] async fn subprocess() -> anyhow::Result<()> { let accesses = track_child!({ tokio::runtime::Builder::new_current_thread().enable_io().build().unwrap().block_on( diff --git a/crates/fspy/tests/static_executable.rs b/crates/fspy/tests/static_executable.rs index d02bc2df..8fe3319b 100644 --- a/crates/fspy/tests/static_executable.rs +++ b/crates/fspy/tests/static_executable.rs @@ -9,6 +9,7 @@ use std::{ use fspy::PathAccessIterable; use fspy_shared_unix::is_dynamically_linked_to_libc; +use test_log::test; use crate::test_utils::assert_contains; @@ -49,61 +50,61 @@ async fn track_test_bin(args: &[&str], cwd: Option<&str>) -> PathAccessIterable termination.path_accesses } -#[tokio::test] +#[test(tokio::test)] async fn open_read() { let accesses = track_test_bin(&["open_read", "/hello"], None).await; assert_contains(&accesses, Path::new("/hello"), fspy::AccessMode::Read); } -#[tokio::test] +#[test(tokio::test)] async fn open_write() { let accesses = track_test_bin(&["open_write", "/hello"], None).await; assert_contains(&accesses, Path::new("/hello"), fspy::AccessMode::Write); } -#[tokio::test] +#[test(tokio::test)] async fn open_readwrite() { let accesses = track_test_bin(&["open_readwrite", "/hello"], None).await; assert_contains(&accesses, Path::new("/hello"), fspy::AccessMode::ReadWrite); } -#[tokio::test] +#[test(tokio::test)] async fn openat2_read() { let accesses = track_test_bin(&["openat2_read", "/hello"], None).await; assert_contains(&accesses, Path::new("/hello"), fspy::AccessMode::Read); } -#[tokio::test] +#[test(tokio::test)] async fn openat2_write() { let accesses = track_test_bin(&["openat2_write", "/hello"], None).await; assert_contains(&accesses, Path::new("/hello"), fspy::AccessMode::Write); } -#[tokio::test] +#[test(tokio::test)] async fn openat2_readwrite() { let accesses = track_test_bin(&["openat2_readwrite", "/hello"], None).await; assert_contains(&accesses, Path::new("/hello"), fspy::AccessMode::ReadWrite); } -#[tokio::test] +#[test(tokio::test)] async fn open_relative() { let accesses = track_test_bin(&["open_read", "hello"], Some("/home")).await; assert_contains(&accesses, Path::new("/home/hello"), fspy::AccessMode::Read); } -#[tokio::test] +#[test(tokio::test)] async fn readdir() { let accesses = track_test_bin(&["readdir", "/home"], None).await; assert_contains(&accesses, Path::new("/home"), fspy::AccessMode::ReadDir); } -#[tokio::test] +#[test(tokio::test)] async fn stat() { let accesses = track_test_bin(&["stat", "/hello"], None).await; assert_contains(&accesses, Path::new("/hello"), fspy::AccessMode::Read); } -#[tokio::test] +#[test(tokio::test)] async fn execve() { let accesses = track_test_bin(&["execve", "/hello"], None).await; assert_contains(&accesses, Path::new("/hello"), fspy::AccessMode::Read); diff --git a/crates/fspy_shared/Cargo.toml b/crates/fspy_shared/Cargo.toml index af59d2fa..c808828c 100644 --- a/crates/fspy_shared/Cargo.toml +++ b/crates/fspy_shared/Cargo.toml @@ -9,7 +9,7 @@ allocator-api2 = { workspace = true } bincode = { workspace = true } bstr = { workspace = true } bytemuck = { workspace = true, features = ["must_cast"] } -shared_memory = { workspace = true } +shared_memory = { workspace = true, features = ["logging"] } thiserror = { workspace = true } tracing = { workspace = true } uuid = { workspace = true, features = ["v4"] } @@ -24,4 +24,4 @@ winsafe = { workspace = true } assert2 = { workspace = true } ctor = { workspace = true } fspy_test_utils = { workspace = true } -shared_memory = { workspace = true } +shared_memory = { workspace = true, features = ["logging"] } From fc359bfb86f90eeb6901d48aec3ea1df38c402c8 Mon Sep 17 00:00:00 2001 From: branchseer Date: Wed, 12 Nov 2025 20:39:50 +0800 Subject: [PATCH 2/2] inherit envs for child processes --- crates/fspy/tests/test_utils.rs | 4 +++- crates/fspy_test_utils/src/lib.rs | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/fspy/tests/test_utils.rs b/crates/fspy/tests/test_utils.rs index dc8a5a8d..bfaf9d57 100644 --- a/crates/fspy/tests/test_utils.rs +++ b/crates/fspy/tests/test_utils.rs @@ -46,7 +46,9 @@ macro_rules! track_child { #[allow(unused)] pub async fn spawn_std(std_cmd: std::process::Command) -> anyhow::Result { let mut command = fspy::Command::new(std_cmd.get_program()); - command.args(std_cmd.get_args()); + command + .args(std_cmd.get_args()) + .envs(std_cmd.get_envs().filter_map(|(name, value)| Some((name, value?)))); let termination = command.spawn().await?.wait_handle.await?; assert!(termination.status.success()); diff --git a/crates/fspy_test_utils/src/lib.rs b/crates/fspy_test_utils/src/lib.rs index ff7ac348..0b17b254 100644 --- a/crates/fspy_test_utils/src/lib.rs +++ b/crates/fspy_test_utils/src/lib.rs @@ -54,6 +54,9 @@ pub fn create_command(id: &str, arg: impl Encode) -> Command { let arg_base64 = BASE64_STANDARD_NO_PAD.encode(&arg_bytes); command.arg(id).arg(arg_base64); + // Set inherit environment explicitly, in case it needs to be converted to fspy::Command later + command.env_clear().envs(std::env::vars_os()); + command }