Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions crates/fspy/src/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,19 @@ impl SpyInner {

#[cfg(target_os = "macos")]
pub fn init_in(dir: &Path) -> io::Result<Self> {
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;

Comment thread
Brooooooklyn marked this conversation as resolved.
use crate::fixture::Fixture;
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(),
Expand Down Expand Up @@ -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<OwnedFd> {
let mut fds: Vec<OwnedFd> = vec![];
const SAFE_FD_NUM: RawFd = 17;

let mut fds: Vec<OwnedFd> = vec![];
while fd.as_raw_fd() < SAFE_FD_NUM {
let new_fd = fd.try_clone()?;
fds.push(fd);
Expand Down
21 changes: 11 additions & 10 deletions crates/fspy_preload_unix/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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(|| {
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion crates/fspy_shared_unix/src/spawn/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub fn handle_exec(
command: &mut Exec,
encoded_payload: &EncodedPayload,
) -> nix::Result<Option<PreExec>> {
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");
Expand Down Expand Up @@ -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,
Expand Down
30 changes: 15 additions & 15 deletions crates/vite_package_manager/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<PackageInfo, _> = client.get_json(&url).await;
assert!(result.is_ok());

Expand Down Expand Up @@ -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();
Expand All @@ -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());
Expand All @@ -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();
Expand All @@ -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());
Expand Down Expand Up @@ -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
Expand All @@ -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<TestData, _> = client.get_json(&url).await;
assert!(result.is_err(), "Expected JSON parsing to fail");
}
Expand Down
35 changes: 15 additions & 20 deletions crates/vite_task/src/fingerprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down Expand Up @@ -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();
Expand All @@ -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

Expand Down Expand Up @@ -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();
Expand All @@ -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());
Expand All @@ -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();
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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();
Expand All @@ -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![] };

Expand All @@ -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();
Expand Down
Loading