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
25 changes: 20 additions & 5 deletions crates/socket-patch-cli/tests/common/hermetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,24 @@ pub enum Extra {
/// fixture's `vendor/`. The pin outranks `XDG_CONFIG_HOME` and holds
/// no config. Run it before the suite sets its own `COMPOSER_*` values.
Composer,
/// `GOFLAGS`, `GOWORK`, `GOPATH` and `GOMODCACHE` removed, then
/// `GOENV=off`. The go crawler finds installed modules through
/// `GOMODCACHE`/`GOPATH`, and Go apply, `vex` and `vendor` honor
/// `GOFLAGS=-modfile` and `GOWORK` (`utils::go_env`), so an ambient
/// value moves the crawl off the fixture or turns a replace into a
/// refusal. `GOENV=off` stops the same keys arriving from the user's
/// `go env -w` file. Tests that need a value set it after the scrub.
Go,
}

/// The [`Extra`] scrubs for a `socket-patch` child that crawls a real
/// project tree: the binary's own crawlers read `VIRTUAL_ENV`, bundler's
/// `BUNDLE_PATH`/`BUNDLE_APP_CONFIG`/`BUNDLE_GEMFILE` and Composer's vendor
/// dir and home, so an ambient value moves discovery (and the installed
/// evidence `vex` hashes) off the fixture. Any env the test sets after the
/// scrub still wins. Apply it with [`scrub_crawler_inputs`].
pub const CRAWLER_EXTRAS: [Extra; 3] = [Extra::Venv, Extra::Bundle, Extra::Composer];
/// `BUNDLE_PATH`/`BUNDLE_APP_CONFIG`/`BUNDLE_GEMFILE`, Composer's vendor
/// dir and home, and Go's module cache and flags, so an ambient value
/// moves discovery (and the installed evidence `vex` hashes) off the
/// fixture. Any env the test sets after the scrub still wins. Apply it
/// with [`scrub_crawler_inputs`].
pub const CRAWLER_EXTRAS: [Extra; 4] = [Extra::Venv, Extra::Bundle, Extra::Composer, Extra::Go];

/// Where [`scrub_crawler_inputs`] points `BUNDLE_USER_CONFIG`.
pub const NO_BUNDLE_USER_CONFIG: &str = "/nonexistent/bundle-user-config";
Expand Down Expand Up @@ -365,6 +374,12 @@ pub fn scrub_extra(cmd: &mut Command, extras: &[Extra]) {
}
cmd.env("COMPOSER_HOME", "/nonexistent/composer-home");
}
Extra::Go => {
for key in ["GOFLAGS", "GOWORK", "GOPATH", "GOMODCACHE"] {
cmd.env_remove(key);
}
cmd.env("GOENV", "off");
}
}
}
}
4 changes: 4 additions & 0 deletions crates/socket-patch-cli/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ pub fn run_bin_with_env(
// would otherwise read the developer's `~/.gradle` / `~/.m2` (and any
// `GRADLE_USER_HOME` / `GRADLE_RO_DEP_CACHE`) into every test.
jvm_env::isolate_cli(&mut cmd);
// No ambient Go module cache, flags or `go env -w` file either: an
// exported `GOFLAGS=-modfile=...` or `GOMODCACHE` would move the go
// crawl and Go apply off the fixture.
hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Go]);
// Caller-supplied env lands last so explicit injections (runtime
// gates, discovery roots) survive the scrub.
for (k, v) in env {
Expand Down
3 changes: 3 additions & 0 deletions crates/socket-patch-cli/tests/e2e_golang_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ fn run_socket(cwd: &Path, args: &[&str], modcache: &Path) -> (i32, String, Strin
fn go(dir: &Path, args: &[&str], env: &[(&str, &str)]) -> std::process::Output {
let mut cmd = Command::new("go");
cmd.args(args).current_dir(dir);
// No ambient `GOWORK`/`GOFLAGS`/`go env -w` file: an exported
// `GOWORK=<file>` fails every `go mod download` in `stage`.
common::hermetic::scrub_extra(&mut cmd, &[common::hermetic::Extra::Go]);
cache_env::isolate(&mut cmd);
for (k, v) in env {
cmd.env(k, v);
Expand Down
3 changes: 3 additions & 0 deletions crates/socket-patch-cli/tests/e2e_golang_hosted_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ impl Machine {
fn go(dir: &Path, machine: &Machine, args: &[&str], env: &[(&str, &str)]) -> std::process::Output {
let mut cmd = Command::new("go");
cmd.args(args).current_dir(dir);
// No ambient `GOWORK`/`GOFLAGS`: an exported `GOWORK=<file>` fails
// every staging `go` command.
common::hermetic::scrub_extra(&mut cmd, &[common::hermetic::Extra::Go]);
cache_env::isolate(&mut cmd);
cmd.env("GOMODCACHE", &machine.modcache);
cmd.env("GOCACHE", &machine.gocache);
Expand Down
2 changes: 1 addition & 1 deletion crates/socket-patch-cli/tests/e2e_hosted_production.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ fn has_command(cmd: &str) -> bool {
/// immediately instead of letting a developer's ambient shell decide what got
/// tested. The crawler's own ambient inputs are scrubbed too
/// (`hermetic::CRAWLER_EXTRAS`: an activated venv, `BUNDLE_*`,
/// `COMPOSER_*`): the hosted scan discovers packages unscoped under the cwd.
/// `COMPOSER_*`, `GOFLAGS`/`GOMODCACHE` and friends): the hosted scan discovers packages unscoped under the cwd.
fn run(cwd: &Path, args: &[&str]) -> (i32, String, String) {
let mut cmd = hermetic::binary_command();
hermetic::scrub_crawler_inputs(&mut cmd);
Expand Down
5 changes: 4 additions & 1 deletion crates/socket-patch-cli/tests/e2e_vendor_golang_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const PATCHED_LIB: &str = "package upstream\n\nfunc Greeting() string { return \
/// through it).
fn run_socket(cwd: &Path, args: &[&str], modcache: &Path) -> (i32, String, String) {
let mut cmd = hermetic_command(&binary());
hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv]);
hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Venv, hermetic::Extra::Go]);
cmd.current_dir(cwd);
cmd.env("GOMODCACHE", modcache);
let _fixture = prebuilt_common::prepare_command(
Expand Down Expand Up @@ -103,6 +103,9 @@ fn go_env<'a>(modcache: &'a str, proxy: &'a str) -> Vec<(&'a str, &'a str)> {
fn go(dir: &Path, args: &[&str], env: &[(&str, &str)]) -> Output {
let mut cmd = Command::new("go");
cmd.args(args).current_dir(dir);
// No ambient `GOWORK`/`GOFLAGS`/`go env -w` file: an exported
// `GOWORK=<file>` fails every `go mod download` in `stage`.
hermetic::scrub_extra(&mut cmd, &[hermetic::Extra::Go]);
cache_env::isolate(&mut cmd);
for (k, v) in env {
cmd.env(k, v);
Expand Down
4 changes: 2 additions & 2 deletions crates/socket-patch-cli/tests/e2e_vendored_production.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,8 @@ fn has_corepack_pm(pm: &str) -> bool {
/// test process and fails if one reaches the child), and forces
/// `SOCKET_NO_CONFIG=1` to block the socket-cli
/// config.json. The crawler's own ambient inputs are scrubbed too
/// (`hermetic::CRAWLER_EXTRAS`: an activated venv, `BUNDLE_*`, `COMPOSER_*`),
/// so an ambient BUNDLE_PATH can't move the gem leg's crawl off
/// (`hermetic::CRAWLER_EXTRAS`: an activated venv, `BUNDLE_*`, `COMPOSER_*`,
/// `GOFLAGS`/`GOMODCACHE` and friends), so an ambient BUNDLE_PATH can't move the gem leg's crawl off
/// `vendor/bundle`.
fn run_socket(cwd: &Path, args: &[&str]) -> (i32, String, String) {
let mut cmd = hermetic::binary_command();
Expand Down
30 changes: 30 additions & 0 deletions crates/socket-patch-cli/tests/spawn_env_hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,36 @@ fn crawler_inputs_sweep_bundler_and_composer_overrides() {
);
}

#[test]
#[serial]
fn crawler_inputs_sweep_go_module_cache_and_flags() {
with_ambient(
&[
("GOFLAGS", "-modfile=/ambient/alt.mod"),
("GOWORK", "/ambient/go.work"),
("GOPATH", "/ambient/gopath"),
("GOMODCACHE", "/ambient/modcache"),
("GOENV", "/ambient/go-env"),
],
|| {
let mut cmd = hermetic::binary_command();
hermetic::scrub_crawler_inputs(&mut cmd);
let env = effective_env(&cmd);
for key in ["GOFLAGS", "GOWORK", "GOPATH", "GOMODCACHE"] {
assert_eq!(get(&env, key), None, "{key}");
}
// The user's `go env -w` file is switched off, not left to
// supply the same keys.
assert_eq!(get(&env, "GOENV"), Some("off"));

// A test's own pin, set after the scrub, survives.
cmd.env("GOMODCACHE", "/fixture/modcache");
let env = effective_env(&cmd);
assert_eq!(get(&env, "GOMODCACHE"), Some("/fixture/modcache"));
},
);
}

#[test]
fn no_private_bundler_sweeps() {
let found: Vec<String> = test_sources()
Expand Down
3 changes: 2 additions & 1 deletion crates/socket-patch-cli/tests/vex_e2e_common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
//! - Every run is hermetic: ambient `SOCKET_*` is scrubbed, telemetry and
//! the socket-cli config are off, ambient API tokens are vetoed (only
//! [`VexRun::api_token`] authenticates) and the crawler's ambient inputs
//! (`VIRTUAL_ENV`, `BUNDLE_*`, `COMPOSER_*`; `hermetic::CRAWLER_EXTRAS`)
//! (`VIRTUAL_ENV`, `BUNDLE_*`, `COMPOSER_*`, Go's `GO*` module/flag vars;
//! `hermetic::CRAWLER_EXTRAS`)
//! are removed. Package-manager homes/caches the installed-tree lookups need go in
//! [`VexRun::envs`].
//! - `--json` is the default ([`VexRun::human`] opts out), so
Expand Down
Loading