diff --git a/crates/runner-shared/src/runtime_env/go.rs b/crates/runner-shared/src/runtime_env/go.rs new file mode 100644 index 000000000..ba00d8ce9 --- /dev/null +++ b/crates/runner-shared/src/runtime_env/go.rs @@ -0,0 +1,34 @@ +const GODEBUG: &str = "GODEBUG"; +/// Starts the global `math/rand` source from `Seed(1)` instead of a random seed. +const RANDAUTOSEED_OFF: &str = "randautoseed=0"; + +/// Go env: +/// - `GODEBUG=randautoseed=0`: deterministic global `math/rand` in every mode. +pub(super) fn env() -> Vec<(&'static str, String)> { + let user_godebug = std::env::var(GODEBUG).ok(); + vec![(GODEBUG, godebug(user_godebug.as_deref()))] +} + +/// Prepends our settings to the user's `GODEBUG`. Go uses the last occurrence +/// of a setting, so an explicit `randautoseed` from the user still wins. +fn godebug(user_godebug: Option<&str>) -> String { + match user_godebug { + Some(user) if !user.is_empty() => format!("{RANDAUTOSEED_OFF},{user}"), + _ => RANDAUTOSEED_OFF.to_owned(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn keeps_user_settings_after_ours() { + assert_eq!(godebug(None), "randautoseed=0"); + assert_eq!(godebug(Some("")), "randautoseed=0"); + assert_eq!( + godebug(Some("gctrace=1,randautoseed=1")), + "randautoseed=0,gctrace=1,randautoseed=1" + ); + } +} diff --git a/crates/runner-shared/src/runtime_env/mod.rs b/crates/runner-shared/src/runtime_env/mod.rs index 8b70f1b16..fc3b2631f 100644 --- a/crates/runner-shared/src/runtime_env/mod.rs +++ b/crates/runner-shared/src/runtime_env/mod.rs @@ -1,5 +1,6 @@ use crate::measurement_mode::MeasurementMode; +mod go; mod java; mod python; @@ -10,5 +11,6 @@ pub fn env(mode: MeasurementMode) -> Vec<(&'static str, String)> { let mut env = vec![(RUNNER_MODE_ENV, mode.runner_mode_env_value().to_owned())]; env.extend(python::env(mode)); env.extend(java::env(mode)); + env.extend(go::env()); env }