diff --git a/crates/fspy/src/unix/mod.rs b/crates/fspy/src/unix/mod.rs index 48cb6a8943..5abc24a1d2 100644 --- a/crates/fspy/src/unix/mod.rs +++ b/crates/fspy/src/unix/mod.rs @@ -73,6 +73,12 @@ impl SpyInner { #[cfg(target_os = "macos")] pub fn init_in(dir: &Path) -> io::Result { + const PRELOAD_CDYLIB: Fixture = Fixture { + name: "fspy_preload", + content: PRELOAD_CDYLIB_BINARY, + hash: formatcp!("{:x}", xxh3_128(PRELOAD_CDYLIB_BINARY)), + }; + use const_format::formatcp; use xxhash_rust::const_xxh3::xxh3_128; @@ -80,12 +86,6 @@ impl SpyInner { let coreutils_path = macos_fixtures::COREUTILS_BINARY.write_to(dir, "")?; let bash_path = macos_fixtures::OILS_BINARY.write_to(dir, "")?; - const PRELOAD_CDYLIB: Fixture = Fixture { - name: "fspy_preload", - content: PRELOAD_CDYLIB_BINARY, - hash: formatcp!("{:x}", xxh3_128(PRELOAD_CDYLIB_BINARY)), - }; - let preload_cdylib_path = PRELOAD_CDYLIB.write_to(dir, ".dylib")?; let fixtures = Fixtures { bash_path: bash_path.as_path().into(), //Path::new("/opt/homebrew/bin/bash"),//brush.as_path(), @@ -154,8 +154,9 @@ impl PathAccessIterable { // https://github.com/nodejs/node/blob/5794e644b724c6c6cac02d306d87a4d6b78251e5/deps/uv/src/unix/core.c#L803-L808 fn duplicate_until_safe(mut fd: OwnedFd) -> io::Result { - let mut fds: Vec = vec![]; const SAFE_FD_NUM: RawFd = 17; + + let mut fds: Vec = vec![]; while fd.as_raw_fd() < SAFE_FD_NUM { let new_fd = fd.try_clone()?; fds.push(fd); diff --git a/crates/fspy_preload_unix/src/client/mod.rs b/crates/fspy_preload_unix/src/client/mod.rs index 273b4e9432..8bce31abb7 100644 --- a/crates/fspy_preload_unix/src/client/mod.rs +++ b/crates/fspy_preload_unix/src/client/mod.rs @@ -211,6 +211,13 @@ impl Client { file_actions: &mut *const libc::posix_spawn_file_actions_t, attrp: *const libc::posix_spawnattr_t, ) -> nix::Result<()> { + unsafe extern "C" { + unsafe fn posix_spawn_file_actions_addinherit_np( + actions: *mut libc::posix_spawn_file_actions_t, + fd: libc::c_int, + ) -> libc::c_int; + } + use core::mem::zeroed; use libc::c_short; @@ -229,13 +236,6 @@ impl Client { return Ok(()); } - unsafe extern "C" { - unsafe fn posix_spawn_file_actions_addinherit_np( - actions: *mut libc::posix_spawn_file_actions_t, - fd: libc::c_int, - ) -> libc::c_int; - } - // ensure ipc fd is inherited when POSIX_SPAWN_CLOEXEC_DEFAULT is set. if (*file_actions).is_null() { let shared_file_actions = self.posix_spawn_file_actions.get_or_init(|| { @@ -285,9 +285,6 @@ pub unsafe fn handle_open(path: impl ToAbsolutePath, mode: impl ToAccessMode) { #[cfg(not(test))] #[ctor::ctor] fn init_client() { - use libc::pthread_atfork; - - CLIENT.set(Client::from_env()).unwrap(); unsafe extern "C" fn reset_shm_atfork() { let Some(client) = global_client() else { return; @@ -301,6 +298,10 @@ fn init_client() { shm_cursor.position = shm_cursor.mmap_mut.len(); }); } + + use libc::pthread_atfork; + + CLIENT.set(Client::from_env()).unwrap(); let ret = unsafe { pthread_atfork(None, None, Some(reset_shm_atfork)) }; if ret != 0 { panic!("pthread_atfork failed: {}", ret); diff --git a/crates/fspy_shared_unix/src/spawn/macos.rs b/crates/fspy_shared_unix/src/spawn/macos.rs index f7ad7e740c..ad053ed10d 100644 --- a/crates/fspy_shared_unix/src/spawn/macos.rs +++ b/crates/fspy_shared_unix/src/spawn/macos.rs @@ -29,6 +29,8 @@ pub fn handle_exec( command: &mut Exec, encoded_payload: &EncodedPayload, ) -> nix::Result> { + const DYLD_INSERT_LIBRARIES: &[u8] = b"DYLD_INSERT_LIBRARIES"; + if command.program.first() != Some(&b'/') { let program = absolute(OsStr::from_bytes(&command.program)).expect("Failed to get absolute path"); @@ -65,7 +67,6 @@ pub fn handle_exec( true }; - const DYLD_INSERT_LIBRARIES: &[u8] = b"DYLD_INSERT_LIBRARIES"; if injectable { ensure_env( &mut command.envs, diff --git a/crates/vite_package_manager/src/request.rs b/crates/vite_package_manager/src/request.rs index fb93839dd9..5debc04532 100644 --- a/crates/vite_package_manager/src/request.rs +++ b/crates/vite_package_manager/src/request.rs @@ -416,6 +416,13 @@ mod tests { #[tokio::test] async fn test_http_client_get_json() { + #[derive(serde::Deserialize, Debug, PartialEq)] + struct PackageInfo { + name: String, + version: String, + description: String, + } + let server = MockServer::start(); // Create mock JSON response @@ -435,13 +442,6 @@ mod tests { let client = HttpClient::new(); let url = format!("{}/api/package.json", server.base_url()); - #[derive(serde::Deserialize, Debug, PartialEq)] - struct PackageInfo { - name: String, - version: String, - description: String, - } - let result: Result = client.get_json(&url).await; assert!(result.is_ok()); @@ -523,6 +523,8 @@ mod tests { #[tokio::test] async fn test_verify_file_hash_sha1() { + use sha1::Sha1; + use sha2::Digest; use tokio::io::AsyncWriteExt; let temp_dir = TempDir::new().unwrap(); @@ -534,8 +536,6 @@ mod tests { file.write_all(content).await.unwrap(); // Calculate expected SHA1 - use sha1::Sha1; - use sha2::Digest; let mut hasher = Sha1::new(); hasher.update(content); let expected_hash = format!("sha1.{:x}", hasher.finalize()); @@ -552,6 +552,7 @@ mod tests { #[tokio::test] async fn test_verify_file_hash_sha224() { + use sha2::{Digest, Sha224}; use tokio::io::AsyncWriteExt; let temp_dir = TempDir::new().unwrap(); @@ -563,7 +564,6 @@ mod tests { file.write_all(content).await.unwrap(); // Calculate expected SHA224 - use sha2::{Digest, Sha224}; let mut hasher = Sha224::new(); hasher.update(content); let expected_hash = format!("sha224.{:x}", hasher.finalize()); @@ -603,6 +603,11 @@ mod tests { #[tokio::test] async fn test_http_client_json_with_invalid_response() { + #[derive(serde::Deserialize)] + struct TestData { + _field: String, + } + let server = MockServer::start(); // Mock response with invalid JSON @@ -614,11 +619,6 @@ mod tests { let client = HttpClient::new(); let url = format!("{}/invalid.json", server.base_url()); - #[derive(serde::Deserialize)] - struct TestData { - _field: String, - } - let result: Result = client.get_json(&url).await; assert!(result.is_err(), "Expected JSON parsing to fail"); } diff --git a/crates/vite_task/src/fingerprint.rs b/crates/vite_task/src/fingerprint.rs index 2fe89af8db..916055e3d8 100644 --- a/crates/vite_task/src/fingerprint.rs +++ b/crates/vite_task/src/fingerprint.rs @@ -132,6 +132,8 @@ mod tests { #[test] fn test_command_fingerprint_stable_with_multiple_envs() { + use bincode::{decode_from_slice, encode_to_vec}; + // Test that CommandFingerprint with TaskCommand::Parsed maintains stable ordering let parsed_cmd = TaskParsedCommand { envs: [ @@ -173,7 +175,6 @@ mod tests { }; // Serialize both fingerprints - use bincode::{decode_from_slice, encode_to_vec}; let config = bincode::config::standard(); let bytes1 = encode_to_vec(&fingerprint1, config).unwrap(); @@ -193,6 +194,13 @@ mod tests { #[test] fn test_fingerprint_stability_across_runs() { + use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash, Hasher}, + }; + + use bincode::encode_to_vec; + // This test simulates what happens when the same task is fingerprinted // multiple times across different program runs @@ -222,16 +230,10 @@ mod tests { }; // Serialize the fingerprint - use bincode::encode_to_vec; let config = bincode::config::standard(); let bytes = encode_to_vec(&fingerprint, config).unwrap(); // Create a hash of the serialized bytes to verify stability - use std::{ - collections::hash_map::DefaultHasher, - hash::{Hash, Hasher}, - }; - let mut hasher = DefaultHasher::new(); bytes.hash(&mut hasher); let hash = hasher.finish(); @@ -245,6 +247,8 @@ mod tests { #[test] fn test_task_config_with_sorted_envs() { + use bincode::encode_to_vec; + // Test that TaskConfig produces stable fingerprints even with HashSet envs let mut envs = HashSet::new(); envs.insert("VAR_3".into()); @@ -265,7 +269,6 @@ mod tests { let resolved = ResolvedTaskConfig { config_dir: RelativePathBuf::default(), config }; // Serialize multiple times - use bincode::encode_to_vec; let bincode_config = bincode::config::standard(); let bytes1 = encode_to_vec(&resolved, bincode_config).unwrap(); @@ -675,12 +678,9 @@ mod tests { #[test] fn test_command_fingerprint_with_fingerprint_ignores() { - // Test that CommandFingerprint includes fingerprint_ignores - use crate::{ - cmd::TaskParsedCommand, - config::{CommandFingerprint, TaskCommand}, - }; + use bincode::encode_to_vec; + // Test that CommandFingerprint includes fingerprint_ignores let parsed_cmd = TaskParsedCommand { envs: [].into(), program: "pnpm".into(), @@ -710,7 +710,6 @@ mod tests { assert_ne!(fingerprint_with_ignores, fingerprint_without_ignores); // Serialize to verify they produce different cache keys - use bincode::encode_to_vec; let config = bincode::config::standard(); let bytes_with = encode_to_vec(&fingerprint_with_ignores, config).unwrap(); @@ -724,12 +723,9 @@ mod tests { #[test] fn test_command_fingerprint_ignores_order_matters() { - // Test that the order of fingerprint_ignores patterns matters - use crate::{ - cmd::TaskParsedCommand, - config::{CommandFingerprint, TaskCommand}, - }; + use bincode::encode_to_vec; + // Test that the order of fingerprint_ignores patterns matters let parsed_cmd = TaskParsedCommand { envs: [].into(), program: "build".into(), args: vec![] }; @@ -753,7 +749,6 @@ mod tests { // (because last-match-wins means different semantics) assert_ne!(fingerprint1, fingerprint2); - use bincode::encode_to_vec; let config = bincode::config::standard(); let bytes1 = encode_to_vec(&fingerprint1, config).unwrap();