Stop the config option labels test reading another test's environment

The test checks the permission picker's current value, which comes from SIGIT_PERMISSIONS and the settings file. The settings and permissions tests rewrite those while they hold ENV_TEST_LOCK, and this test took no lock, so it occasionally saw Auto where it expected Manual. Reproduced by looping the test body alongside settings::tests. The test now takes the lock and pins the three variables it depends on. The setup tests, which repoint the model cache the picker also reads, now share the same lock instead of a private one. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Co-Authored-By: siGit Code v1.6.6-acp <noreply@sigit.si>

Seto Elkahfi committed Oct 10, 2026 at 17:17 UTC a6fbdb466272278d8115ff14b237d7bbce0a52bc
2 files changed +42 -3
src/main.rs
+37
@@ -7611,6 +7611,43 @@ mod tests {
7611
7612 #[test]
7613 fn acp_config_option_labels_show_context_window() {
7614 + // The picker reads the permission default, the local-inference
7615 + // setting and the model cache from the environment, which other tests
7616 + // rewrite while they hold this lock (#168).
7617 + let _guard = crate::ENV_TEST_LOCK
7618 + .lock()
7619 + .unwrap_or_else(|poisoned| poisoned.into_inner());
7620 + let config = std::env::temp_dir().join(format!("sigit-labels-{}", uuid::Uuid::new_v4()));
7621 + let saved: Vec<_> = [
7622 + "SIGIT_CONFIG_DIR",
7623 + "SIGIT_PERMISSIONS",
7624 + "SIGIT_LOCAL_INFERENCE",
7625 + ]
7626 + .into_iter()
7627 + .map(|name| (name, std::env::var_os(name)))
7628 + .collect();
7629 + // SAFETY: serialized by ENV_TEST_LOCK and restored below.
7630 + unsafe {
7631 + std::env::set_var("SIGIT_CONFIG_DIR", &config);
7632 + std::env::remove_var("SIGIT_PERMISSIONS");
7633 + std::env::remove_var("SIGIT_LOCAL_INFERENCE");
7634 + }
7635 + let outcome = std::panic::catch_unwind(acp_config_option_labels_once);
7636 + // SAFETY: serialized by ENV_TEST_LOCK.
7637 + unsafe {
7638 + for (name, value) in saved {
7639 + match value {
7640 + Some(value) => std::env::set_var(name, value),
7641 + None => std::env::remove_var(name),
7642 + }
7643 + }
7644 + }
7645 + if let Err(panic) = outcome {
7646 + std::panic::resume_unwind(panic);
7647 + }
7648 + }
7649 +
7650 + fn acp_config_option_labels_once() {
7651 let current = GgufModelConfig {
7652 model_id: "sigit-cloud:oke".to_string(),
7653 files: Vec::new(),
src/setup.rs
+5 -3
@@ -431,11 +431,13 @@ fn resolve_shared_container() -> Option<PathBuf> {
431 #[cfg(test)]
432 mod tests {
433 use super::*;
434 - use std::sync::{Mutex, OnceLock};
434 + use std::sync::Mutex;
435
436 + /// The crate-wide lock, not one of this module's own: the model picker
437 + /// reads this cache from other modules' tests, and they must not see it
438 + /// pointed at a scratch directory halfway through.
439 fn env_lock() -> &'static Mutex<()> {
437 - static LOCK: OnceLock<Mutex<()>> = OnceLock::new();
438 - LOCK.get_or_init(|| Mutex::new(()))
440 + &crate::ENV_TEST_LOCK
441 }
442
443 fn unique_temp_dir(name: &str) -> PathBuf {