From ee21897ebd35fc875a790b7ef0192609e81489f0 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Tue, 18 Feb 2020 19:12:34 -0500 Subject: [PATCH] tests: make 'cross test' work The reason why it wasn't working was the integration tests. Namely, the integration tests attempted to execute the 'rg' binary directly from inside cross's docker container. But this obviously doesn't work when 'rg' was compiled for a totally different architecture. Cross normally does this by hooking into the Rust test infrastructure and causing tests to run with 'qemu'. But our integration tests didn't do that. This commit fixes our test setup to check for cross's environment variable that points to the 'qemu' binary. Once we have that, we just use 'qemu-foo rg' instead of 'rg'. Piece of cake. --- tests/util.rs | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/tests/util.rs b/tests/util.rs index b6f6d3c8..daba256b 100644 --- a/tests/util.rs +++ b/tests/util.rs @@ -160,7 +160,7 @@ impl Dir { /// on all systems. Tests that need to check `--path-separator` itself /// can simply pass it again to override it. pub fn command(&self) -> TestCommand { - let mut cmd = process::Command::new(&self.bin()); + let mut cmd = self.bin(); cmd.env_remove("RIPGREP_CONFIG_PATH"); cmd.current_dir(&self.dir); cmd.arg("--path-separator").arg("/"); @@ -171,11 +171,19 @@ impl Dir { } /// Returns the path to the ripgrep executable. - pub fn bin(&self) -> PathBuf { - if cfg!(windows) { + pub fn bin(&self) -> process::Command { + let rg = if cfg!(windows) { self.root.join("../rg.exe") } else { self.root.join("../rg") + }; + match cross_runner() { + None => process::Command::new(rg), + Some(runner) => { + let mut cmd = process::Command::new(runner); + cmd.arg(rg); + cmd + } } } @@ -429,3 +437,26 @@ fn repeat io::Result<()>>(mut f: F) -> io::Result<()> { } Err(last_err.unwrap()) } + +/// When running tests with cross, we need to be a bit smarter about how we +/// run our `rg` binary. We can't just run it directly since it might be +/// compiled for a totally different target. Instead, it's likely that `cross` +/// will have setup qemu to run it. While this is integrated into the Rust +/// testing by default, we need to handle it ourselves for integration tests. +/// +/// Thankfully, cross sets an environment variable that points to the proper +/// qemu binary that we want to run. So we just search for that env var and +/// return its value if we could find it. +fn cross_runner() -> Option { + for (k, v) in std::env::vars_os() { + let (k, v) = (k.to_string_lossy(), v.to_string_lossy()); + if !k.starts_with("CARGO_TARGET_") && !k.ends_with("_RUNNER") { + continue; + } + if !v.starts_with("qemu-") { + continue; + } + return Some(v.into_owned()); + } + None +}