-
Notifications
You must be signed in to change notification settings - Fork 561
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
270 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
pub mod helpers; | ||
|
||
use std::process::Command; | ||
|
||
use anyhow::Result; | ||
use assert_cmd::assert::OutputAssertExt; | ||
use helpers::{cargo_clean, SccacheTest, CARGO, CRATE_DIR}; | ||
use predicates::{boolean::PredicateBooleanExt, str::PredicateStrExt}; | ||
use serial_test::serial; | ||
|
||
#[test] | ||
#[serial] | ||
fn test_cache_hit_rate() -> Result<()> { | ||
let test_info = SccacheTest::new(None)?; | ||
|
||
Command::new(CARGO.as_os_str()) | ||
.args(["build", "--color=never"]) | ||
.envs(test_info.env.iter().cloned()) | ||
.current_dir(CRATE_DIR.as_os_str()) | ||
.assert() | ||
.try_stderr(predicates::str::contains("\x1b[").from_utf8().not())? | ||
.try_success()?; | ||
|
||
test_info | ||
.show_text_stats(false)? | ||
.try_stdout( | ||
predicates::str::is_match(r"Cache hits rate\s+0\.00\s%") | ||
.unwrap() | ||
.from_utf8(), | ||
)? | ||
.try_stdout( | ||
predicates::str::is_match(r"Cache hits rate \(Rust\)\s+0\.00\s%") | ||
.unwrap() | ||
.from_utf8(), | ||
)? | ||
.try_success()?; | ||
|
||
// Clean it so we can build it again. | ||
cargo_clean(&test_info)?; | ||
|
||
Command::new(CARGO.as_os_str()) | ||
.args(["run", "--color=always"]) | ||
.envs(test_info.env.iter().cloned()) | ||
.current_dir(CRATE_DIR.as_os_str()) | ||
.assert() | ||
.try_stderr(predicates::str::contains("\x1b[").from_utf8())? | ||
.try_success()?; | ||
|
||
test_info | ||
.show_text_stats(false)? | ||
.try_stdout( | ||
predicates::str::is_match(r"Cache hits rate\s+50\.00\s%") | ||
.unwrap() | ||
.from_utf8(), | ||
)? | ||
.try_stdout( | ||
predicates::str::is_match(r"Cache hits rate \(Rust\)\s+50\.00\s%") | ||
.unwrap() | ||
.from_utf8(), | ||
)? | ||
.try_success()?; | ||
|
||
Ok(()) | ||
} | ||
|
||
#[test] | ||
#[serial] | ||
fn test_adv_cache_hit_rate() -> Result<()> { | ||
let test_info = SccacheTest::new(None)?; | ||
|
||
Command::new(CARGO.as_os_str()) | ||
.args(["build", "--color=never"]) | ||
.envs(test_info.env.iter().cloned()) | ||
.current_dir(CRATE_DIR.as_os_str()) | ||
.assert() | ||
.try_stderr(predicates::str::contains("\x1b[").from_utf8().not())? | ||
.try_success()?; | ||
|
||
test_info | ||
.show_text_stats(true)? | ||
.try_stdout( | ||
predicates::str::is_match(r"Cache hits rate\s+0\.00\s%") | ||
.unwrap() | ||
.from_utf8(), | ||
)? | ||
.try_stdout( | ||
predicates::str::is_match(r"Cache hits rate \(rust\)\s+0\.00\s%") | ||
.unwrap() | ||
.from_utf8(), | ||
)? | ||
.try_success()?; | ||
|
||
cargo_clean(&test_info)?; | ||
|
||
Command::new(CARGO.as_os_str()) | ||
.args(["run", "--color=always"]) | ||
.envs(test_info.env.iter().cloned()) | ||
.current_dir(CRATE_DIR.as_os_str()) | ||
.assert() | ||
.try_stderr(predicates::str::contains("\x1b[").from_utf8())? | ||
.try_success()?; | ||
|
||
test_info | ||
.show_text_stats(true)? | ||
.try_stdout( | ||
predicates::str::is_match(r"Cache hits rate\s+50\.00\s%") | ||
.unwrap() | ||
.from_utf8(), | ||
)? | ||
.try_stdout( | ||
predicates::str::is_match(r"Cache hits rate \(rust\)\s+50\.00\s%") | ||
.unwrap() | ||
.from_utf8(), | ||
)? | ||
.try_success()?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
use anyhow::{Context, Result}; | ||
use assert_cmd::assert::OutputAssertExt; | ||
use chrono::Local; | ||
use fs_err as fs; | ||
use log::trace; | ||
use once_cell::sync::Lazy; | ||
use std::convert::Infallible; | ||
use std::ffi::OsString; | ||
use std::io::Write; | ||
use std::path::{Path, PathBuf}; | ||
use std::process::{Command, Stdio}; | ||
|
||
pub static CRATE_DIR: Lazy<PathBuf> = | ||
Lazy::new(|| Path::new(file!()).parent().unwrap().join("../test-crate")); | ||
pub static CARGO: Lazy<OsString> = Lazy::new(|| std::env::var_os("CARGO").unwrap()); | ||
pub static SCCACHE_BIN: Lazy<PathBuf> = Lazy::new(|| assert_cmd::cargo::cargo_bin("sccache")); | ||
/// Ensures the logger is only initialized once. Panics if initialization fails. | ||
static LOGGER: Lazy<Result<(), Infallible>> = Lazy::new(|| { | ||
env_logger::Builder::new() | ||
.format(|f, record| { | ||
writeln!( | ||
f, | ||
"{} [{}] - {}", | ||
Local::now().format("%Y-%m-%dT%H:%M:%S%.3f"), | ||
record.level(), | ||
record.args() | ||
) | ||
}) | ||
.parse_env("RUST_LOG") | ||
.init(); | ||
Ok(()) | ||
}); | ||
|
||
/// Used as a test setup fixture. The drop implementation cleans up after a _successful_ test. | ||
/// We catch the panic to ensure that the drop runs and the TempDir is cleaned up. | ||
pub struct SccacheTest<'a> { | ||
/// Tempdir used for Sccache cache and cargo output. It is kept in the struct only to have the | ||
/// destructor run when SccacheTest goes out of scope, but is never used otherwise. | ||
#[allow(dead_code)] | ||
pub tempdir: tempfile::TempDir, | ||
pub env: Vec<(&'a str, std::ffi::OsString)>, | ||
} | ||
|
||
impl SccacheTest<'_> { | ||
pub fn new(additional_envs: Option<&[(&'static str, std::ffi::OsString)]>) -> Result<Self> { | ||
assert!(LOGGER.is_ok()); | ||
|
||
// Create a temp directory to use for the disk cache. | ||
let tempdir = tempfile::Builder::new() | ||
.prefix("sccache_test_rust_cargo") | ||
.tempdir() | ||
.context("Failed to create tempdir")?; | ||
let cache_dir = tempdir.path().join("cache"); | ||
fs::create_dir(&cache_dir)?; | ||
let cargo_dir = tempdir.path().join("cargo"); | ||
fs::create_dir(&cargo_dir)?; | ||
|
||
// Ensure there's no existing sccache server running. | ||
stop_sccache()?; | ||
|
||
trace!("sccache --start-server"); | ||
|
||
Command::new(SCCACHE_BIN.as_os_str()) | ||
.arg("--start-server") | ||
.env("SCCACHE_DIR", &cache_dir) | ||
.assert() | ||
.try_success() | ||
.context("Failed to start sccache server")?; | ||
|
||
let mut env = vec![ | ||
("CARGO_TARGET_DIR", cargo_dir.as_os_str().to_owned()), | ||
("RUSTC_WRAPPER", SCCACHE_BIN.as_os_str().to_owned()), | ||
// Explicitly disable incremental compilation because sccache is unable to cache it at | ||
// the time of writing. | ||
("CARGO_INCREMENTAL", OsString::from("0")), | ||
("TEST_ENV_VAR", OsString::from("1")), | ||
]; | ||
|
||
if let Some(vec) = additional_envs { | ||
env.extend_from_slice(vec); | ||
} | ||
|
||
Ok(SccacheTest { | ||
tempdir, | ||
env: env.to_owned(), | ||
}) | ||
} | ||
|
||
/// Show the statistics for sccache. This will be called at the end of a test and making this | ||
/// an associated function will ensure that the struct lives until the end of the test. | ||
pub fn show_stats(&self) -> assert_cmd::assert::AssertResult { | ||
trace!("sccache --show-stats"); | ||
|
||
Command::new(SCCACHE_BIN.as_os_str()) | ||
.args(["--show-stats", "--stats-format=json"]) | ||
.assert() | ||
.try_success() | ||
} | ||
|
||
pub fn show_text_stats(&self, advanced: bool) -> assert_cmd::assert::AssertResult { | ||
let cmd = if advanced { | ||
"--show-adv-stats" | ||
} else { | ||
"--show-stats" | ||
}; | ||
|
||
trace!("sccache {cmd}"); | ||
|
||
Command::new(SCCACHE_BIN.as_os_str()) | ||
.args([cmd, "--stats-format=text"]) | ||
.assert() | ||
.try_success() | ||
} | ||
} | ||
|
||
impl Drop for SccacheTest<'_> { | ||
fn drop(&mut self) { | ||
stop_sccache().expect("Stopping Sccache server failed"); | ||
} | ||
} | ||
|
||
pub fn stop_sccache() -> Result<()> { | ||
trace!("sccache --stop-server"); | ||
|
||
Command::new(SCCACHE_BIN.as_os_str()) | ||
.arg("--stop-server") | ||
.stdout(Stdio::null()) | ||
.stderr(Stdio::null()) | ||
.status() | ||
.context("Failed to stop sccache server")?; | ||
Ok(()) | ||
} | ||
|
||
pub fn cargo_clean(test_info: &SccacheTest) -> Result<()> { | ||
Command::new(CARGO.as_os_str()) | ||
.args(["clean"]) | ||
.envs(test_info.env.iter().cloned()) | ||
.current_dir(CRATE_DIR.as_os_str()) | ||
.assert() | ||
.try_success()?; | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.