Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow ui tests to have dependencies in a reliable way #2373

Merged
merged 1 commit into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 50 additions & 12 deletions cargo-miri/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

mod version;

use std::collections::HashMap;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt::Write as _;
Expand Down Expand Up @@ -114,10 +115,14 @@ fn show_error(msg: String) -> ! {
std::process::exit(1)
}

// Determines whether a `--flag` is present.
/// Determines whether a `--flag` is present.
fn has_arg_flag(name: &str) -> bool {
let mut args = std::env::args().take_while(|val| val != "--");
args.any(|val| val == name)
num_arg_flag(name) > 0
}

/// Determines how many times a `--flag` is present.
fn num_arg_flag(name: &str) -> usize {
std::env::args().take_while(|val| val != "--").filter(|val| val == name).count()
}

/// Yields all values of command line flag `name` as `Ok(arg)`, and all other arguments except
Expand Down Expand Up @@ -588,7 +593,7 @@ fn phase_cargo_miri(mut args: env::Args) {
"`cargo miri` supports the following subcommands: `run`, `test`, and `setup`."
)),
};
let verbose = has_arg_flag("-v");
let verbose = num_arg_flag("-v");

// We always setup.
setup(&subcommand);
Expand Down Expand Up @@ -685,15 +690,15 @@ fn phase_cargo_miri(mut args: env::Args) {
cmd.env("MIRI_LOCAL_CRATES", local_crates(&metadata));

// Run cargo.
if verbose {
if verbose > 0 {
eprintln!("[cargo-miri miri] RUSTC_WRAPPER={:?}", cargo_miri_path);
eprintln!("[cargo-miri miri] {}={:?}", target_runner_env_name, cargo_miri_path);
if *target != host {
eprintln!("[cargo-miri miri] {}={:?}", host_runner_env_name, cargo_miri_path);
}
eprintln!("[cargo-miri miri] RUSTDOC={:?}", cargo_miri_path);
eprintln!("[cargo-miri miri] {:?}", cmd);
cmd.env("MIRI_VERBOSE", ""); // This makes the other phases verbose.
cmd.env("MIRI_VERBOSE", verbose.to_string()); // This makes the other phases verbose.
}
exec(cmd)
}
Expand Down Expand Up @@ -752,7 +757,8 @@ fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
}
}

let verbose = std::env::var_os("MIRI_VERBOSE").is_some();
let verbose = std::env::var("MIRI_VERBOSE")
.map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
let target_crate = is_target_crate();
let print = get_arg_flag_value("--print").is_some() || has_arg_flag("-vV"); // whether this is cargo/xargo invoking rustc to get some infos

Expand All @@ -761,13 +767,13 @@ fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
// https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693
// As we store a JSON file instead of building the crate here, an empty file is fine.
let dep_info_name = out_filename("", ".d");
if verbose {
if verbose > 0 {
eprintln!("[cargo-miri rustc] writing stub dep-info to `{}`", dep_info_name.display());
}
File::create(dep_info_name).expect("failed to create fake .d file");

let filename = out_filename("", "");
if verbose {
if verbose > 0 {
eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display());
}
info.store(&filename);
Expand Down Expand Up @@ -810,7 +816,7 @@ fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
cmd.args(&env.args);
cmd.env("MIRI_BE_RUSTC", "target");

if verbose {
if verbose > 0 {
eprintln!(
"[cargo-miri rustc] captured input:\n{}",
std::str::from_utf8(&env.stdin).unwrap()
Expand Down Expand Up @@ -877,6 +883,15 @@ fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
cmd.arg("-C").arg("panic=abort");
}
} else {
// For host crates (but not when we are printing), we might still have to set the sysroot.
if !print {
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
// When we're running `cargo-miri` from `x.py` we need to pass the sysroot explicitly as rustc
// can't figure out the sysroot on its own unless it's from rustup.
if let Some(sysroot) = std::env::var_os("SYSROOT") {
cmd.arg("--sysroot").arg(sysroot);
}
}

// For host crates or when we are printing, just forward everything.
cmd.args(args);
}
Expand All @@ -888,8 +903,14 @@ fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
cmd.env("MIRI_BE_RUSTC", if target_crate { "target" } else { "host" });

// Run it.
if verbose {
eprintln!("[cargo-miri rustc] {:?}", cmd);
if verbose > 0 {
eprint!("[cargo-miri rustc] ");
if verbose > 1 {
for (key, value) in env_vars_from_cmd(&cmd) {
eprintln!("{key}={value:?} \\");
}
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
}
eprintln!("{:?}", cmd);
}
exec(cmd);

Expand All @@ -908,6 +929,23 @@ fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
}
}

fn env_vars_from_cmd(cmd: &Command) -> Vec<(String, String)> {
let mut envs = HashMap::new();
for (key, value) in std::env::vars() {
envs.insert(key, value);
}
for (key, value) in cmd.get_envs() {
if let Some(value) = value {
envs.insert(key.to_str().unwrap().into(), value.to_str().unwrap().to_owned());
} else {
envs.remove(key.to_str().unwrap());
}
}
let mut envs: Vec<_> = envs.into_iter().collect();
envs.sort();
envs
}

#[derive(Debug, Copy, Clone, PartialEq)]
enum RunnerPhase {
/// `cargo` is running a binary
Expand Down
23 changes: 2 additions & 21 deletions test-cargo-miri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions test-cargo-miri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ issue_rust_86261 = { path = "issue-rust-86261" }

[dev-dependencies]
rand = { version = "0.8", features = ["small_rng"] }
getrandom_1 = { package = "getrandom", version = "0.1" }
getrandom_2 = { package = "getrandom", version = "0.2" }
serde_derive = "1.0" # not actually used, but exercises some unique code path (`--extern` .so file)
page_size = "0.4.1"

Expand Down
28 changes: 18 additions & 10 deletions test-cargo-miri/run-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
and the working directory to contain the cargo-miri-test project.
'''

import sys, subprocess, os, re
import sys, subprocess, os, re, difflib

CGREEN = '\33[32m'
CBOLD = '\33[1m'
Expand All @@ -27,6 +27,17 @@ def normalize_stdout(str):
str = str.replace("src\\", "src/") # normalize paths across platforms
return re.sub("finished in \d+\.\d\ds", "finished in $TIME", str)

def check_output(actual, path, name):
expected = open(path).read()
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
if expected == actual:
return True
print(f"{path} did not match reference!")
print(f"--- BEGIN diff {name} ---")
for text in difflib.unified_diff(expected.split("\n"), actual.split("\n")):
print(text)
print(f"--- END diff {name} ---")
return False

def test(name, cmd, stdout_ref, stderr_ref, stdin=b'', env={}):
print("Testing {}...".format(name))
## Call `cargo miri`, capture all output
Expand All @@ -42,17 +53,14 @@ def test(name, cmd, stdout_ref, stderr_ref, stdin=b'', env={}):
(stdout, stderr) = p.communicate(input=stdin)
stdout = stdout.decode("UTF-8")
stderr = stderr.decode("UTF-8")
if p.returncode == 0 and normalize_stdout(stdout) == open(stdout_ref).read() and stderr == open(stderr_ref).read():
stdout = normalize_stdout(stdout)

stdout_matches = check_output(stdout, stdout_ref, "stdout")
stderr_matches = check_output(stderr, stderr_ref, "stderr")

if p.returncode == 0 and stdout_matches and stderr_matches:
# All good!
return
# Show output
print("Test stdout or stderr did not match reference!")
print("--- BEGIN test stdout ---")
print(stdout, end="")
print("--- END test stdout ---")
print("--- BEGIN test stderr ---")
print(stderr, end="")
print("--- END test stderr ---")
fail("exit code was {}".format(p.returncode))

def test_no_rebuild(name, cmd, env={}):
Expand Down
8 changes: 1 addition & 7 deletions test-cargo-miri/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,9 @@ fn does_not_work_on_miri() {
assert!(&x as *const _ as usize % 4 < 4);
}

// We also use this to test some external crates, that we cannot depend on in the compiletest suite.

// Make sure integration tests can access dev-dependencies
#[test]
fn entropy_rng() {
// Test `getrandom` directly (in multiple different versions).
let mut data = vec![0; 16];
getrandom_1::getrandom(&mut data).unwrap();
getrandom_2::getrandom(&mut data).unwrap();

// Try seeding with "real" entropy.
let mut rng = SmallRng::from_entropy();
let _val = rng.gen::<i32>();
Expand Down
Loading