diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4f8067ea..cce660612 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1397,7 +1397,7 @@ jobs: # The composer capstones shell out to a real composer; `composer:` # pins the release line (1, 2.2 LTS, 2) so the composer.lock grammar # the edits assert stays stable across runners. - uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2 + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2 with: php-version: '8.2' tools: composer:${{ matrix.composer }} diff --git a/crates/socket-patch-cli/tests/apply/apply_invariants.rs b/crates/socket-patch-cli/tests/apply/apply_invariants.rs index b73a91034..39fb88ce2 100644 --- a/crates/socket-patch-cli/tests/apply/apply_invariants.rs +++ b/crates/socket-patch-cli/tests/apply/apply_invariants.rs @@ -15,15 +15,13 @@ //! crawler won't match, which trips the "no packages found / offline" //! branches and exercises the invariants without needing a real fixture. +use crate::common::{binary, git_sha256}; + use std::path::{Path, PathBuf}; use std::process::Command; use sha2::{Digest, Sha256}; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Minimal manifest with one synthetic patch entry. The PURL points at a /// package that won't be found on disk; the `afterHash` blob is missing /// from `.socket/blobs/`. This forces every branch we want to test — @@ -151,17 +149,6 @@ const SCOPED_NPM_PURL: &str = "pkg:npm/scopedpkg@1.0.0"; const SCOPED_ORIGINAL: &[u8] = b"module.exports = function vulnerable() { return 'pwn'; };\n"; const SCOPED_PATCHED: &[u8] = b"module.exports = function safe() { return 'ok'; };\n"; -/// Git SHA-256: `SHA256("blob \0" ++ content)`. Computed -/// independently here so the manifest hashes are NOT derived from the -/// code under test (no circular oracle). -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Lay down a project with TWO manifest patches: /// - an npm patch that is fully applicable offline (package installed, /// patched blob present in `.socket/blobs/`), and diff --git a/crates/socket-patch-cli/tests/apply/cli_gem_variant_mismatch_policy.rs b/crates/socket-patch-cli/tests/apply/cli_gem_variant_mismatch_policy.rs index 39f9a92fa..15639f137 100644 --- a/crates/socket-patch-cli/tests/apply/cli_gem_variant_mismatch_policy.rs +++ b/crates/socket-patch-cli/tests/apply/cli_gem_variant_mismatch_policy.rs @@ -26,11 +26,11 @@ //! modified"). When NO variant matches, the base still fails with //! "no matching variant found" and the file stays untouched. +use crate::common::{binary, git_sha256}; + use std::path::{Path, PathBuf}; use std::process::Command; -use sha2::{Digest, Sha256}; - const SINGLETON_PURL: &str = "pkg:gem/rack@3.1.0"; const UUID_SINGLETON: &str = "31313131-3131-4131-8131-313131313131"; @@ -48,19 +48,6 @@ const LINUX_MARKER: &[u8] = b"\n# SOCKET-LINUX-PATCH\n"; const DARWIN_BEFORE: &[u8] = b"# nokogiri.rb from the arm64-darwin gem\n"; const DARWIN_MARKER: &[u8] = b"\n# DARWIN-MARKER\n"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - -/// Git-SHA256: SHA256("blob \0" ++ content). -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - fn with_marker(base: &[u8], marker: &[u8]) -> Vec { let mut v = base.to_vec(); v.extend_from_slice(marker); diff --git a/crates/socket-patch-cli/tests/apply/in_process_gem_config_warning.rs b/crates/socket-patch-cli/tests/apply/in_process_gem_config_warning.rs index 5bc4eacd7..d267e26ad 100644 --- a/crates/socket-patch-cli/tests/apply/in_process_gem_config_warning.rs +++ b/crates/socket-patch-cli/tests/apply/in_process_gem_config_warning.rs @@ -10,26 +10,14 @@ //! * non-JSON runs print ONE stderr warning, gated on `!--silent` //! (`--silent` = errors only — a bare crawler eprintln violated that). -use std::path::{Path, PathBuf}; -use std::process::Command; +use crate::common::{binary, git_sha256}; -use sha2::{Digest, Sha256}; +use std::path::Path; +use std::process::Command; const PURL: &str = "pkg:gem/rack@3.1.0"; const CODE: &str = "gem_bundle_config_path_ignored"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Project fixture: Gemfile + `.bundle/config` pointing `BUNDLE_PATH` at /// an ABSOLUTE directory outside the project (holding a real store, so /// the only reason it goes undiscovered is the containment skip), plus — diff --git a/crates/socket-patch-cli/tests/apply/in_process_gem_fallback_home.rs b/crates/socket-patch-cli/tests/apply/in_process_gem_fallback_home.rs index fcd626e5e..f941c627e 100644 --- a/crates/socket-patch-cli/tests/apply/in_process_gem_fallback_home.rs +++ b/crates/socket-patch-cli/tests/apply/in_process_gem_fallback_home.rs @@ -20,11 +20,11 @@ #![cfg(unix)] +use crate::common::{binary, git_sha256}; + use std::path::{Path, PathBuf}; use std::process::Command; -use sha2::{Digest, Sha256}; - const BASE_PURL: &str = "pkg:gem/rack@3.1.0"; const QUALIFIED_PURL: &str = "pkg:gem/rack@3.1.0?platform=ruby"; const SKIP_CODE: &str = "gem_fallback_home_skipped"; @@ -32,18 +32,6 @@ const SKIP_CODE: &str = "gem_fallback_home_skipped"; const ORIGINAL: &[u8] = b"module Rack\n VERSION = 'VULNERABLE'\nend\n"; const MARKER: &[u8] = b"# SOCKET-PATCHED-FALLBACK\n"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - fn patched_bytes() -> Vec { let mut v = ORIGINAL.to_vec(); v.extend_from_slice(MARKER); diff --git a/crates/socket-patch-cli/tests/apply/in_process_gem_multicopy.rs b/crates/socket-patch-cli/tests/apply/in_process_gem_multicopy.rs index 0b3097023..0f0e45e15 100644 --- a/crates/socket-patch-cli/tests/apply/in_process_gem_multicopy.rs +++ b/crates/socket-patch-cli/tests/apply/in_process_gem_multicopy.rs @@ -17,26 +17,13 @@ //! physical copy is patched (and later restored) AND that the JSON summary //! counts every copy. +use crate::common::{binary, git_sha256}; + use std::path::{Path, PathBuf}; use std::process::Command; -use sha2::{Digest, Sha256}; - const PURL: &str = "pkg:gem/rack@3.1.0"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - -/// Git-SHA256: SHA256("blob \0" ++ content). -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Write a gem copy at `gem_dir` with `lib/rack.rb` holding `bytes`, /// returning the file path. fn write_copy(gem_dir: &Path, bytes: &[u8]) -> PathBuf { diff --git a/crates/socket-patch-cli/tests/apply/in_process_variant_apply_failure.rs b/crates/socket-patch-cli/tests/apply/in_process_variant_apply_failure.rs index 1692b184e..05e5efb4f 100644 --- a/crates/socket-patch-cli/tests/apply/in_process_variant_apply_failure.rs +++ b/crates/socket-patch-cli/tests/apply/in_process_variant_apply_failure.rs @@ -19,19 +19,15 @@ //! Requires: `python3` with `venv` and `pip` on PATH. Skipped (visibly) //! when python3 is missing — same contract as `in_process_pypi_apply`. +use crate::common::{binary, git_sha256}; + use std::path::{Path, PathBuf}; use std::process::Command; -use sha2::{Digest, Sha256}; - const PYPI_PACKAGE: &str = "six"; const PYPI_VERSION: &str = "1.16.0"; const UUID: &str = "12121212-1212-4121-8121-121212121212"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Spawn the CLI with the ambient environment scrubbed, so the flags each /// test passes are the only thing deciding behaviour. /// @@ -72,14 +68,6 @@ fn run_apply_scrubbed(args: &[&str]) -> std::process::Output { cmd.output().expect("run socket-patch apply") } -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - fn find_python() -> Option<&'static str> { for cmd in ["python3", "python", "py"] { let ok = Command::new(cmd) diff --git a/crates/socket-patch-cli/tests/cli/cli_dry_run_paths_e2e.rs b/crates/socket-patch-cli/tests/cli/cli_dry_run_paths_e2e.rs index 2b7d23c0e..68ae871bc 100644 --- a/crates/socket-patch-cli/tests/cli/cli_dry_run_paths_e2e.rs +++ b/crates/socket-patch-cli/tests/cli/cli_dry_run_paths_e2e.rs @@ -3,13 +3,9 @@ //! asserts the JSON envelope's `dryRun: true` field — covering the //! dry-run flag-propagation branches each command's `run` has. -use std::path::{Path, PathBuf}; +use crate::common::{binary, git_sha256}; -use sha2::{Digest, Sha256}; - -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} +use std::path::Path; fn make_socket_with_empty_manifest(root: &std::path::Path) { let socket = root.join(".socket"); @@ -18,17 +14,6 @@ fn make_socket_with_empty_manifest(root: &std::path::Path) { std::fs::create_dir_all(socket.join("blobs")).unwrap(); } -/// Git SHA-256: `SHA256("blob \0" ++ content)`. Computed -/// independently here so the manifest hashes are NOT derived from the -/// code under test (no circular oracle). -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - const DRYRUN_PURL: &str = "pkg:npm/dryrunpkg@1.0.0"; const DRYRUN_ORIGINAL: &[u8] = b"module.exports = function vulnerable() { return 'pwn'; };\n"; const DRYRUN_PATCHED: &[u8] = b"module.exports = function safe() { return 'ok'; };\n"; diff --git a/crates/socket-patch-cli/tests/cli/covgap_output.rs b/crates/socket-patch-cli/tests/cli/covgap_output.rs index 1f5e1c860..6286eff7d 100644 --- a/crates/socket-patch-cli/tests/cli/covgap_output.rs +++ b/crates/socket-patch-cli/tests/cli/covgap_output.rs @@ -14,7 +14,9 @@ #![cfg(unix)] -use std::path::{Path, PathBuf}; +use crate::common::binary; + +use std::path::Path; use std::time::Duration; use portable_pty::{native_pty_system, CommandBuilder, PtySize}; @@ -30,10 +32,6 @@ const ORG_SLUG: &str = "test-org"; const UUID_A: &str = "11111111-1111-4111-8111-111111111111"; const UUID_B: &str = "22222222-2222-4222-8222-222222222222"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Spawn the socket-patch binary inside a PTY, send `input`, and collect /// all output until the child exits. Returns `(exit_code, output)`. /// diff --git a/crates/socket-patch-cli/tests/cli/interactive_prompts_e2e.rs b/crates/socket-patch-cli/tests/cli/interactive_prompts_e2e.rs index a7387e225..b8c392e74 100644 --- a/crates/socket-patch-cli/tests/cli/interactive_prompts_e2e.rs +++ b/crates/socket-patch-cli/tests/cli/interactive_prompts_e2e.rs @@ -7,15 +7,13 @@ #![cfg(unix)] -use std::path::{Path, PathBuf}; +use crate::common::binary; + +use std::path::Path; use std::time::Duration; use portable_pty::{native_pty_system, CommandBuilder, PtySize}; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Spawn the socket-patch binary inside a PTY, send `input`, and /// collect all output until the child exits. Returns `(exit_code, /// output)`. The timeout is enforced via a watchdog thread that diff --git a/crates/socket-patch-cli/tests/cli/main.rs b/crates/socket-patch-cli/tests/cli/main.rs index 9ef09285e..f3bd4b28c 100644 --- a/crates/socket-patch-cli/tests/cli/main.rs +++ b/crates/socket-patch-cli/tests/cli/main.rs @@ -18,4 +18,5 @@ mod covgap_commands_list; mod covgap_output; mod interactive_prompts_e2e; mod output_modes_e2e; +mod shared_helper_copies; mod telemetry_e2e; diff --git a/crates/socket-patch-cli/tests/cli/shared_helper_copies.rs b/crates/socket-patch-cli/tests/cli/shared_helper_copies.rs new file mode 100644 index 000000000..2c99bcefd --- /dev/null +++ b/crates/socket-patch-cli/tests/cli/shared_helper_copies.rs @@ -0,0 +1,174 @@ +//! One `binary()` and one `git_sha256` for every CLI test target (#824). +//! +//! `common/mod.rs` owns both helpers, and its own tests pin `git_sha256` +//! to the canonical Git-blob hash and to production's +//! `compute_git_sha256_from_bytes` (the two shapes the per-file copies +//! took). This ratchet keeps new private copies out: a file may define its +//! own only while it is listed below. + +use std::path::Path; + +/// Files that still define a private `binary()` or `git_sha256`. Each is +/// changed by an open PR, or is a shared module whose includers don't all +/// declare `mod common`. Migrate a file onto `common` and delete its entry; +/// a stale entry is not an error, so a PR that migrates one never turns +/// another red. +const PENDING_PRIVATE_HELPERS: &[&str] = &[ + "apply/apply_network.rs", + "apply/in_process_npm_multicopy.rs", + "cli/api_client_errors_e2e.rs", + "cli/covgap_api_client.rs", + "cli/output_modes_e2e.rs", + "cli/telemetry_e2e.rs", + "cli_scan_silent.rs", + "covgap_commands_scan_mod.rs", + "diff_created_file_e2e.rs", + "docker_e2e_npm.rs", + "docker_e2e_nuget.rs", + "docker_e2e_pypi.rs", + "e2e_embedded_vex.rs", + "e2e_gem.rs", + "e2e_hosted_production.rs", + "e2e_npm.rs", + "e2e_pypi.rs", + "e2e_redirect_gem_build.rs", + "e2e_redirect_gradle_build.rs", + "e2e_redirect_npm_build.rs", + "e2e_redirect_pnpm_build.rs", + "e2e_scan.rs", + "e2e_vendor_composer_build.rs", + "e2e_vendor_npm_build.rs", + "e2e_vendor_pnpm_build.rs", + "e2e_vendor_pypi_build.rs", + "e2e_vex_lockfile/cargo.rs", + "e2e_vex_lockfile/maven.rs", + "e2e_vex_lockfile/uv.rs", + "e2e_vex_lockfile/yarn.rs", + "e2e_vex_redirect.rs", + "e2e_vex_vendor.rs", + "get/get_batch_paths_e2e.rs", + "get/global_packages_e2e.rs", + "in_process_agent_reapply.rs", + "in_process_alternate_installers.rs", + "in_process_cargo_apply.rs", + "in_process_edge_cases.rs", + "in_process_gem_apply.rs", + "in_process_gem_multi_platform.rs", + "in_process_get_manifest_path.rs", + "in_process_pypi_apply.rs", + "in_process_pypi_multi_release.rs", + "in_process_remote_ecosystems_apply.rs", + "in_process_remove_repair_lifecycle.rs", + "mode_migration_cargo.rs", + "mode_migration_npm.rs", + "remove/covgap_commands_remove.rs", + "remove_rollback_api_overrides.rs", + "repair/coverage_fix_repair_vendor_predelete.rs", + "repair/covgap_commands_repair.rs", + "repair/covgap_commands_repair_vendor.rs", + "repair/repair_invariants.rs", + "repair/repair_vendor_e2e.rs", + "repair/repair_vendor_flavors_e2e.rs", + "rollback/rollback_invariants.rs", + "rollback/rollback_multicopy_blob_gate.rs", + "scan/covgap_commands_fetch_stage.rs", + "scan/covgap_commands_scan_vendor_flow.rs", + "scan/scan_invariants.rs", + "scan/scan_paths_e2e.rs", + "scan/scan_sync_e2e.rs", + "scan/scan_vendor_step_error_e2e.rs", + "scan_rollout_e2e.rs", + "scan_vendor_e2e.rs", + "vendor_ecosystem_fixtures/mod.rs", + "vendor_jvm_cli.rs", + "vex_e2e_common/mod.rs", + "vlt_e2e_common/mod.rs", + "vlt_hosted_common/mod.rs", + "vlt_vendor_common/mod.rs", +]; + +/// Every `.rs` file under `tests/`, as (`/`-joined relative path, text). +fn test_sources() -> Vec<(String, String)> { + fn walk(dir: &Path, root: &Path, out: &mut Vec<(String, String)>) { + let mut entries: Vec<_> = std::fs::read_dir(dir) + .unwrap_or_else(|e| panic!("read {}: {e}", dir.display())) + .map(|e| e.unwrap().path()) + .collect(); + entries.sort(); + for path in entries { + if path.is_dir() { + walk(&path, root, out); + } else if path.extension().is_some_and(|e| e == "rs") { + let rel = path + .strip_prefix(root) + .unwrap() + .components() + .map(|c| c.as_os_str().to_string_lossy().into_owned()) + .collect::>() + .join("/"); + let text = std::fs::read_to_string(&path) + .unwrap_or_else(|e| panic!("read {}: {e}", path.display())); + out.push((rel, text)); + } + } + } + let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests"); + let mut out = Vec::new(); + walk(&root, &root, &mut out); + out +} + +/// Whether `text` defines a `binary()` or `git_sha256(..)` of its own. +fn defines_private_helper(text: &str) -> bool { + text.lines().any(|line| { + let line = line.trim_start(); + let line = line + .strip_prefix("pub(crate) ") + .or_else(|| line.strip_prefix("pub ")) + .unwrap_or(line); + line.starts_with("fn binary()") || line.starts_with("fn git_sha256(") + }) +} + +#[test] +fn no_new_private_binary_or_git_sha256() { + let unexpected: Vec = test_sources() + .into_iter() + .filter(|(rel, text)| { + !rel.starts_with("common/") + && !PENDING_PRIVATE_HELPERS.contains(&rel.as_str()) + && defines_private_helper(text) + }) + .map(|(rel, _)| rel) + .collect(); + assert!( + unexpected.is_empty(), + "these test files define their own binary() or git_sha256: {unexpected:?}. \ + Use `common::binary` / `common::git_sha256` instead (declare \ + `#[path = \"common/mod.rs\"] mod common;`, or `use crate::common::..` in a \ + directory test binary). Do not add them to PENDING_PRIVATE_HELPERS." + ); +} + +#[test] +fn the_detector_sees_every_former_copy_shape() { + for copy in [ + "fn binary() -> PathBuf {\n env!(\"CARGO_BIN_EXE_socket-patch\").into()\n}", + "fn binary() -> &'static str {\n env!(\"CARGO_BIN_EXE_socket-patch\")\n}", + " fn binary() -> PathBuf {", + "pub fn git_sha256(bytes: &[u8]) -> String {", + "fn git_sha256(content: &[u8]) -> String {", + ] { + assert!(defines_private_helper(copy), "missed: {copy}"); + } + for not_a_copy in [ + "use common::{binary, git_sha256};", + "let bin = binary();", + "pub fn git_sha256_file(path: &Path) -> String {", + ] { + assert!( + !defines_private_helper(not_a_copy), + "false positive: {not_a_copy}" + ); + } +} diff --git a/crates/socket-patch-cli/tests/cli_apply_silent.rs b/crates/socket-patch-cli/tests/cli_apply_silent.rs index 3f3c5c027..c96180923 100644 --- a/crates/socket-patch-cli/tests/cli_apply_silent.rs +++ b/crates/socket-patch-cli/tests/cli_apply_silent.rs @@ -23,15 +23,15 @@ //! manifest exists and `--check` is not set, so the no-manifest hook path //! never prints it at all. -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::Command; use socket_patch_cli::args::GLOBAL_ARG_ENV_VARS; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Run `socket-patch apply` in `cwd` with a scrubbed SOCKET_* environment /// so ambient developer/CI configuration (tokens, silent toggles) can't /// change the branch under test. diff --git a/crates/socket-patch-cli/tests/cli_get_silent.rs b/crates/socket-patch-cli/tests/cli_get_silent.rs index 72f454a6a..e5c3e6681 100644 --- a/crates/socket-patch-cli/tests/cli_get_silent.rs +++ b/crates/socket-patch-cli/tests/cli_get_silent.rs @@ -7,15 +7,15 @@ //! package-name identifier in an empty project dir takes the //! crawl → "No packages found" path and exits 0 before any API call. -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::Command; use socket_patch_cli::args::GLOBAL_ARG_ENV_VARS; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Run `socket-patch get` in `cwd` with a scrubbed SOCKET_* environment /// so ambient developer/CI configuration (tokens, org slugs, silent /// toggles) can't change the branch under test. diff --git a/crates/socket-patch-cli/tests/cli_remove_silent.rs b/crates/socket-patch-cli/tests/cli_remove_silent.rs index bab3ee490..6adbdbcba 100644 --- a/crates/socket-patch-cli/tests/cli_remove_silent.rs +++ b/crates/socket-patch-cli/tests/cli_remove_silent.rs @@ -12,15 +12,15 @@ //! `get_api_client_with_overrides` in core for every command and is //! out of scope for `remove`'s `--silent` gating. +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::path::{Path, PathBuf}; use std::process::Command; use socket_patch_cli::args::GLOBAL_ARG_ENV_VARS; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - const ONE_PATCH_MANIFEST: &str = r#"{ "patches": { "pkg:npm/__remove_silent_test__@1.0.0": { diff --git a/crates/socket-patch-cli/tests/coverage_fix_apply_silent_mute_exit.rs b/crates/socket-patch-cli/tests/coverage_fix_apply_silent_mute_exit.rs index 049d8356b..dd60945f6 100644 --- a/crates/socket-patch-cli/tests/coverage_fix_apply_silent_mute_exit.rs +++ b/crates/socket-patch-cli/tests/coverage_fix_apply_silent_mute_exit.rs @@ -20,15 +20,15 @@ //! this path (partialFailure, empty events, NO top-level error record — //! deliberately distinct from vendor's `no_local_source` hard error). -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::Command; use socket_patch_cli::args::GLOBAL_ARG_ENV_VARS; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Run `socket-patch apply` in `cwd` with a scrubbed SOCKET_* environment /// so ambient developer/CI configuration (tokens, silent toggles) can't /// change the branch under test. diff --git a/crates/socket-patch-cli/tests/coverage_fix_vendor_silent_mute_exit.rs b/crates/socket-patch-cli/tests/coverage_fix_vendor_silent_mute_exit.rs index 3bfe0e862..eec277448 100644 --- a/crates/socket-patch-cli/tests/coverage_fix_vendor_silent_mute_exit.rs +++ b/crates/socket-patch-cli/tests/coverage_fix_vendor_silent_mute_exit.rs @@ -20,15 +20,15 @@ //! machine channel (`error.code = no_local_source`, as `in_process_vendor.rs` //! pins for the offline flavor). -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::Command; use socket_patch_cli::args::GLOBAL_ARG_ENV_VARS; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Run `socket-patch vendor` in `cwd` with a scrubbed SOCKET_* environment /// so ambient developer/CI configuration (tokens, silent toggles) can't /// change the branch under test. diff --git a/crates/socket-patch-cli/tests/covgap_commands_vex.rs b/crates/socket-patch-cli/tests/covgap_commands_vex.rs index 65cb456db..17d378531 100644 --- a/crates/socket-patch-cli/tests/covgap_commands_vex.rs +++ b/crates/socket-patch-cli/tests/covgap_commands_vex.rs @@ -10,6 +10,10 @@ //! self-contained tempdir project driven through the built binary with a //! scrubbed child environment. No test mutates this process's environment. +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::collections::HashMap; use std::path::Path; use std::process::Command; @@ -33,10 +37,6 @@ const UUID: &str = "9f6b2c4e-1d3a-4f6b-8c2d-7e5a9b1c3d5f"; /// `e2e_vex_vendor.rs`. const STALE_OPENVEX_DOC: &str = r#"{"@context":"https://openvex.dev/ns/v0.2.0","@id":"urn:uuid:stale","author":"Socket","timestamp":"2020-01-01T00:00:00Z","version":1,"statements":[]}"#; -fn binary() -> &'static str { - env!("CARGO_BIN_EXE_socket-patch") -} - /// CLI invocation with the ambient `SOCKET_*` environment scrubbed (same /// rationale as `e2e_vex.rs`: explicit flags must be the sole source of /// truth; the parent env is never mutated so tests need no serialization). diff --git a/crates/socket-patch-cli/tests/crawl_fd_limit_e2e.rs b/crates/socket-patch-cli/tests/crawl_fd_limit_e2e.rs index d492e3e6a..5ecdc35f5 100644 --- a/crates/socket-patch-cli/tests/crawl_fd_limit_e2e.rs +++ b/crates/socket-patch-cli/tests/crawl_fd_limit_e2e.rs @@ -19,15 +19,15 @@ //! ceiling — see the `walk_pool` module docs. #![cfg(unix)] -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::{Command, Output}; use serde_json::Value; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - fn write_package(dir: &Path, name: &str, version: &str) { std::fs::create_dir_all(dir).unwrap(); std::fs::write( diff --git a/crates/socket-patch-cli/tests/docker_e2e_cargo.rs b/crates/socket-patch-cli/tests/docker_e2e_cargo.rs index c5259a3c8..61db1094e 100644 --- a/crates/socket-patch-cli/tests/docker_e2e_cargo.rs +++ b/crates/socket-patch-cli/tests/docker_e2e_cargo.rs @@ -8,10 +8,13 @@ #![cfg(feature = "docker-e2e")] +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + use std::process::Command; use base64::Engine; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path, path_regex}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -48,14 +51,6 @@ fn cov_docker_args() -> Vec { ] } -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - async fn make_mock_server(after_hash: &str) -> MockServer { let listener = std::net::TcpListener::bind("0.0.0.0:0").expect("bind wiremock"); let server = MockServer::builder().listener(listener).start().await; diff --git a/crates/socket-patch-cli/tests/docker_e2e_composer.rs b/crates/socket-patch-cli/tests/docker_e2e_composer.rs index 023669bb4..3da189230 100644 --- a/crates/socket-patch-cli/tests/docker_e2e_composer.rs +++ b/crates/socket-patch-cli/tests/docker_e2e_composer.rs @@ -11,6 +11,10 @@ #![cfg(feature = "docker-e2e")] +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + use std::process::Command; use base64::Engine; @@ -52,14 +56,6 @@ fn cov_docker_args() -> Vec { ] } -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Plain SHA-256 of the bytes (no git blob header) — matches what /// `sha256sum` reports inside the container, so the test can assert the /// installed file is byte-identical to the patch blob, not merely that diff --git a/crates/socket-patch-cli/tests/docker_e2e_deno.rs b/crates/socket-patch-cli/tests/docker_e2e_deno.rs index 9c38d682f..1cadce993 100644 --- a/crates/socket-patch-cli/tests/docker_e2e_deno.rs +++ b/crates/socket-patch-cli/tests/docker_e2e_deno.rs @@ -29,10 +29,13 @@ #![cfg(feature = "docker-e2e")] +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + use std::process::Command; use base64::Engine; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path, path_regex}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -45,16 +48,6 @@ const NPM_UUID: &str = "13131313-1313-4131-8131-131313131313"; const PATCHED_BYTES: &[u8] = b"/* SOCKET-PATCH-E2E-MARKER */\nmodule.exports = function () { return {}; };\n"; -/// Git-SHA256: SHA256("blob \0" ++ content). Matches the binary's -/// content-addressable hashing. -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Coverage instrumentation hook — same shape as every other docker /// e2e test file. When `SOCKET_PATCH_COV_BIN` is set, mounts the /// instrumented socket-patch binary into the container and pipes diff --git a/crates/socket-patch-cli/tests/docker_e2e_gem.rs b/crates/socket-patch-cli/tests/docker_e2e_gem.rs index 3109c8125..458c7e105 100644 --- a/crates/socket-patch-cli/tests/docker_e2e_gem.rs +++ b/crates/socket-patch-cli/tests/docker_e2e_gem.rs @@ -19,6 +19,10 @@ #![cfg(feature = "docker-e2e")] +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + use std::process::Command; use base64::Engine; @@ -58,14 +62,6 @@ fn cov_docker_args() -> Vec { ] } -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Plain SHA-256 of the bytes (no git blob header) — matches what /// `sha256sum` reports inside the container, so the test can assert the /// installed file is byte-identical to the patch blob, not merely that diff --git a/crates/socket-patch-cli/tests/docker_e2e_golang.rs b/crates/socket-patch-cli/tests/docker_e2e_golang.rs index 6f96d3850..0ecc085f7 100644 --- a/crates/socket-patch-cli/tests/docker_e2e_golang.rs +++ b/crates/socket-patch-cli/tests/docker_e2e_golang.rs @@ -7,10 +7,13 @@ #![cfg(feature = "docker-e2e")] +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + use std::process::Command; use base64::Engine; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path, path_regex}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -46,14 +49,6 @@ fn cov_docker_args() -> Vec { ] } -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - async fn make_mock_server(after_hash: &str) -> MockServer { let listener = std::net::TcpListener::bind("0.0.0.0:0").expect("bind wiremock"); let server = MockServer::builder().listener(listener).start().await; diff --git a/crates/socket-patch-cli/tests/docker_e2e_maven.rs b/crates/socket-patch-cli/tests/docker_e2e_maven.rs index c102a5b75..27f111b46 100644 --- a/crates/socket-patch-cli/tests/docker_e2e_maven.rs +++ b/crates/socket-patch-cli/tests/docker_e2e_maven.rs @@ -11,10 +11,13 @@ #![cfg(feature = "docker-e2e")] +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + use std::process::Command; use base64::Engine; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path, path_regex}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -55,14 +58,6 @@ fn cov_docker_args() -> Vec { ] } -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - async fn make_mock_server(after_hash: &str) -> MockServer { let listener = std::net::TcpListener::bind("0.0.0.0:0").expect("bind wiremock"); let server = MockServer::builder().listener(listener).start().await; diff --git a/crates/socket-patch-cli/tests/docker_e2e_sbt.rs b/crates/socket-patch-cli/tests/docker_e2e_sbt.rs index 3f502accf..33be00146 100644 --- a/crates/socket-patch-cli/tests/docker_e2e_sbt.rs +++ b/crates/socket-patch-cli/tests/docker_e2e_sbt.rs @@ -41,6 +41,10 @@ #![cfg(feature = "docker-e2e")] +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + use std::io::{Read as _, Write as _}; use std::process::Command; @@ -68,13 +72,6 @@ fn hex_of(bytes: &[u8]) -> String { hex::encode(D::digest(bytes)) } -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// The pristine jar from Maven Central (checked against Central's `.sha1`) /// and the patched one: every member copied raw, plus [`MARKER`]. async fn jars() -> (Vec, Vec) { diff --git a/crates/socket-patch-cli/tests/e2e_cargo.rs b/crates/socket-patch-cli/tests/e2e_cargo.rs index 73c6acaef..34946dc53 100644 --- a/crates/socket-patch-cli/tests/e2e_cargo.rs +++ b/crates/socket-patch-cli/tests/e2e_cargo.rs @@ -13,7 +13,11 @@ //! cargo test -p socket-patch-cli --test e2e_cargo //! ``` -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::{Command, Output}; use wiremock::matchers::{method, path}; @@ -23,10 +27,6 @@ use wiremock::{Mock, MockServer, ResponseTemplate}; // Helpers // --------------------------------------------------------------------------- -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Start a mock Socket public proxy answering the scan's `POST /patch/batch` /// with an empty (no-patch) result, so no scan in this file ever leaves /// localhost. diff --git a/crates/socket-patch-cli/tests/e2e_composer.rs b/crates/socket-patch-cli/tests/e2e_composer.rs index 8f8081df7..a5ccc37f1 100644 --- a/crates/socket-patch-cli/tests/e2e_composer.rs +++ b/crates/socket-patch-cli/tests/e2e_composer.rs @@ -12,7 +12,10 @@ //! cargo test -p socket-patch-cli --test e2e_composer //! ``` -use std::path::PathBuf; +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::process::{Command, Output}; use wiremock::matchers::{method, path}; @@ -22,10 +25,6 @@ use wiremock::{Mock, MockServer, ResponseTemplate}; // Helpers // --------------------------------------------------------------------------- -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Start a mock Socket public proxy answering the scan's `POST /patch/batch` /// with an empty (no-patch) result, so no scan in this file ever leaves /// localhost. Same shape as the e2e_nuget/e2e_gem harnesses. diff --git a/crates/socket-patch-cli/tests/e2e_golang.rs b/crates/socket-patch-cli/tests/e2e_golang.rs index 6a560ae2c..095a5d5b5 100644 --- a/crates/socket-patch-cli/tests/e2e_golang.rs +++ b/crates/socket-patch-cli/tests/e2e_golang.rs @@ -15,8 +15,12 @@ //! cargo test -p socket-patch-cli --test e2e_golang //! ``` +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::collections::BTreeSet; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::process::Output; use wiremock::matchers::{method, path}; @@ -30,10 +34,6 @@ use wiremock::{Mock, MockServer, ResponseTemplate}; /// resolves to a fixed path and no `/v0/organizations` lookup is needed. const ORG: &str = "testorg"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Mount a batch endpoint that returns "no patches" (200, empty `packages`). /// /// The point is not the response — offline-equivalent emptiness is fine — but diff --git a/crates/socket-patch-cli/tests/e2e_gradle_agent_build.rs b/crates/socket-patch-cli/tests/e2e_gradle_agent_build.rs index 703597e4e..16bcd6aa2 100644 --- a/crates/socket-patch-cli/tests/e2e_gradle_agent_build.rs +++ b/crates/socket-patch-cli/tests/e2e_gradle_agent_build.rs @@ -12,6 +12,10 @@ //! classifier jars, build logic, the build cache, the read-only cache) in a //! JSON probe report per cell. +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + #[path = "common/hermetic.rs"] mod hermetic; #[path = "prebuilt_common/mod.rs"] @@ -53,10 +57,6 @@ fn coordinate() -> String { format!("{GROUP}:{VICTIM}:{VICTIM_VERSION}") } -fn git_sha256(bytes: &[u8]) -> String { - socket_patch_core::hash::git_sha256::compute_git_sha256_from_bytes(bytes) -} - fn sha1_hex(bytes: &[u8]) -> String { hex::encode(sha1::Sha1::digest(bytes)) } diff --git a/crates/socket-patch-cli/tests/e2e_gradle_discovery_build.rs b/crates/socket-patch-cli/tests/e2e_gradle_discovery_build.rs index 8eec1bbf2..ec60af503 100644 --- a/crates/socket-patch-cli/tests/e2e_gradle_discovery_build.rs +++ b/crates/socket-patch-cli/tests/e2e_gradle_discovery_build.rs @@ -9,6 +9,10 @@ //! (`jvm_fixture_repo`) and scans it; toolchain selection is //! `gradle_build_common`'s `SOCKET_PATCH_GRADLE_E2E_*` knobs. +#[path = "common/mod.rs"] +mod common; +use common::binary; + #[path = "common/hermetic.rs"] mod hermetic; #[path = "prebuilt_common/mod.rs"] @@ -36,10 +40,6 @@ const COMMONS_TEXT: &str = "pkg:maven/org.apache.commons/commons-text@1.10.0"; const BUILD_PLUGIN: &str = "pkg:maven/com.example/build-plugin@1.0"; const M2_ONLY: &str = "pkg:maven/com.example/m2-only@3.0"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// A batch endpoint that answers every queried purl with one free patch, /// so each crawled package shows up in `packages[]`. async fn mock_batch_all(server: &MockServer) { diff --git a/crates/socket-patch-cli/tests/e2e_maven.rs b/crates/socket-patch-cli/tests/e2e_maven.rs index 5afaf4373..9cffa68ea 100644 --- a/crates/socket-patch-cli/tests/e2e_maven.rs +++ b/crates/socket-patch-cli/tests/e2e_maven.rs @@ -13,7 +13,11 @@ //! cargo test -p socket-patch-cli --test e2e_maven //! ``` -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::{Command, Output}; use wiremock::matchers::{method, path}; @@ -23,10 +27,6 @@ use wiremock::{Mock, MockServer, ResponseTemplate}; // Helpers // --------------------------------------------------------------------------- -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Start a mock Socket public proxy answering the scan's `POST /patch/batch` /// with an empty (no-patch) result, so no scan in this file ever leaves /// localhost. diff --git a/crates/socket-patch-cli/tests/e2e_nuget.rs b/crates/socket-patch-cli/tests/e2e_nuget.rs index f8ec8eb1e..2dfce5ad6 100644 --- a/crates/socket-patch-cli/tests/e2e_nuget.rs +++ b/crates/socket-patch-cli/tests/e2e_nuget.rs @@ -13,7 +13,11 @@ //! cargo test -p socket-patch-cli --test e2e_nuget //! ``` -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::{Command, Output}; use wiremock::matchers::{method, path}; @@ -23,10 +27,6 @@ use wiremock::{Mock, MockServer, ResponseTemplate}; // Helpers // --------------------------------------------------------------------------- -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Start a mock Socket public proxy answering the scan's `POST /patch/batch` /// with an empty (no-patch) result, so no scan in this file ever leaves /// localhost. diff --git a/crates/socket-patch-cli/tests/e2e_redirect_bun_build.rs b/crates/socket-patch-cli/tests/e2e_redirect_bun_build.rs index 62758751d..683a4f2cd 100644 --- a/crates/socket-patch-cli/tests/e2e_redirect_bun_build.rs +++ b/crates/socket-patch-cli/tests/e2e_redirect_bun_build.rs @@ -90,6 +90,10 @@ //! equal `bun --version`, so a CI leg cannot pass by running the wrong bun //! or no bun at all. +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; @@ -150,10 +154,6 @@ const LOCK_V2_FROM: BunVersion = (1, 4, 0); // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// The REQUIRED gate: set AND non-empty. CI's e2e matrix passes /// `SOCKET_PATCH_BUN_E2E_REQUIRED: ${{ matrix.bun != '' && '1' || '' }}`, /// so an empty value is the non-bun legs' "unset" — an `is_some()` gate diff --git a/crates/socket-patch-cli/tests/e2e_redirect_cargo_build.rs b/crates/socket-patch-cli/tests/e2e_redirect_cargo_build.rs index 62345cce4..65c2b53b6 100644 --- a/crates/socket-patch-cli/tests/e2e_redirect_cargo_build.rs +++ b/crates/socket-patch-cli/tests/e2e_redirect_cargo_build.rs @@ -66,6 +66,10 @@ //! unreachable for the fixture build (a failure instead under //! `SOCKET_PATCH_CARGO_E2E_REQUIRED=1`); every assertion after that is hard. +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::path::{Path, PathBuf}; use std::process::{Command, Output}; @@ -103,10 +107,6 @@ const PATCH_SUFFIX: &str = // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Run socket-patch with ambient `SOCKET_*` vars scrubbed and the fixture's /// private CARGO_HOME injected (the cargo crawler resolves the registry /// source tree through it). diff --git a/crates/socket-patch-cli/tests/e2e_redirect_cargo_shapes.rs b/crates/socket-patch-cli/tests/e2e_redirect_cargo_shapes.rs index 73da2c89e..809eff910 100644 --- a/crates/socket-patch-cli/tests/e2e_redirect_cargo_shapes.rs +++ b/crates/socket-patch-cli/tests/e2e_redirect_cargo_shapes.rs @@ -44,6 +44,10 @@ //! Skips (with a println) when `cargo` is missing or crates.io is //! unreachable (a failure instead under `SOCKET_PATCH_CARGO_E2E_REQUIRED=1`). +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; @@ -107,10 +111,6 @@ struct Shape { refused: Option<&'static str>, } -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - fn run_socket(cwd: &Path, args: &[&str], cargo_home: &Path) -> (i32, String, String) { run_socket_env(cwd, args, cargo_home, &[]) } diff --git a/crates/socket-patch-cli/tests/e2e_redirect_rush_sim.rs b/crates/socket-patch-cli/tests/e2e_redirect_rush_sim.rs index 594492eef..cc1f2a79d 100644 --- a/crates/socket-patch-cli/tests/e2e_redirect_rush_sim.rs +++ b/crates/socket-patch-cli/tests/e2e_redirect_rush_sim.rs @@ -24,7 +24,11 @@ //! `rush install`, asserting patched bytes; plus the //! `preventManualShrinkwrapChanges` failure + `rush update` recovery. -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::{Command, Output, Stdio}; use sha2::{Digest, Sha512}; @@ -55,10 +59,6 @@ const VULNS: &[(&str, &[&str])] = &[(GHSA, &["CVE-2026-5151"])]; // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Probe corepack from a NEUTRAL temp dir (a `packageManager` field in an /// ancestor package.json — e.g. this monorepo root — otherwise makes corepack /// refuse a different manager). diff --git a/crates/socket-patch-cli/tests/e2e_redirect_yarn_berry_build.rs b/crates/socket-patch-cli/tests/e2e_redirect_yarn_berry_build.rs index 4c96ef1b3..0223f2c30 100644 --- a/crates/socket-patch-cli/tests/e2e_redirect_yarn_berry_build.rs +++ b/crates/socket-patch-cli/tests/e2e_redirect_yarn_berry_build.rs @@ -45,6 +45,10 @@ //! `scripts/yarn-berry-vex-matrix.sh`); `SOCKET_PATCH_YARN_E2E_REQUIRED=1` //! turns every soft-skip into a failure. +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; @@ -88,10 +92,6 @@ macro_rules! skip { // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Probe corepack from a NEUTRAL temp dir: a `packageManager` field in an /// ancestor `package.json` (e.g. this monorepo's root) makes corepack refuse /// to run a different package manager, which would spuriously fail the gate. diff --git a/crates/socket-patch-cli/tests/e2e_redirect_yarn_classic_build.rs b/crates/socket-patch-cli/tests/e2e_redirect_yarn_classic_build.rs index 181a7664d..e36d0fbbf 100644 --- a/crates/socket-patch-cli/tests/e2e_redirect_yarn_classic_build.rs +++ b/crates/socket-patch-cli/tests/e2e_redirect_yarn_classic_build.rs @@ -50,6 +50,10 @@ //! unavailable or the fixture install cannot reach the registry — unless //! `SOCKET_PATCH_YARN_E2E_REQUIRED=1`; every assertion after is hard. +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::path::{Path, PathBuf}; use std::process::{Command, Output}; @@ -92,10 +96,6 @@ macro_rules! skip { // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - fn scrub_socket_env(cmd: &mut Command) { for (k, _) in std::env::vars_os() { if k.to_string_lossy().starts_with("SOCKET_") { diff --git a/crates/socket-patch-cli/tests/e2e_safety_cargo_build.rs b/crates/socket-patch-cli/tests/e2e_safety_cargo_build.rs index 29e90c39d..1df6e17d6 100644 --- a/crates/socket-patch-cli/tests/e2e_safety_cargo_build.rs +++ b/crates/socket-patch-cli/tests/e2e_safety_cargo_build.rs @@ -49,9 +49,9 @@ //! `_LOCK_VERSION`) apply to the headline test. //! `#[ignore]` gated because it shells out to `cargo`. -use std::path::{Path, PathBuf}; +use common::git_sha256; -use sha2::{Digest, Sha256}; +use std::path::{Path, PathBuf}; #[path = "cargo_e2e_matrix/mod.rs"] mod cargo_e2e_matrix; @@ -211,17 +211,6 @@ fn git_hashes() -> (String, String) { ) } -/// Local Git-SHA-256 helper (sha2 + the "blob N\0" framing). We have -/// one in `common` but keep an inline copy to keep the test self- -/// readable. -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Stage `.socket/manifest.json` + `.socket/blobs/` so /// the apply pipeline can run fully offline against the synthetic /// vendored crate. diff --git a/crates/socket-patch-cli/tests/e2e_sbt_vendor.rs b/crates/socket-patch-cli/tests/e2e_sbt_vendor.rs index 31a207eb0..f44240f1d 100644 --- a/crates/socket-patch-cli/tests/e2e_sbt_vendor.rs +++ b/crates/socket-patch-cli/tests/e2e_sbt_vendor.rs @@ -14,6 +14,10 @@ //! drift, `repair`, a forged ledger, an escaping symlink, the subproject //! and build-edit refusals. +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + #[path = "common/hermetic.rs"] mod hermetic; #[path = "prebuilt_common/mod.rs"] @@ -50,10 +54,6 @@ const JUNIT: Gav<'static> = Gav { const GSON_TREE: &str = ".socket/vendor/maven2/com/google/code/gson/gson/2.8.9-socket.1d3c1fd2"; const GSON_JAR: &str = ".socket/vendor/maven2/com/google/code/gson/gson/2.8.9-socket.1d3c1fd2/gson-2.8.9-socket.1d3c1fd2.jar"; -fn git_sha256(bytes: &[u8]) -> String { - socket_patch_core::hash::git_sha256::compute_git_sha256_from_bytes(bytes) -} - fn jar(notice: &[u8]) -> Vec { let mut zw = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); let opts = zip::write::SimpleFileOptions::default(); diff --git a/crates/socket-patch-cli/tests/e2e_sbt_vendor_build.rs b/crates/socket-patch-cli/tests/e2e_sbt_vendor_build.rs index 74e530a3c..874e195c0 100644 --- a/crates/socket-patch-cli/tests/e2e_sbt_vendor_build.rs +++ b/crates/socket-patch-cli/tests/e2e_sbt_vendor_build.rs @@ -31,6 +31,10 @@ //! VERSION,REQUIRED,SEED}` (`sbt_vendor_build_common`). Scratch trees go //! under `TMPDIR`. +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + #[path = "common/hermetic.rs"] mod hermetic; #[path = "maven_build_common/mod.rs"] @@ -70,10 +74,6 @@ fn hex8(uuid: &str) -> &str { &uuid[..8] } -fn git_sha256(bytes: &[u8]) -> String { - socket_patch_core::hash::git_sha256::compute_git_sha256_from_bytes(bytes) -} - /// One warmed fixture: the build at `proj`, its isolated `home` (whose /// Coursier / Ivy caches hold the installed packages, as sbt left them), /// the download fixture's Maven2 `mirror`, and the patched member of each diff --git a/crates/socket-patch-cli/tests/e2e_scala_cli_vendor.rs b/crates/socket-patch-cli/tests/e2e_scala_cli_vendor.rs index e165252b6..560a95871 100644 --- a/crates/socket-patch-cli/tests/e2e_scala_cli_vendor.rs +++ b/crates/socket-patch-cli/tests/e2e_scala_cli_vendor.rs @@ -27,6 +27,10 @@ #![cfg_attr(windows, allow(dead_code, unused_imports))] +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + #[path = "common/hermetic.rs"] mod hermetic_spawn; #[path = "prebuilt_common/mod.rs"] @@ -54,10 +58,6 @@ const ROOT_BYTES: &str = const GUARD_BYTES: &str = "// managed by socket-patch\n//> using repository file://${.}\n"; const INDEX: &str = ".socket/vendor/coursier-index.tsv"; -fn git_sha256(bytes: &[u8]) -> String { - socket_patch_core::hash::git_sha256::compute_git_sha256_from_bytes(bytes) -} - fn purl(name: &str) -> String { format!("pkg:maven/org.example/{name}@1.0") } diff --git a/crates/socket-patch-cli/tests/e2e_vendor_bun_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_bun_build.rs index 609e06410..db9d1bb30 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_bun_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_bun_build.rs @@ -74,13 +74,17 @@ //! equal `bun --version`, so a CI leg cannot pass by running the wrong bun //! or no bun at all. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; -use sha2::{Digest, Sha256, Sha512}; +use sha2::{Digest, Sha512}; use wiremock::matchers::{method, path, path_regex}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -136,10 +140,6 @@ const LOCK_V2_FROM: BunVersion = (1, 4, 0); // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// The REQUIRED gate: set AND non-empty. CI's e2e matrix passes /// `SOCKET_PATCH_BUN_E2E_REQUIRED: ${{ matrix.bun != '' && '1' || '' }}`, /// so an empty value is the non-bun legs' "unset" — an `is_some()` gate @@ -295,13 +295,6 @@ fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { ) } -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - fn b64(bytes: &[u8]) -> String { use base64::Engine as _; base64::engine::general_purpose::STANDARD.encode(bytes) diff --git a/crates/socket-patch-cli/tests/e2e_vendor_cargo_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_cargo_build.rs index a73a2e951..c9af54b82 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_cargo_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_cargo_build.rs @@ -79,6 +79,10 @@ //! the fixture build (a failure instead under //! `SOCKET_PATCH_CARGO_E2E_REQUIRED=1`); all assertions after that are hard. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; @@ -200,10 +204,6 @@ fn metadata_version(dir: &Path, cargo_home: &Path) -> String { // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Run socket-patch with ambient `SOCKET_*` vars scrubbed and the fixture's /// private CARGO_HOME injected (the cargo crawler resolves the registry /// source tree through it). @@ -241,13 +241,6 @@ fn cargo(cwd: &Path, args: &[&str], cargo_home: &Path) -> Output { .expect("failed to run cargo") } -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - fn b64(bytes: &[u8]) -> String { use base64::Engine as _; base64::engine::general_purpose::STANDARD.encode(bytes) diff --git a/crates/socket-patch-cli/tests/e2e_vendor_gem_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_gem_build.rs index c8a4adfb1..f3f1f376b 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_gem_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_gem_build.rs @@ -58,13 +58,16 @@ //! required) or when the fixture install cannot reach rubygems.org; every //! assertion after that is hard. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -85,10 +88,6 @@ const ORG: &str = "test-org"; // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// The real-bundler gate (`common/bundler_e2e.rs`: the version-matrix env /// contract). Floor 1.17 — every bundler from the last 1.x on writes the /// `PATH` + `(= v)!` shape the pair edit produces, and the version matrix @@ -148,15 +147,6 @@ fn bundle(cwd: &Path, args: &[&str], frozen: bool) -> Output { cmd.output().expect("failed to run bundle") } -/// Git-blob SHA-256 (`sha256("blob \0" ++ bytes)`) — the hash format -/// socket-patch records in manifests. -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Base64 for the wiremock view's inline `blobContent`. fn b64(bytes: &[u8]) -> String { use base64::Engine as _; diff --git a/crates/socket-patch-cli/tests/e2e_vendor_golang_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_golang_build.rs index d9eecff51..b306b8775 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_golang_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_golang_build.rs @@ -25,13 +25,16 @@ //! record, never with a tampered artifact member or a reverted go.mod. The //! Go release is whatever `go` is on `PATH` (see `golang_e2e_matrix`). +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -55,10 +58,6 @@ const PATCHED_LIB: &str = "package upstream\n\nfunc Greeting() string { return \ // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Run socket-patch with `SOCKET_*` scrubbed + the fixture GOMODCACHE (the /// go crawler resolves installed modules through it). fn run_socket(cwd: &Path, args: &[&str], modcache: &Path) -> (i32, String, String) { @@ -114,13 +113,6 @@ fn go(dir: &Path, args: &[&str], env: &[(&str, &str)]) -> Output { cmd.output().expect("run go") } -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - fn b64(bytes: &[u8]) -> String { use base64::Engine as _; base64::engine::general_purpose::STANDARD.encode(bytes) diff --git a/crates/socket-patch-cli/tests/e2e_vendor_gradle_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_gradle_build.rs index 495d69b9b..4c40b6240 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_gradle_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_gradle_build.rs @@ -18,6 +18,10 @@ //! with `SOCKET_PATCH_GRADLE_E2E_REQUIRED` (`gradle_build_common`). Maven //! for #395 via `SOCKET_PATCH_MAVEN_E2E_{MVN,VERSION,REQUIRED}`. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "common/hermetic.rs"] mod hermetic; #[path = "prebuilt_common/mod.rs"] @@ -49,14 +53,6 @@ const UUID: &str = "1d3c1fd2-7b4e-4c1a-9f0e-2a3b4c5d6e7f"; const UUID_2: &str = "9a8b7c6d-7b4e-4c1a-9f0e-2a3b4c5d6e7f"; const DEP: &str = "com.socketfixture:victim:1.10.0"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - -fn git_sha256(bytes: &[u8]) -> String { - socket_patch_core::hash::git_sha256::compute_git_sha256_from_bytes(bytes) -} - /// `Victim.class` in `state` (`pristine` upstream, `patched` vendored). fn victim_member(state: &str) -> Vec { victim_class(VICTIM_VERSION, state) diff --git a/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs index ef49cba43..f6fed853a 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_jvm_build.rs @@ -30,6 +30,10 @@ //! (the version it must report) and `SOCKET_PATCH_GRADLE_E2E_REQUIRED` (no //! SKIP) (`gradle_build_common`). Scratch trees go under `TMPDIR`. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "maven_build_common/mod.rs"] mod maven_build_common; @@ -61,14 +65,6 @@ const SV: &str = "1.10.0-socket.1d3c1fd2"; /// the local repository would break the plugin realm, not the project. const CLASSPATH_PLUGIN: &str = "org.apache.maven.plugins:maven-dependency-plugin:3.5.0"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - -fn git_sha256(bytes: &[u8]) -> String { - socket_patch_core::hash::git_sha256::compute_git_sha256_from_bytes(bytes) -} - /// `socket-patch ` with ambient `SOCKET_*` scrubbed, `m2` as the Maven /// repo and, when given, `gradle_home` as the `GRADLE_USER_HOME` the CLI /// crawls (and the fixture registry serves). diff --git a/crates/socket-patch-cli/tests/e2e_vendor_yarn_berry_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_yarn_berry_build.rs index 5f43d035f..b6edf019d 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_yarn_berry_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_yarn_berry_build.rs @@ -45,13 +45,16 @@ //! `scripts/yarn-berry-vex-matrix.sh`); `SOCKET_PATCH_YARN_E2E_REQUIRED=1` //! turns every soft-skip into a failure. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -90,10 +93,6 @@ mod cache_env; // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - fn has_corepack_pm(pm: &str) -> bool { // Isolated too: this probe is what actually downloads the package manager // the first time, and corepack stores it under `COREPACK_HOME`. @@ -158,13 +157,6 @@ fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { ) } -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - fn stage_patch(proj: &Path, purl: &str, file_key: &str, before: &[u8], after: &[u8]) { let socket = proj.join(".socket"); std::fs::create_dir_all(socket.join("blobs")).unwrap(); diff --git a/crates/socket-patch-cli/tests/e2e_vendor_yarn_classic_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_yarn_classic_build.rs index 3903d14a8..c1f53a99a 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_yarn_classic_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_yarn_classic_build.rs @@ -46,13 +46,17 @@ //! cannot reach the registry — unless `SOCKET_PATCH_YARN_E2E_REQUIRED=1`; //! every assertion after that is HARD. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; -use sha2::{Digest, Sha256}; +use sha2::Digest; /// Canonical lowercase patch uuid (a dedicated path level under /// `.socket/vendor/npm/`). @@ -87,10 +91,6 @@ macro_rules! skip { // ── self-contained helpers ──────────────────────────────────────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Run `corepack ` in `cwd` with the given extra env, the download /// prompt disabled, and every `SOCKET_*` var scrubbed. fn corepack(cwd: &Path, pm: &str, args: &[&str], extra_env: &[(&str, &str)]) -> Output { @@ -136,14 +136,6 @@ fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { ) } -/// Git-blob SHA-256 (`sha256("blob \0" ++ bytes)`). -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Write `.socket/manifest.json` + the after-hash blob so vendor runs fully /// offline. fn stage_patch(proj: &Path, purl: &str, file_key: &str, before: &[u8], after: &[u8]) { diff --git a/crates/socket-patch-cli/tests/e2e_vendor_yarn_classic_dev_flow.rs b/crates/socket-patch-cli/tests/e2e_vendor_yarn_classic_dev_flow.rs index 48f846196..5dd8c95d1 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_yarn_classic_dev_flow.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_yarn_classic_dev_flow.rs @@ -40,14 +40,16 @@ //! cannot reach the registry — unless `SOCKET_PATCH_YARN_E2E_REQUIRED=1`; //! every assertion after that is HARD. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::process::{Command, Output}; -use sha2::{Digest, Sha256}; - /// Canonical lowercase patch uuid (a dedicated path level under /// `.socket/vendor/npm/`). const UUID: &str = "2b3c4d5e-6f7a-4b2c-9d3e-123456789abc"; @@ -112,10 +114,6 @@ fn patch_api(purl: &str, patched: &[u8]) -> vex_e2e_common::PatchApi { // ── self-contained helpers (convention: e2e test files stay standalone) ─ -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Run `corepack ` in `cwd` with the given extra env, the download /// prompt disabled, and every `SOCKET_*` var scrubbed. /// @@ -152,14 +150,6 @@ fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) { ) } -/// Git-blob SHA-256 (`sha256("blob \0" ++ bytes)`). -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Write `.socket/manifest.json` + the after-hash blob so vendor runs fully /// offline. fn stage_patch(proj: &Path, purl: &str, file_key: &str, before: &[u8], after: &[u8]) { diff --git a/crates/socket-patch-cli/tests/e2e_vendored_production.rs b/crates/socket-patch-cli/tests/e2e_vendored_production.rs index efe0f8daa..51a34a20f 100644 --- a/crates/socket-patch-cli/tests/e2e_vendored_production.rs +++ b/crates/socket-patch-cli/tests/e2e_vendored_production.rs @@ -100,6 +100,10 @@ //! cargo test -p socket-patch-cli --test e2e_vendored_production -- --ignored --test-threads=1 //! ``` +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::path::{Path, PathBuf}; use std::process::{Command, Output}; @@ -284,10 +288,6 @@ macro_rules! soft_skip { // CLI invocation // --------------------------------------------------------------------------- -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - fn has_command(cmd: &str) -> bool { // `go` has no `--version` flag — it takes `go version` as a subcommand. let probe: &[&str] = if cmd == "go" { diff --git a/crates/socket-patch-cli/tests/e2e_vex.rs b/crates/socket-patch-cli/tests/e2e_vex.rs index d4fe3ebf9..4c4d155b2 100644 --- a/crates/socket-patch-cli/tests/e2e_vex.rs +++ b/crates/socket-patch-cli/tests/e2e_vex.rs @@ -14,6 +14,10 @@ //! 4. verify-mode against patched files laid on disk //! 5. verify-mode where one patch file is missing → omitted + warning +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::collections::HashMap; use std::path::Path; use std::process::Command; @@ -24,10 +28,6 @@ use socket_patch_core::manifest::schema::{ PatchFileInfo, PatchManifest, PatchRecord, VulnerabilityInfo, }; -fn binary() -> &'static str { - env!("CARGO_BIN_EXE_socket-patch") -} - /// Build a `Command` for the CLI with the entire `SOCKET_*` environment /// scrubbed from the child process. /// diff --git a/crates/socket-patch-cli/tests/e2e_vex_lockfile/golang.rs b/crates/socket-patch-cli/tests/e2e_vex_lockfile/golang.rs index e709813fd..336d5a660 100644 --- a/crates/socket-patch-cli/tests/e2e_vex_lockfile/golang.rs +++ b/crates/socket-patch-cli/tests/e2e_vex_lockfile/golang.rs @@ -43,6 +43,8 @@ //! go-patches redirect (no uuid — a documented limitation, asserted below). //! Embedded: `scan --vex` and `apply --vex` on a manifest-less project. +use crate::common::binary; + use crate::vex_e2e_common; use std::collections::HashMap; @@ -78,10 +80,6 @@ const PATCHED_GO: &[u8] = b"package bar // patched\n"; // ── harness ─────────────────────────────────────────────────────────── -fn binary() -> &'static str { - env!("CARGO_BIN_EXE_socket-patch") -} - /// A project under `/app` plus private (empty unless a test fills them) /// module cache and GOPATH. struct Fx { diff --git a/crates/socket-patch-cli/tests/e2e_vex_lockfile/main.rs b/crates/socket-patch-cli/tests/e2e_vex_lockfile/main.rs index cbc231a4e..39d72efa2 100644 --- a/crates/socket-patch-cli/tests/e2e_vex_lockfile/main.rs +++ b/crates/socket-patch-cli/tests/e2e_vex_lockfile/main.rs @@ -20,6 +20,8 @@ //! (with the PDM/Hatch and Pipenv/pip helpers beside it); `common_selftest` //! tests those helpers themselves. +#[path = "../common/mod.rs"] +mod common; #[path = "../common/hermetic.rs"] mod hermetic; #[path = "../prebuilt_common/mod.rs"] diff --git a/crates/socket-patch-cli/tests/e2e_vex_lockfile/sbt_vendored.rs b/crates/socket-patch-cli/tests/e2e_vex_lockfile/sbt_vendored.rs index 49b19b9f1..600e740ad 100644 --- a/crates/socket-patch-cli/tests/e2e_vex_lockfile/sbt_vendored.rs +++ b/crates/socket-patch-cli/tests/e2e_vex_lockfile/sbt_vendored.rs @@ -19,6 +19,8 @@ //! | d | the generated file edited | `sbt_owned_file_modified` | //! | e | no ledger | nothing attested; the tree check still runs | +use crate::common::git_sha256; + use std::path::{Path, PathBuf}; use std::time::{Duration, SystemTime}; @@ -60,10 +62,6 @@ fn jar(notice: &[u8]) -> Vec { zw.finish().unwrap().into_inner() } -fn git_sha256(bytes: &[u8]) -> String { - socket_patch_core::hash::git_sha256::compute_git_sha256_from_bytes(bytes) -} - /// `root/proj`: the sbt 1.13.0 probe build (gson 2.8.9 resolved in `b`), /// vendored for real; the manifest is then removed. struct Fx { diff --git a/crates/socket-patch-cli/tests/e2e_yarn4_pnpm_linker_build.rs b/crates/socket-patch-cli/tests/e2e_yarn4_pnpm_linker_build.rs index ddadbb45d..bdb172089 100644 --- a/crates/socket-patch-cli/tests/e2e_yarn4_pnpm_linker_build.rs +++ b/crates/socket-patch-cli/tests/e2e_yarn4_pnpm_linker_build.rs @@ -40,6 +40,10 @@ //! `scripts/yarn-berry-vex-matrix.sh`); `SOCKET_PATCH_YARN_E2E_REQUIRED=1` //! turns every soft-skip into a failure. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; @@ -87,10 +91,6 @@ const YARNRC_PNPM: &str = "nodeLinker: pnpm\nenableGlobalCache: false\n"; // ── self-contained helpers (convention: e2e test files stay standalone) ─ -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Probe corepack from a NEUTRAL temp dir (see the redirect sibling: an /// ancestor `packageManager` field would make corepack refuse other PMs). fn has_corepack_pm(pm: &str) -> bool { @@ -226,11 +226,6 @@ fn assert_yarn_node_resolves_patched(root: &Path, patched: &[u8]) { ); } -/// Git-blob SHA-256 for the offline vendor manifest. -fn git_sha256(content: &[u8]) -> String { - compute_git_sha256_from_bytes(content) -} - /// Write `.socket/manifest.json` + the after-hash blob so vendor runs fully /// offline. fn stage_patch(proj: &Path, purl: &str, before: &[u8], after: &[u8]) { diff --git a/crates/socket-patch-cli/tests/e2e_yarn4_workspaces_build.rs b/crates/socket-patch-cli/tests/e2e_yarn4_workspaces_build.rs index 2794a4781..145c70ce9 100644 --- a/crates/socket-patch-cli/tests/e2e_yarn4_workspaces_build.rs +++ b/crates/socket-patch-cli/tests/e2e_yarn4_workspaces_build.rs @@ -42,6 +42,10 @@ //! `scripts/yarn-berry-vex-matrix.sh`); `SOCKET_PATCH_YARN_E2E_REQUIRED=1` //! turns every soft-skip into a failure. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; @@ -87,10 +91,6 @@ macro_rules! skip { // ── self-contained helpers (convention: e2e test files stay standalone) ─ -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Probe corepack from a NEUTRAL temp dir (see the redirect sibling: an /// ancestor `packageManager` field would make corepack refuse other PMs). fn has_corepack_pm(pm: &str) -> bool { @@ -226,11 +226,6 @@ fn assert_member_resolves_patched(root: &Path, patched: &[u8]) { ); } -/// Git-blob SHA-256 for the offline vendor manifest. -fn git_sha256(content: &[u8]) -> String { - compute_git_sha256_from_bytes(content) -} - /// Write `.socket/manifest.json` + the after-hash blob so vendor runs fully /// offline. fn stage_patch(proj: &Path, purl: &str, before: &[u8], after: &[u8]) { diff --git a/crates/socket-patch-cli/tests/e2e_yarn_legacy_cachekey_refusal_build.rs b/crates/socket-patch-cli/tests/e2e_yarn_legacy_cachekey_refusal_build.rs index 5ec77dd37..07623f327 100644 --- a/crates/socket-patch-cli/tests/e2e_yarn_legacy_cachekey_refusal_build.rs +++ b/crates/socket-patch-cli/tests/e2e_yarn_legacy_cachekey_refusal_build.rs @@ -40,7 +40,11 @@ //! return when the corepack-pinned yarn is unavailable or the fixture //! install cannot reach the registry; every assertion after that is HARD. -use std::path::{Path, PathBuf}; +#[path = "common/mod.rs"] +mod common; +use common::binary; + +use std::path::Path; use std::process::{Output, Stdio}; use base64::Engine as _; @@ -86,10 +90,6 @@ const GHSA: &str = "GHSA-yarn-legacy-refusal"; // ── self-contained helpers (convention: e2e test files stay standalone) ─ -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// Probe corepack from a NEUTRAL temp dir: a `packageManager` field in an /// ancestor `package.json` makes corepack refuse to run a different package /// manager, which would spuriously fail the gate (mirrors diff --git a/crates/socket-patch-cli/tests/ecosystem_dispatch_e2e.rs b/crates/socket-patch-cli/tests/ecosystem_dispatch_e2e.rs index 84d93c194..7597acf49 100644 --- a/crates/socket-patch-cli/tests/ecosystem_dispatch_e2e.rs +++ b/crates/socket-patch-cli/tests/ecosystem_dispatch_e2e.rs @@ -33,6 +33,10 @@ //! rollback dispatch branch yields zero discovered packages → the //! assertions fail loudly. +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::path::{Path, PathBuf}; use serde_json::Value; @@ -44,10 +48,6 @@ mod hermetic; const ORIGINAL: &[u8] = b"original\n"; const PATCHED: &[u8] = b"patched\n"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Compute the git-style blob SHA-256 (`sha256("blob \0" + bytes)`) /// the same way the production hashing code does. fn git_blob_sha256(bytes: &[u8]) -> String { diff --git a/crates/socket-patch-cli/tests/gradle_agent_cli.rs b/crates/socket-patch-cli/tests/gradle_agent_cli.rs index d7e6bf2b7..5d301dec5 100644 --- a/crates/socket-patch-cli/tests/gradle_agent_cli.rs +++ b/crates/socket-patch-cli/tests/gradle_agent_cli.rs @@ -11,6 +11,10 @@ //! //! Designated #551 regression test: [`m2_only_gradle_project_refuses`]. +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + #[path = "common/hermetic.rs"] mod hermetic; #[path = "prebuilt_common/mod.rs"] @@ -32,10 +36,6 @@ const POM: &str = "victim-1.0.pom"; const NOTICE: &str = "META-INF/NOTICE.txt"; const GAV: &str = "com.example:victim:1.0"; -fn git_sha256(bytes: &[u8]) -> String { - socket_patch_core::hash::git_sha256::compute_git_sha256_from_bytes(bytes) -} - fn sha1_hex(bytes: &[u8]) -> String { hex::encode(sha1::Sha1::digest(bytes)) } diff --git a/crates/socket-patch-cli/tests/in_process_rollback_all_ecosystems.rs b/crates/socket-patch-cli/tests/in_process_rollback_all_ecosystems.rs index b34873621..faf628011 100644 --- a/crates/socket-patch-cli/tests/in_process_rollback_all_ecosystems.rs +++ b/crates/socket-patch-cli/tests/in_process_rollback_all_ecosystems.rs @@ -30,22 +30,17 @@ //! qualified PURL there is genuinely unsupported and those fixtures keep //! bare PURLs. +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + use std::path::Path; use serial_test::serial; -use sha2::{Digest, Sha256}; use socket_patch_cli::commands::rollback::{run as rollback_run, RollbackArgs}; const ORG_PURL_TEMPLATE: &str = "pkg:%s/%s@%s"; -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - fn write_manifest_with_patch( socket: &Path, purl: &str, diff --git a/crates/socket-patch-cli/tests/maven_sidecar_cli.rs b/crates/socket-patch-cli/tests/maven_sidecar_cli.rs index 4ae48436c..bda297244 100644 --- a/crates/socket-patch-cli/tests/maven_sidecar_cli.rs +++ b/crates/socket-patch-cli/tests/maven_sidecar_cli.rs @@ -4,6 +4,10 @@ //! and are put back exactly on rollback; absent, none is created; one that //! never described the file is left alone. Every rollback is byte-exact. +#[path = "common/mod.rs"] +mod common; +use common::git_sha256; + #[path = "common/hermetic.rs"] mod hermetic; #[path = "prebuilt_common/mod.rs"] @@ -22,10 +26,6 @@ const PRISTINE: &[u8] = const PATCHED: &[u8] = b"com.examplelib2.0\n"; -fn git_sha256(bytes: &[u8]) -> String { - socket_patch_core::hash::git_sha256::compute_git_sha256_from_bytes(bytes) -} - fn sha1_hex(bytes: &[u8]) -> String { hex::encode(sha1::Sha1::digest(bytes)) } diff --git a/crates/socket-patch-cli/tests/mode_migration_bun.rs b/crates/socket-patch-cli/tests/mode_migration_bun.rs index 67c473d3b..e7ea8aa77 100644 --- a/crates/socket-patch-cli/tests/mode_migration_bun.rs +++ b/crates/socket-patch-cli/tests/mode_migration_bun.rs @@ -86,6 +86,10 @@ //! equal `bun --version`, so a CI leg cannot pass by running the wrong bun //! or no bun at all. +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; @@ -193,10 +197,6 @@ const LOCK_V2_FROM: BunVersion = (1, 4, 0); // ── toolchain gate (shared semantics with the two bun capstones) ────────── -fn binary() -> PathBuf { - PathBuf::from(env!("CARGO_BIN_EXE_socket-patch")) -} - /// The REQUIRED gate: set AND non-empty. CI's e2e matrix passes /// `SOCKET_PATCH_BUN_E2E_REQUIRED: ${{ matrix.bun != '' && '1' || '' }}`, /// so an empty value is the non-bun legs' "unset" — an `is_some()` gate diff --git a/crates/socket-patch-cli/tests/remove/remove_network.rs b/crates/socket-patch-cli/tests/remove/remove_network.rs index d069cf72f..bfb0e433b 100644 --- a/crates/socket-patch-cli/tests/remove/remove_network.rs +++ b/crates/socket-patch-cli/tests/remove/remove_network.rs @@ -16,30 +16,18 @@ //! `rollback_patches` (the binary would contact the mock, succeed, and //! delete the entry). -use std::path::{Path, PathBuf}; +use crate::common::{binary, git_sha256}; + +use std::path::Path; use std::process::Command; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path}; use wiremock::{Mock, MockServer, ResponseTemplate}; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - const ORG_SLUG: &str = "test-org"; const PURL: &str = "pkg:npm/remove-network-test@1.0.0"; const UUID: &str = "11111111-1111-4111-8111-111111111111"; -/// Git-SHA256: SHA256("blob \0" ++ content). -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Install the fixture package PATCHED (file at `after` bytes) so the /// nested rollback genuinely needs the beforeHash blob. Rollback's blob /// gate covers only installed rollback targets — a manifest-only fixture diff --git a/crates/socket-patch-cli/tests/rollback/cli_rollback_silent.rs b/crates/socket-patch-cli/tests/rollback/cli_rollback_silent.rs index 3603b56c5..c8d776612 100644 --- a/crates/socket-patch-cli/tests/rollback/cli_rollback_silent.rs +++ b/crates/socket-patch-cli/tests/rollback/cli_rollback_silent.rs @@ -19,14 +19,10 @@ //! command (offline runs suppress it) and is out of scope for `rollback`'s //! `--silent` gating. -use std::path::{Path, PathBuf}; -use std::process::Command; - -use sha2::{Digest, Sha256}; +use crate::common::{binary, git_sha256}; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} +use std::path::Path; +use std::process::Command; /// Run `socket-patch rollback` in `cwd` with the entire `SOCKET_*` ambient /// environment scrubbed (prefix scrub — ambient tokens, silent toggles, or @@ -66,15 +62,6 @@ fn stderr_chatter(stderr: &str) -> Vec { .collect() } -/// Git-SHA256: SHA256("blob \0" ++ content). -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// Manifest with one npm patch whose before-blob is NOT staged — plus the /// package INSTALLED under `node_modules/` with its file off the original /// bytes. Installation matters: the before-blob gate covers only installed diff --git a/crates/socket-patch-cli/tests/rollback/main.rs b/crates/socket-patch-cli/tests/rollback/main.rs index 46ae232be..981cf6e02 100644 --- a/crates/socket-patch-cli/tests/rollback/main.rs +++ b/crates/socket-patch-cli/tests/rollback/main.rs @@ -2,6 +2,8 @@ //! //! One test binary per command: each module was its own binary. +#[path = "../common/mod.rs"] +mod common; #[path = "../vlt_hosted_common/mod.rs"] mod vlt_hosted_common; #[path = "../vlt_hosted_common/vendored.rs"] diff --git a/crates/socket-patch-cli/tests/rollback/rollback_duality_invariants.rs b/crates/socket-patch-cli/tests/rollback/rollback_duality_invariants.rs index 31f457502..f5d2b1529 100644 --- a/crates/socket-patch-cli/tests/rollback/rollback_duality_invariants.rs +++ b/crates/socket-patch-cli/tests/rollback/rollback_duality_invariants.rs @@ -8,15 +8,11 @@ //! child processes, hand-written camelCase manifests, git-sha256 oracle, //! `--offline` throughout (before-blobs are staged, so nothing fetches). +use crate::common::{binary, git_sha256}; + use std::path::{Path, PathBuf}; use std::process::Command; -use sha2::{Digest, Sha256}; - -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// A `rollback` command with the full `SOCKET_*` environment scrubbed and /// the working directory pinned (same rationale as the twin helper in /// `rollback_invariants.rs`: an ambient `SOCKET_OFFLINE`/`SOCKET_DRY_RUN`/ @@ -47,15 +43,6 @@ fn run(cwd: &Path, args: &[&str]) -> (i32, String, String) { ) } -/// Git-SHA256: SHA256("blob \0" ++ content). -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// One hand-written camelCase manifest entry (single `package/index.js` /// file row), matching the TS-compatible on-disk schema. fn manifest_entry(purl: &str, uuid: &str, before_hash: &str, after_hash: &str) -> String { diff --git a/crates/socket-patch-cli/tests/scan/coverage_fix_scan_discovery_corrupt_ledger.rs b/crates/socket-patch-cli/tests/scan/coverage_fix_scan_discovery_corrupt_ledger.rs index 59e30ec48..054e7cde6 100644 --- a/crates/socket-patch-cli/tests/scan/coverage_fix_scan_discovery_corrupt_ledger.rs +++ b/crates/socket-patch-cli/tests/scan/coverage_fix_scan_discovery_corrupt_ledger.rs @@ -8,17 +8,14 @@ //! Modeled on `scan_vendor_e2e.rs` (mock API + real fixture through the //! built binary). -use std::path::{Path, PathBuf}; +use crate::common::{binary, git_sha256}; + +use std::path::Path; use std::process::Command; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path}; use wiremock::{Mock, MockServer, ResponseTemplate}; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - const ORG_SLUG: &str = "test-org"; /// The vendored cargo patch: uuid + purl of the entry that must survive. const UUID: &str = "11111111-1111-4111-8111-111111111111"; @@ -26,14 +23,6 @@ const CARGO_PURL: &str = "pkg:cargo/foo@1.0.0"; const BEFORE: &[u8] = b"before\n"; const AFTER: &[u8] = b"after\n"; -fn git_sha256(content: &[u8]) -> String { - let header = format!("blob {}\0", content.len()); - let mut hasher = Sha256::new(); - hasher.update(header.as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// One installed npm package so the crawl finds ≥1 package and scan does /// not take the zero-package early return (which skips the GC entirely). fn write_npm_fixture(root: &Path) { diff --git a/crates/socket-patch-cli/tests/scan/covgap_ecosystem_dispatch.rs b/crates/socket-patch-cli/tests/scan/covgap_ecosystem_dispatch.rs index 87d4900a3..24379786a 100644 --- a/crates/socket-patch-cli/tests/scan/covgap_ecosystem_dispatch.rs +++ b/crates/socket-patch-cli/tests/scan/covgap_ecosystem_dispatch.rs @@ -22,7 +22,9 @@ //! through `find_packages_for_rollback`'s deno branch, restore the file's //! ORIGINAL bytes on disk, and report `rolledBack == 1` for the exact PURL. -use std::path::{Path, PathBuf}; +use crate::common::binary; + +use std::path::Path; use std::process::Command; use serde_json::Value; @@ -31,10 +33,6 @@ use sha2::{Digest, Sha256}; const ORIGINAL: &[u8] = b"original\n"; const PATCHED: &[u8] = b"patched\n"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// Compute the git-style blob SHA-256 (`sha256("blob \0" + bytes)`) /// the same way the production hashing code does. fn git_blob_sha256(bytes: &[u8]) -> String { diff --git a/crates/socket-patch-cli/tests/scan/scan_ecosystems_scope_e2e.rs b/crates/socket-patch-cli/tests/scan/scan_ecosystems_scope_e2e.rs index 725012077..0e48d1841 100644 --- a/crates/socket-patch-cli/tests/scan/scan_ecosystems_scope_e2e.rs +++ b/crates/socket-patch-cli/tests/scan/scan_ecosystems_scope_e2e.rs @@ -19,16 +19,14 @@ //! installed (`CARGO_HOME` points at an empty dir, so the cargo crawl finds //! nothing — hermetic, and a lockfile-only cargo entry either way). -use std::path::{Path, PathBuf}; +use crate::common::binary; + +use std::path::Path; use std::process::Command; use wiremock::matchers::{method, path}; use wiremock::{Mock, MockServer, ResponseTemplate}; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - const ORG: &str = "test-org"; const INSTALLED_PURL: &str = "pkg:npm/installed-dep@1.0.0"; const NPM_LOCK_ONLY: &str = "lock-only-dep"; diff --git a/crates/socket-patch-cli/tests/scan_pnpm_relocated_store_cwd_e2e.rs b/crates/socket-patch-cli/tests/scan_pnpm_relocated_store_cwd_e2e.rs index 7fe0b5739..1b049e931 100644 --- a/crates/socket-patch-cli/tests/scan_pnpm_relocated_store_cwd_e2e.rs +++ b/crates/socket-patch-cli/tests/scan_pnpm_relocated_store_cwd_e2e.rs @@ -9,6 +9,10 @@ //! (#361). A store inside the project is still walked from the same cwd, //! whether it is recorded relative or absolute. +#[path = "common/mod.rs"] +mod common; +use common::binary; + use std::path::{Path, PathBuf}; use std::process::Command; @@ -17,10 +21,6 @@ use wiremock::{Mock, MockServer, ResponseTemplate}; const ORG: &str = "test-org"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - fn write_pkg(dir: &Path, name: &str) { std::fs::create_dir_all(dir).unwrap(); std::fs::write( diff --git a/crates/socket-patch-cli/tests/vendor/docker_vendor_common_selftest.rs b/crates/socket-patch-cli/tests/vendor/docker_vendor_common_selftest.rs index b33d94912..4a2848b93 100644 --- a/crates/socket-patch-cli/tests/vendor/docker_vendor_common_selftest.rs +++ b/crates/socket-patch-cli/tests/vendor/docker_vendor_common_selftest.rs @@ -10,11 +10,11 @@ //! The `|| fail "hashing ..."` guards are the only thing standing in the //! way, and they only work if `git_blob_sha` actually reports failure. +use crate::common::git_sha256; + use std::path::Path; use std::process::{Command, Output, Stdio}; -use sha2::{Digest, Sha256}; - use crate::docker_vendor_common; use docker_vendor_common::{bash_prelude, skip_or_require_image, stage_patch_fn}; @@ -56,15 +56,6 @@ fn run_stage_script(dir: &Path, body: &str) -> Output { .expect("failed to run bash") } -/// Git-blob SHA-256 (`sha256("blob \0" ++ bytes)`) — the hash format -/// socket-patch records in manifests. -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// A missing before-file must abort staging at the hashing guard — not /// silently record the hash of the bare `blob \0` header (a plausible /// 64-hex value) in the manifest and return success. diff --git a/crates/socket-patch-cli/tests/vendor/vendor_gem_lockfile_only_e2e.rs b/crates/socket-patch-cli/tests/vendor/vendor_gem_lockfile_only_e2e.rs index 77cb8f6a5..1c5f507a5 100644 --- a/crates/socket-patch-cli/tests/vendor/vendor_gem_lockfile_only_e2e.rs +++ b/crates/socket-patch-cli/tests/vendor/vendor_gem_lockfile_only_e2e.rs @@ -1,9 +1,10 @@ //! Service vendoring of portable gems without a local install or registry fetch. -use std::path::{Path, PathBuf}; +use crate::common::{binary, git_sha256}; + +use std::path::Path; use std::process::Command; -use sha2::{Digest, Sha256}; use wiremock::matchers::{method, path as wm_path}; use wiremock::{Mock, MockServer, ResponseTemplate}; @@ -17,17 +18,6 @@ const LIB: &str = "lib/socketfixturegem.rb"; const PRISTINE: &[u8] = b"module SocketFixtureGem; VERSION = '1.0.0'; end\n"; const PATCHED: &[u8] = b"module SocketFixtureGem; VERSION = '1.0.0'; SAFE = true; end\n"; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// A minimal `.gem`: an uncompressed tar whose only entry the fetcher reads /// is `data.tar.gz`, itself a gzipped tar of the gem's files at the root. fn make_gem() -> Vec { diff --git a/crates/socket-patch-cli/tests/vendor/vendor_rerun_no_network_e2e.rs b/crates/socket-patch-cli/tests/vendor/vendor_rerun_no_network_e2e.rs index 6e7047750..d8be5402c 100644 --- a/crates/socket-patch-cli/tests/vendor/vendor_rerun_no_network_e2e.rs +++ b/crates/socket-patch-cli/tests/vendor/vendor_rerun_no_network_e2e.rs @@ -19,22 +19,13 @@ //! Hermetic: every registry base and the patch API point at a //! guaranteed-dead local endpoint, and patch staging reads `.socket/blobs`. -use std::path::{Path, PathBuf}; +use crate::common::{binary, git_sha256}; + +use std::path::Path; use std::process::Command; use sha2::{Digest, Sha256}; -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - /// A guaranteed-unreachable local endpoint: bind an ephemeral port, then /// release it, so every request fails fast with connection-refused. fn dead_endpoint() -> String { diff --git a/crates/socket-patch-cli/tests/vendor_crash_safety_e2e.rs b/crates/socket-patch-cli/tests/vendor_crash_safety_e2e.rs index be60253a2..3e48b3025 100644 --- a/crates/socket-patch-cli/tests/vendor_crash_safety_e2e.rs +++ b/crates/socket-patch-cli/tests/vendor_crash_safety_e2e.rs @@ -11,10 +11,14 @@ //! artifact, rebuilds it and wires the project exactly as an uninterrupted //! run would have. +#[path = "common/mod.rs"] +mod common; +use common::{binary, git_sha256}; + #[path = "prebuilt_common/mod.rs"] mod prebuilt_common; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::process::Command; use serde_json::{json, Value}; @@ -25,13 +29,6 @@ const PURL: &str = "pkg:npm/left-pad@1.3.0"; const ORIG_INDEX: &[u8] = b"module.exports = () => 'orig';\n"; const PATCHED_INDEX: &[u8] = b"module.exports = () => 'patched';\n"; -fn git_sha256(content: &[u8]) -> String { - let mut hasher = Sha256::new(); - hasher.update(format!("blob {}\0", content.len()).as_bytes()); - hasher.update(content); - hex::encode(hasher.finalize()) -} - fn rel_tgz() -> String { format!(".socket/vendor/npm/{UUID}/left-pad-1.3.0.tgz") } @@ -91,10 +88,6 @@ fn npm_project() -> tempfile::TempDir { tmp } -fn binary() -> PathBuf { - env!("CARGO_BIN_EXE_socket-patch").into() -} - /// `vendor --json --offline` through the built binary, optionally crashing /// at `failpoint`. Returns the exit code and stdout. fn vendor(root: &Path, failpoint: Option<&str>) -> (i32, String) {