Skip to content

Commit ab6fb9d

Browse files
committed
Allow tests to have dependencies
1 parent d5e199f commit ab6fb9d

File tree

69 files changed

+792
-165
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+792
-165
lines changed

Cargo.lock

+35
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cargo-miri/bin.rs

+50-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
mod version;
55

6+
use std::collections::HashMap;
67
use std::env;
78
use std::ffi::{OsStr, OsString};
89
use std::fmt::Write as _;
@@ -114,10 +115,14 @@ fn show_error(msg: String) -> ! {
114115
std::process::exit(1)
115116
}
116117

117-
// Determines whether a `--flag` is present.
118+
/// Determines whether a `--flag` is present.
118119
fn has_arg_flag(name: &str) -> bool {
119-
let mut args = std::env::args().take_while(|val| val != "--");
120-
args.any(|val| val == name)
120+
num_arg_flag(name) > 0
121+
}
122+
123+
/// Determines how many times a `--flag` is present.
124+
fn num_arg_flag(name: &str) -> usize {
125+
std::env::args().take_while(|val| val != "--").filter(|val| val == name).count()
121126
}
122127

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

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

687692
// Run cargo.
688-
if verbose {
693+
if verbose > 0 {
689694
eprintln!("[cargo-miri miri] RUSTC_WRAPPER={:?}", cargo_miri_path);
690695
eprintln!("[cargo-miri miri] {}={:?}", target_runner_env_name, cargo_miri_path);
691696
if *target != host {
692697
eprintln!("[cargo-miri miri] {}={:?}", host_runner_env_name, cargo_miri_path);
693698
}
694699
eprintln!("[cargo-miri miri] RUSTDOC={:?}", cargo_miri_path);
695700
eprintln!("[cargo-miri miri] {:?}", cmd);
696-
cmd.env("MIRI_VERBOSE", ""); // This makes the other phases verbose.
701+
cmd.env("MIRI_VERBOSE", verbose.to_string()); // This makes the other phases verbose.
697702
}
698703
exec(cmd)
699704
}
@@ -752,7 +757,8 @@ fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
752757
}
753758
}
754759

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

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

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

813-
if verbose {
819+
if verbose > 0 {
814820
eprintln!(
815821
"[cargo-miri rustc] captured input:\n{}",
816822
std::str::from_utf8(&env.stdin).unwrap()
@@ -877,6 +883,15 @@ fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
877883
cmd.arg("-C").arg("panic=abort");
878884
}
879885
} else {
886+
// For host crates (but not when we are printing), we might still have to set the sysroot.
887+
if !print {
888+
// When we're running `cargo-miri` from `x.py` we need to pass the sysroot explicitly as rustc
889+
// can't figure out the sysroot on its own unless it's from rustup.
890+
if let Some(sysroot) = std::env::var_os("SYSROOT") {
891+
cmd.arg("--sysroot").arg(sysroot);
892+
}
893+
}
894+
880895
// For host crates or when we are printing, just forward everything.
881896
cmd.args(args);
882897
}
@@ -888,8 +903,14 @@ fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
888903
cmd.env("MIRI_BE_RUSTC", if target_crate { "target" } else { "host" });
889904

890905
// Run it.
891-
if verbose {
892-
eprintln!("[cargo-miri rustc] {:?}", cmd);
906+
if verbose > 0 {
907+
eprint!("[cargo-miri rustc] ");
908+
if verbose > 1 {
909+
for (key, value) in env_vars_from_cmd(&cmd) {
910+
eprintln!("{key}={value:?} \\");
911+
}
912+
}
913+
eprintln!("{:?}", cmd);
893914
}
894915
exec(cmd);
895916

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

932+
fn env_vars_from_cmd(cmd: &Command) -> Vec<(String, String)> {
933+
let mut envs = HashMap::new();
934+
for (key, value) in std::env::vars() {
935+
envs.insert(key, value);
936+
}
937+
for (key, value) in cmd.get_envs() {
938+
if let Some(value) = value {
939+
envs.insert(key.to_str().unwrap().into(), value.to_str().unwrap().to_owned());
940+
} else {
941+
envs.remove(key.to_str().unwrap());
942+
}
943+
}
944+
let mut envs: Vec<_> = envs.into_iter().collect();
945+
envs.sort();
946+
envs
947+
}
948+
911949
#[derive(Debug, Copy, Clone, PartialEq)]
912950
enum RunnerPhase {
913951
/// `cargo` is running a binary

test-cargo-miri/Cargo.lock

+2-21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test-cargo-miri/Cargo.toml

-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ issue_rust_86261 = { path = "issue-rust-86261" }
1919

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

test-cargo-miri/run-test.py

+18-10
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
and the working directory to contain the cargo-miri-test project.
66
'''
77

8-
import sys, subprocess, os, re
8+
import sys, subprocess, os, re, difflib
99

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

30+
def check_output(actual, path, name):
31+
expected = open(path).read()
32+
if expected == actual:
33+
return True
34+
print(f"{path} did not match reference!")
35+
print(f"--- BEGIN diff {name} ---")
36+
for text in difflib.unified_diff(expected.split("\n"), actual.split("\n")):
37+
print(text)
38+
print(f"--- END diff {name} ---")
39+
return False
40+
3041
def test(name, cmd, stdout_ref, stderr_ref, stdin=b'', env={}):
3142
print("Testing {}...".format(name))
3243
## Call `cargo miri`, capture all output
@@ -42,17 +53,14 @@ def test(name, cmd, stdout_ref, stderr_ref, stdin=b'', env={}):
4253
(stdout, stderr) = p.communicate(input=stdin)
4354
stdout = stdout.decode("UTF-8")
4455
stderr = stderr.decode("UTF-8")
45-
if p.returncode == 0 and normalize_stdout(stdout) == open(stdout_ref).read() and stderr == open(stderr_ref).read():
56+
stdout = normalize_stdout(stdout)
57+
58+
stdout_matches = check_output(stdout, stdout_ref, "stdout")
59+
stderr_matches = check_output(stderr, stderr_ref, "stderr")
60+
61+
if p.returncode == 0 and stdout_matches and stderr_matches:
4662
# All good!
4763
return
48-
# Show output
49-
print("Test stdout or stderr did not match reference!")
50-
print("--- BEGIN test stdout ---")
51-
print(stdout, end="")
52-
print("--- END test stdout ---")
53-
print("--- BEGIN test stderr ---")
54-
print(stderr, end="")
55-
print("--- END test stderr ---")
5664
fail("exit code was {}".format(p.returncode))
5765

5866
def test_no_rebuild(name, cmd, env={}):

test-cargo-miri/tests/test.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,9 @@ fn does_not_work_on_miri() {
2020
assert!(&x as *const _ as usize % 4 < 4);
2121
}
2222

23-
// We also use this to test some external crates, that we cannot depend on in the compiletest suite.
24-
23+
// Make sure integration tests can access dev-dependencies
2524
#[test]
2625
fn entropy_rng() {
27-
// Test `getrandom` directly (in multiple different versions).
28-
let mut data = vec![0; 16];
29-
getrandom_1::getrandom(&mut data).unwrap();
30-
getrandom_2::getrandom(&mut data).unwrap();
31-
3226
// Try seeding with "real" entropy.
3327
let mut rng = SmallRng::from_entropy();
3428
let _val = rng.gen::<i32>();

0 commit comments

Comments
 (0)