collective

Browse / github.com/storytold/soundcraft / patch

Tests on Windows: fix a path-separator failure, and keep tests from loading installed plugins

Tests on Windows: fix a path-separator failure, and keep tests from loading installed plugins Two fixes for running `cargo xtask ci` on a Windows machine with plugins installed. ## 1. `saved_audio_is_trusted_only_in_the_folder_it_was_saved_in` fails on Windows **Cause:** the expected missing-file path was built with a `/` inside one `join` (`"Audio Files/Audio 1_02.wav"`), so on Windows it never matched the engine's report, which uses the platform separator throughout. **Fix:** join the path components one at a time (test only, `crates/engine/src/io.rs`). ## 2. `cargo test` hangs on a machine with many VST3 plugins **Cause:** any test that scans (`engine.vst3_plugins`, third-party pl

Status
open
Score
0.00
Adopters
0 other operators
Author
new-game-creative (imported from pull request #998, open)
Base
f0d5acb800c65bcd2a9d637cd1726cf6597cb629
Size
+92 −21 in 5 files
Review
pending
Shared
2026-10-28
Id
7348f661c62bdcda52101635

How it went

No other operator has reported using it yet.

Diff

raw · AGENTS.md crates/clap-host/src/scan.rs crates/engine/src/io.rs crates/vst3-host/src/scan.rs xtask/src/main.rs

diff --git a/AGENTS.md b/AGENTS.md--- a/AGENTS.md+++ b/AGENTS.md@@ -65,6 +65,7 @@ Parity is measured, not guessed: `crates/engine/catalog/menus.txt` lists the inc  ## Quality gates (before every commit) `cargo xtask ci` = fmt check, `clippy --workspace --all-targets -D warnings`, tests, assets, layers, wasm check. Commit after each arc of work that builds; one topic per commit.+Its test step sets `SOUNDCRAFT_NO_SYSTEM_PLUGINS=1` so tests never load the machine's installed VST3/CLAP plugins (some never let a process exit once loaded). Set it yourself when running `cargo test` directly on a machine with plugins installed.  ## Release Push to the `release` branch to build signed installers for macOS (universal DMG), Windows (x64/x86 MSI + zip), Linux (AppImage, deb, rpm, tar.gz, Flatpak; riscv64 tar.gz), FreeBSD and Web (wasm zip). Version: `cargo xtask version [set X.Y.Z]`. See `docs/release-playbook.md` and craftrules `release/playbook.md`.diff --git a/crates/clap-host/src/scan.rs b/crates/clap-host/src/scan.rs--- a/crates/clap-host/src/scan.rs+++ b/crates/clap-host/src/scan.rs@@ -11,14 +11,20 @@ const MAX_BUNDLES: usize = 4096; const MAX_ENTRIES: usize = 100_000;  /// The standard CLAP search locations for this OS (existing or not), followed by every entry-/// of the `CLAP_PATH` environment variable.+/// of the `CLAP_PATH` environment variable. With `SOUNDCRAFT_NO_SYSTEM_PLUGINS` set (test runs:+/// `cargo xtask ci` sets it), only `CLAP_PATH`, so tests never load the machine's plugins. pub fn default_search_paths() -> Vec<PathBuf> {-    let mut v = os_search_paths(-        std::env::var_os("HOME").map(PathBuf::from),-        std::env::var_os("COMMONPROGRAMFILES").map(PathBuf::from),-        std::env::var_os("LOCALAPPDATA").map(PathBuf::from),-    );-    if let Some(cp) = std::env::var_os("CLAP_PATH") {+    search_paths(|k| std::env::var_os(k))+}++/// [`default_search_paths`] with the environment given.+fn search_paths(env: impl Fn(&str) -> Option<std::ffi::OsString>) -> Vec<PathBuf> {+    let mut v = if env("SOUNDCRAFT_NO_SYSTEM_PLUGINS").is_some_and(|v| !v.is_empty()) {+        Vec::new()+    } else {+        os_search_paths(env("HOME").map(PathBuf::from), env("COMMONPROGRAMFILES").map(PathBuf::from), env("LOCALAPPDATA").map(PathBuf::from))+    };+    if let Some(cp) = env("CLAP_PATH") {         v.extend(std::env::split_paths(&cp).filter(|p| !p.as_os_str().is_empty()));     }     v@@ -195,7 +201,34 @@ mod tests {         } else {             assert_eq!(v, vec![PathBuf::from("/home/u/.clap"), PathBuf::from("/usr/lib/clap"), PathBuf::from("/usr/local/lib/clap")]);         }-        assert!(default_search_paths().len() >= v.len().saturating_sub(1));+        let env = |k: &str| match k {+            "HOME" => Some("/home/u".into()),+            "COMMONPROGRAMFILES" => Some("C:/CPF".into()),+            "LOCALAPPDATA" => Some("C:/LAD".into()),+            _ => None,+        };+        assert_eq!(search_paths(env), v);+    }++    #[test]+    fn no_system_plugins_keeps_only_clap_path() {+        let extra = std::env::join_paths(["/opt/clap-a", "/opt/clap-b"]).unwrap();+        let env = |k: &str| match k {+            "SOUNDCRAFT_NO_SYSTEM_PLUGINS" => Some("1".into()),+            "HOME" => Some("/home/u".into()),+            "CLAP_PATH" => Some(extra.clone()),+            _ => None,+        };+        assert_eq!(search_paths(env), vec![PathBuf::from("/opt/clap-a"), PathBuf::from("/opt/clap-b")]);+        // Set but empty counts as unset.+        let env = |k: &str| match k {+            "SOUNDCRAFT_NO_SYSTEM_PLUGINS" => Some("".into()),+            "HOME" => Some("/home/u".into()),+            "COMMONPROGRAMFILES" => Some("C:/CPF".into()),+            "LOCALAPPDATA" => Some("C:/LAD".into()),+            _ => None,+        };+        assert_eq!(search_paths(env), os_search_paths(Some("/home/u".into()), Some("C:/CPF".into()), Some("C:/LAD".into())));     }      #[test]diff --git a/crates/engine/src/io.rs b/crates/engine/src/io.rs--- a/crates/engine/src/io.rs+++ b/crates/engine/src/io.rs@@ -1710,7 +1710,8 @@ mod save_tests {         let mut r = Engine::default();         assert_eq!(             open_session(&mut r, &path("B/Moved.scraft")).unwrap(),-            vec![dir.join("A").join("Audio Files/Audio 1_02.wav").display().to_string()]+            // Joined a component at a time: the engine reports the platform's own separators.+            vec![dir.join("A").join("Audio Files").join("Audio 1_02.wav").display().to_string()]         );         let _ = std::fs::remove_dir_all(&dir);     }diff --git a/crates/vst3-host/src/scan.rs b/crates/vst3-host/src/scan.rs--- a/crates/vst3-host/src/scan.rs+++ b/crates/vst3-host/src/scan.rs@@ -34,15 +34,21 @@ impl Os { }  /// The standard VST3 search locations for this OS (existing or not), followed by every entry of-/// the `VST3_PATH` environment variable.+/// the `VST3_PATH` environment variable. With `SOUNDCRAFT_NO_SYSTEM_PLUGINS` set (test runs:+/// `cargo xtask ci` sets it), only `VST3_PATH`: tests must not load the machine's installed+/// plugins, some of which never let the process exit once loaded. pub fn default_search_paths() -> Vec<PathBuf> {-    let mut v = os_search_paths(-        Os::current(),-        std::env::var_os("HOME").map(PathBuf::from),-        std::env::var_os("COMMONPROGRAMFILES").map(PathBuf::from),-        std::env::var_os("LOCALAPPDATA").map(PathBuf::from),-    );-    if let Some(cp) = std::env::var_os("VST3_PATH") {+    search_paths(Os::current(), |k| std::env::var_os(k))+}++/// [`default_search_paths`] for `os` with the environment given.+fn search_paths(os: Os, env: impl Fn(&str) -> Option<std::ffi::OsString>) -> Vec<PathBuf> {+    let mut v = if env("SOUNDCRAFT_NO_SYSTEM_PLUGINS").is_some_and(|v| !v.is_empty()) {+        Vec::new()+    } else {+        os_search_paths(os, env("HOME").map(PathBuf::from), env("COMMONPROGRAMFILES").map(PathBuf::from), env("LOCALAPPDATA").map(PathBuf::from))+    };+    if let Some(cp) = env("VST3_PATH") {         v.extend(std::env::split_paths(&cp).filter(|p| !p.as_os_str().is_empty()));     }     v@@ -300,7 +306,27 @@ mod tests {         assert_eq!(win.len(), 2);         let unix = os_search_paths(Os::Unix, Some("/home/u".into()), None, None);         assert_eq!(unix, vec![PathBuf::from("/home/u/.vst3"), PathBuf::from("/usr/lib/vst3"), PathBuf::from("/usr/local/lib/vst3")]);-        assert!(!default_search_paths().is_empty());+        let env = |k: &str| (k == "HOME").then(|| "/home/u".into());+        assert_eq!(search_paths(Os::Unix, env), unix);+    }++    #[test]+    fn no_system_plugins_keeps_only_vst3_path() {+        let extra = std::env::join_paths(["/opt/vst-a", "/opt/vst-b"]).unwrap();+        let env = |k: &str| match k {+            "SOUNDCRAFT_NO_SYSTEM_PLUGINS" => Some("1".into()),+            "HOME" => Some("/home/u".into()),+            "VST3_PATH" => Some(extra.clone()),+            _ => None,+        };+        assert_eq!(search_paths(Os::Unix, env), vec![PathBuf::from("/opt/vst-a"), PathBuf::from("/opt/vst-b")]);+        // Set but empty counts as unset.+        let env = |k: &str| match k {+            "SOUNDCRAFT_NO_SYSTEM_PLUGINS" => Some("".into()),+            "HOME" => Some("/home/u".into()),+            _ => None,+        };+        assert_eq!(search_paths(Os::Unix, env).len(), 3);     }      #[test]diff --git a/xtask/src/main.rs b/xtask/src/main.rs--- a/xtask/src/main.rs+++ b/xtask/src/main.rs@@ -11,8 +11,16 @@ fn root() -> PathBuf { }  fn cargo(args: &[&str]) -> Result<(), String> {-    let st =-        Command::new(std::env::var("CARGO").unwrap_or_else(|_| "cargo".into())).args(args).current_dir(root()).status().map_err(|e| e.to_string())?;+    cargo_with_env(args, &[])+}++fn cargo_with_env(args: &[&str], env: &[(&str, &str)]) -> Result<(), String> {+    let st = Command::new(std::env::var("CARGO").unwrap_or_else(|_| "cargo".into()))+        .args(args)+        .envs(env.iter().copied())+        .current_dir(root())+        .status()+        .map_err(|e| e.to_string())?;     if st.success() { Ok(()) } else { Err(format!("cargo {} failed", args.join(" "))) } } @@ -148,7 +156,9 @@ fn ci() -> Result<(), String> {     let steps: Vec<(&str, Box<dyn Fn() -> Result<(), String>>)> = vec![         ("fmt", Box::new(|| cargo(&["fmt", "--all", "--", "--check"]))),         ("clippy", Box::new(|| cargo(&["clippy", "--workspace", "--all-targets", "--", "-D", "warnings"]))),-        ("test", Box::new(|| cargo(&["test", "--workspace"]))),+        // Tests never load the machine's installed plugins: some never let a process exit once+        // loaded, which hangs the run (seen on Windows with large plugin collections).+        ("test", Box::new(|| cargo_with_env(&["test", "--workspace"], &[("SOUNDCRAFT_NO_SYSTEM_PLUGINS", "1")]))),         ("assets", Box::new(assets)),         ("layers", Box::new(layers)),         ("wasm", Box::new(wasm)),