Refactor system tests to use assert_cmd

This commit is contained in:
Ted Mielczarek 2018-07-27 12:07:08 -04:00
Родитель a8606b1203
Коммит 13701e3903
3 изменённых файлов: 115 добавлений и 103 удалений

8
Cargo.lock сгенерированный
Просмотреть файл

@ -20,7 +20,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"escargot 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"predicates 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"predicates 0.5.2 (git+https://github.com/luser/predicates-rs?branch=function-unsized)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -742,7 +742,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "predicates"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/luser/predicates-rs?branch=function-unsized#56592bae5e0dbce03b0d6f82a5063844d336c91a"
dependencies = [
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"float-cmp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -964,7 +964,7 @@ dependencies = [
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)",
"predicates 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"predicates 0.5.2 (git+https://github.com/luser/predicates-rs?branch=function-unsized)",
"redis 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"retry 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1618,7 +1618,7 @@ dependencies = [
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd"
"checksum predicates 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f3dc50ff273939a7688f8bccd748add1a0822dd6a9aa132b52600c7c45cc6409"
"checksum predicates 0.5.2 (git+https://github.com/luser/predicates-rs?branch=function-unsized)" = "<none>"
"checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1"

Просмотреть файл

@ -96,3 +96,6 @@ unstable = []
[workspace]
exclude = ["tests/test-crate"]
[patch.crates-io]
predicates = { git = "https://github.com/luser/predicates-rs", branch = "function-unsized" }

Просмотреть файл

@ -16,16 +16,20 @@
#![allow(dead_code, unused_imports)]
extern crate assert_cmd;
extern crate cc;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate predicates;
extern crate sccache;
extern crate serde_json;
extern crate tempdir;
extern crate which;
use assert_cmd::prelude::*;
use log::LogLevel::Trace;
use predicates::prelude::*;
use sccache::server::ServerInfo;
use std::collections::HashMap;
use std::env;
@ -39,10 +43,10 @@ use std::process::{
Output,
Stdio,
};
use std::str;
use tempdir::TempDir;
use which::which_in;
struct Compiler {
pub name: &'static str,
pub exe: OsString,
@ -59,59 +63,22 @@ const COMPILERS: &'static [&'static str] = &["clang"];
//TODO: could test gcc when targeting mingw.
fn find_sccache_binary() -> PathBuf {
// Older versions of cargo put the test binary next to the sccache binary.
// Newer versions put it in the deps/ subdirectory.
let exe = env::current_exe().unwrap();
let this_dir = exe.parent().unwrap();
let dirs = &[&this_dir, &this_dir.parent().unwrap()];
dirs
.iter()
.map(|d| d.join("sccache").with_extension(env::consts::EXE_EXTENSION))
.filter_map(|d| fs::metadata(&d).ok().map(|_| d))
.next()
.expect(&format!("Error: sccache binary not found, looked in `{:?}`. Do you need to run `cargo build`?", dirs))
fn stop() {
trace!("sccache --stop-server");
drop(Command::main_binary().unwrap()
.arg("--stop-server")
.stdout(Stdio::null())
.stderr(Stdio::null())
.status());
}
fn do_run<T: AsRef<OsStr>>(exe: &Path, args: &[T], cwd: &Path, env_vars: &[(OsString, OsString)]) -> Output {
let mut cmd = Command::new(exe);
cmd.args(args)
.current_dir(cwd)
.stdout(Stdio::piped())
.stderr(Stdio::piped());
for &(ref k, ref v) in env_vars.iter() {
cmd.env(k, v);
}
trace!("do_run: {:?}", cmd);
cmd.spawn()
.unwrap_or_else(|e| { panic!("failed to execute child: {}", e) })
.wait_with_output()
.unwrap()
}
fn run_stdout<T>(exe: &Path, args: &[T], cwd: &Path, env_vars: &[(OsString, OsString)]) -> String
where T: AsRef<OsStr> + fmt::Debug,
{
let output = do_run(exe, args, cwd, env_vars);
assert!(output.status.success(), "Failed to run {:?} {:?}", exe, args);
String::from_utf8(output.stdout).expect("Couldn't convert stdout to String")
}
fn run<T: AsRef<OsStr>>(exe: &Path, args: &[T], cwd: &Path, env_vars: &[(OsString, OsString)]) -> bool {
let output = do_run(exe, args, cwd, env_vars);
if output.status.success() {
true
} else {
let va = args.iter().map(|a| a.as_ref().to_str().unwrap()).collect::<Vec<_>>();
println!("Process `{:?} {}` failed:", exe, va.join(" "));
print!("stdout: `");
io::stdout().write(&output.stdout).unwrap();
println!("`");
print!("stderr: `");
io::stdout().write(&output.stderr).unwrap();
println!("`");
false
}
fn zero_stats() {
trace!("sccache --zero-stats");
drop(Command::main_binary().unwrap()
.arg("--zero-stats")
.stdout(Stdio::null())
.stderr(Stdio::null())
.status());
}
macro_rules! vec_from {
@ -128,9 +95,16 @@ fn compile_cmdline<T: AsRef<OsStr>>(compiler: &str, exe: T, input: &str, output:
}
}
fn get_stats(sccache: &Path, cwd: &Path) -> ServerInfo {
let output = run_stdout(sccache, &["--show-stats", "--stats-format=json"], cwd, &[]);
serde_json::from_str(&output).expect("Failed to parse JSON stats")
fn get_stats<F: 'static + Fn(ServerInfo)>(f: F) {
Command::main_binary().unwrap()
.args(&["--show-stats", "--stats-format=json"])
.assert()
.success()
.stdout(predicate::function(move |output: &[u8]| {
let s = str::from_utf8(output).expect("Output not UTF-8");
f(serde_json::from_str(s).expect("Failed to parse JSON stats"));
true
}));
}
fn write_source(path: &Path, filename: &str, contents: &str) {
@ -139,11 +113,10 @@ fn write_source(path: &Path, filename: &str, contents: &str) {
f.write_all(contents.as_bytes()).unwrap();
}
fn run_sccache_command_test(sccache: &Path, compiler: Compiler, tempdir: &Path) {
fn run_sccache_command_test(compiler: Compiler, tempdir: &Path) {
let Compiler { name, exe, env_vars } = compiler;
// Ensure there's no existing sccache server running.
trace!("stop server");
do_run(sccache, &["--stop-server"], tempdir, &[]);
stop();
// Create a subdir for the cache.
let cache = tempdir.join("cache");
fs::create_dir_all(&cache).unwrap();
@ -151,13 +124,12 @@ fn run_sccache_command_test(sccache: &Path, compiler: Compiler, tempdir: &Path)
trace!("start server");
// Don't run this with run() because on Windows `wait_with_output`
// will hang because the internal server process is not detached.
assert!(Command::new(sccache)
.arg("--start-server")
.current_dir(tempdir)
.env("SCCACHE_DIR", &cache)
.status()
.unwrap()
.success());
Command::main_binary().unwrap()
.arg("--start-server")
.env("SCCACHE_DIR", &cache)
.status()
.unwrap()
.success();
trace!("run_sccache_command_test: {}", name);
// Compile a source file.
const INPUT: &'static str = "test.c";
@ -173,30 +145,47 @@ fn run_sccache_command_test(sccache: &Path, compiler: Compiler, tempdir: &Path)
let out_file = tempdir.join("test.o");
trace!("compile");
assert_eq!(true, run(sccache, &compile_cmdline(name, &exe, INPUT, OUTPUT), tempdir, &env_vars));
Command::main_binary().unwrap()
.args(&compile_cmdline(name, &exe, INPUT, OUTPUT))
.current_dir(tempdir)
.envs(env_vars.clone())
.assert()
.success();
assert_eq!(true, fs::metadata(&out_file).and_then(|m| Ok(m.len() > 0)).unwrap());
trace!("request stats");
let info = get_stats(sccache, tempdir);
assert_eq!(1, info.stats.compile_requests);
assert_eq!(1, info.stats.requests_executed);
assert_eq!(0, info.stats.cache_hits);
assert_eq!(1, info.stats.cache_misses);
get_stats(|info| {
assert_eq!(1, info.stats.compile_requests);
assert_eq!(1, info.stats.requests_executed);
assert_eq!(0, info.stats.cache_hits);
assert_eq!(1, info.stats.cache_misses);
});
trace!("compile");
fs::remove_file(&out_file).unwrap();
assert_eq!(true, run(sccache, &compile_cmdline(name, &exe, INPUT, OUTPUT), tempdir, &env_vars));
Command::main_binary().unwrap()
.args(&compile_cmdline(name, &exe, INPUT, OUTPUT))
.current_dir(tempdir)
.envs(env_vars.clone())
.assert()
.success();
assert_eq!(true, fs::metadata(&out_file).and_then(|m| Ok(m.len() > 0)).unwrap());
trace!("request stats");
let info = get_stats(sccache, tempdir);
assert_eq!(2, info.stats.compile_requests);
assert_eq!(2, info.stats.requests_executed);
assert_eq!(1, info.stats.cache_hits);
assert_eq!(1, info.stats.cache_misses);
get_stats(|info| {
assert_eq!(2, info.stats.compile_requests);
assert_eq!(2, info.stats.requests_executed);
assert_eq!(1, info.stats.cache_hits);
assert_eq!(1, info.stats.cache_misses);
});
if name == "cl.exe" {
// Check that -deps works.
trace!("compile with -deps");
let mut args = compile_cmdline(name, &exe, INPUT, OUTPUT);
args.push("-depstest.d".into());
assert_eq!(true, run(sccache, &args, tempdir, &env_vars));
Command::main_binary().unwrap()
.args(&args)
.current_dir(tempdir)
.envs(env_vars.clone())
.assert()
.success();
// Check the contents
let mut f = File::open(tempdir.join("test.d")).expect("Failed to open dep file");
let mut buf = String::new();
@ -212,14 +201,17 @@ fn run_sccache_command_test(sccache: &Path, compiler: Compiler, tempdir: &Path)
trace!("test -MP with -Werror");
let mut args = compile_cmdline(name, &exe, INPUT_ERR, OUTPUT);
args.extend(vec_from!(OsString, "-MD", "-MP", "-MF", "foo.pp", "-Werror"));
let output = do_run(sccache, &args, tempdir, &env_vars);
assert!(!output.status.success());
// This should fail, but the error should be from the #error!
let stderr = String::from_utf8(output.stderr).expect("Couldn't convert stderr to String");
assert!(stderr.find("to generate dependencies you must specify either -M or -MM").is_none(), "Should not have complained about commandline arguments");
Command::main_binary().unwrap()
.args(&args)
.current_dir(tempdir)
.envs(env_vars.clone())
.assert()
.failure()
.stderr(predicates::str::contains(
"to generate dependencies you must specify either -M or -MM").from_utf8().not());
trace!("test -fprofile-generate with different source inputs");
do_run(sccache, &["--zero-stats"], tempdir, &[]);
zero_stats();
const SRC: &str = "source.c";
write_source(&tempdir, SRC, "/*line 1*/
#ifndef UNDEFINED
@ -233,16 +225,28 @@ int main(int argc, char** argv) {
let mut args = compile_cmdline(name, &exe, SRC, OUTPUT);
args.extend(vec_from!(OsString, "-fprofile-generate"));
trace!("compile source.c (1)");
assert_eq!(true, run(sccache, &args, tempdir, &env_vars));
let info = get_stats(sccache, tempdir);
assert_eq!(0, info.stats.cache_hits);
assert_eq!(1, info.stats.cache_misses);
Command::main_binary().unwrap()
.args(&args)
.current_dir(tempdir)
.envs(env_vars.clone())
.assert()
.success();
get_stats(|info| {
assert_eq!(0, info.stats.cache_hits);
assert_eq!(1, info.stats.cache_misses);
});
// Compile the same source again to ensure we can get a cache hit.
trace!("compile source.c (2)");
assert_eq!(true, run(sccache, &args, tempdir, &env_vars));
let info = get_stats(sccache, tempdir);
assert_eq!(1, info.stats.cache_hits);
assert_eq!(1, info.stats.cache_misses);
Command::main_binary().unwrap()
.args(&args)
.current_dir(tempdir)
.envs(env_vars.clone())
.assert()
.success();
get_stats(|info| {
assert_eq!(1, info.stats.cache_hits);
assert_eq!(1, info.stats.cache_misses);
});
// Now write out a slightly different source file that will preprocess to the same thing,
// modulo line numbers. This should not be a cache hit because line numbers are important
// with -fprofile-generate.
@ -257,13 +261,19 @@ int main(int argc, char** argv) {
}
");
trace!("compile source.c (3)");
assert_eq!(true, run(sccache, &args, tempdir, &env_vars));
let info = get_stats(sccache, tempdir);
assert_eq!(1, info.stats.cache_hits);
assert_eq!(2, info.stats.cache_misses);
Command::main_binary().unwrap()
.args(&args)
.current_dir(tempdir)
.envs(env_vars.clone())
.assert()
.success();
get_stats(|info| {
assert_eq!(1, info.stats.cache_hits);
assert_eq!(2, info.stats.cache_misses);
});
}
trace!("stop server");
assert_eq!(true, run(sccache, &["--stop-server"], tempdir, &[]));
stop();
}
#[cfg(unix)]
@ -311,13 +321,12 @@ fn test_sccache_command() {
Err(_) => {},
}
let tempdir = TempDir::new("sccache_system_test").unwrap();
let sccache = find_sccache_binary();
let compilers = find_compilers();
if compilers.is_empty() {
warn!("No compilers found, skipping test");
} else {
for compiler in compilers {
run_sccache_command_test(&sccache, compiler, tempdir.path())
run_sccache_command_test(compiler, tempdir.path())
}
}
}