Skip to content

Commit

Permalink
Run all run(-dep) tests natively, too
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Oct 8, 2024
1 parent d28fb80 commit ca3fd79
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 36 deletions.
18 changes: 11 additions & 7 deletions tests/pass-dep/libc/libc-mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,17 @@ fn test_strcpy() {
}

fn test_malloc() {
// Test that small allocations sometimes *are* not very aligned.
let saw_unaligned = (0..64).any(|_| unsafe {
let p = libc::malloc(3);
libc::free(p);
(p as usize) % 4 != 0 // find any that this is *not* 4-aligned
});
assert!(saw_unaligned);
// Real systems may always align to at least a specific power of 2 (like 4 or 8).
#[cfg(miri)]
{
// Test that small allocations sometimes *are* not very aligned.
let saw_unaligned = (0..64).any(|_| unsafe {
let p = libc::malloc(3);
libc::free(p);
(p as usize) % 4 != 0 // find any that this is *not* 4-aligned
});
assert!(saw_unaligned);
}

unsafe {
let p1 = libc::malloc(20);
Expand Down
1 change: 1 addition & 0 deletions tests/pass-dep/num_cpus.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//@compile-flags: -Zmiri-disable-isolation
//@only-miri: fake cpu number

fn main() {
assert_eq!(num_cpus::get(), 1);
Expand Down
1 change: 1 addition & 0 deletions tests/pass-dep/page_size_override.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//@compile-flags: -Zmiri-force-page-size=8
//@only-miri: fake page size

fn main() {
let page_size = page_size::get();
Expand Down
179 changes: 150 additions & 29 deletions tests/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@ use colored::*;
use regex::bytes::Regex;
use ui_test::build_manager::BuildManager;
use ui_test::color_eyre::eyre::{Context, Result};
use ui_test::custom_flags::Flag;
use ui_test::custom_flags::edition::Edition;
use ui_test::custom_flags::run::Run;
use ui_test::dependencies::DependencyBuilder;
use ui_test::per_test_config::TestConfig;
use ui_test::per_test_config::{Comments, Condition, TestConfig};
use ui_test::spanned::Spanned;
use ui_test::{CommandBuilder, Config, Format, Match, ignore_output_conflict, status_emitter};
use ui_test::{
CommandBuilder, Config, Errored, Format, Match, ignore_output_conflict, status_emitter,
};

#[derive(Copy, Clone, Debug)]
enum Mode {
Pass,
Pass {
/// Whether to compile and run with rustc instead of miri
rustc: bool,
},
/// Requires annotations
Fail,
/// Not used for tests, but for `miri run --dep`
Expand Down Expand Up @@ -107,8 +114,89 @@ fn miri_config(
..Config::rustc(path)
};

if let Mode::Pass { rustc: true } = mode {
config.comment_defaults.base().add_custom("run", Run {
exit_code: 0,
output_conflict_handling: Some(|path, actual, errors, config| {
let path = path.with_file_name(
path.file_name().unwrap().to_str().unwrap().replace(".run.", "."),
);
// Blessing is only allowed in miri mode, rustc mode must match
ui_test::error_on_output_conflict(&path, actual, errors, config);
}),
});
config.program.envs.push(("MIRI_BE_RUSTC".into(), Some("host".into())));

#[derive(Debug)]
struct Strip;

impl Flag for Strip {
fn clone_inner(&self) -> Box<dyn Flag> {
Box::new(Strip)
}

fn must_be_unique(&self) -> bool {
true
}

fn apply(
&self,
cmd: &mut Command,
_config: &TestConfig,
_build_manager: &BuildManager,
) -> Result<(), Errored> {
let mut c = Command::new(cmd.get_program());
for (k, v) in cmd.get_envs() {
match v {
Some(v) => c.env(k, v),
None => c.env_remove(k),
};
}
if let Some(dir) = cmd.get_current_dir() {
c.current_dir(dir);
}
c.args(
cmd.get_args().filter(|arg| !arg.as_encoded_bytes().starts_with(b"-Zmiri-")),
);
*cmd = c;
Ok(())
}

fn test_condition(
&self,
_config: &Config,
comments: &Comments,
revision: &str,
) -> bool {
for rev in comments.for_revision(revision) {
for arg in &rev.compile_flags {
// A real execution will preempt, and thus behave differently
if arg.starts_with("-Zmiri-preemption-rate") {
return true;
}
// FIXME: can probably support these somehow
if arg.starts_with("-Zmiri-env") {
return true;
}
}
}
false
}
}

config.comment_defaults.base().add_custom("strip_dash_z_miri", Strip);

// Only run on no target if `only-miri` is passed.
config
.custom_comments
.insert("only-miri", |parser, _, _| parser.only.push(Condition::Target(vec![])));
} else {
// Nop, we are in miri mode
config.custom_comments.insert("only-miri", |_, _, _| {});
}

config.comment_defaults.base().exit_status = match mode {
Mode::Pass => Some(0),
Mode::Pass { .. } => Some(0),
Mode::Fail => Some(1),
Mode::RunDep => None,
Mode::Panic => Some(101),
Expand All @@ -128,18 +216,23 @@ fn miri_config(
config.comment_defaults.base().add_custom("edition", Edition("2021".into()));

if let Some(WithDependencies { bless }) = with_dependencies {
let program = match mode {
Mode::Pass { rustc: true } => CommandBuilder::cargo(),
_ =>
CommandBuilder {
// Set the `cargo-miri` binary, which we expect to be in the same folder as the `miri` binary.
// (It's a separate crate, so we don't get an env var from cargo.)
program: miri_path()
.with_file_name(format!("cargo-miri{}", env::consts::EXE_SUFFIX)),
// There is no `cargo miri build` so we just use `cargo miri run`.
args: ["miri", "run"].into_iter().map(Into::into).collect(),
// Reset `RUSTFLAGS` to work around <https://github.com/rust-lang/rust/pull/119574#issuecomment-1876878344>.
envs: vec![("RUSTFLAGS".into(), None)],
..CommandBuilder::cargo()
},
};
config.comment_defaults.base().set_custom("dependencies", DependencyBuilder {
program: CommandBuilder {
// Set the `cargo-miri` binary, which we expect to be in the same folder as the `miri` binary.
// (It's a separate crate, so we don't get an env var from cargo.)
program: miri_path()
.with_file_name(format!("cargo-miri{}", env::consts::EXE_SUFFIX)),
// There is no `cargo miri build` so we just use `cargo miri run`.
args: ["miri", "run"].into_iter().map(Into::into).collect(),
// Reset `RUSTFLAGS` to work around <https://github.com/rust-lang/rust/pull/119574#issuecomment-1876878344>.
envs: vec![("RUSTFLAGS".into(), None)],
..CommandBuilder::cargo()
},
program,
crate_manifest_path: Path::new("test_dependencies").join("Cargo.toml"),
build_std: None,
bless_lockfile: bless,
Expand All @@ -163,7 +256,19 @@ fn run_tests(

let mut config = miri_config(target, path, mode, with_dependencies);
config.with_args(&args);
config.bless_command = Some("./miri test --bless".into());
if let Mode::Pass { rustc: true } = mode {
config.fill_host_and_target()?;
// Rustc mode only works on the host
if !config.host_matches_target() {
return Ok(());
}
config.output_conflict_handling = ui_test::ignore_output_conflict;

config.bless_command =
Some("add `//@only-miri:` to the test if it cannot be run on the host directly".into());
} else {
config.bless_command = Some("./miri test --bless".into());
}

if env::var_os("MIRI_SKIP_UI_CHECKS").is_some() {
assert!(!args.bless, "cannot use RUSTC_BLESS and MIRI_SKIP_UI_CHECKS at the same time");
Expand All @@ -174,17 +279,25 @@ fn run_tests(
config.program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into())));
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
config.program.envs.push(("MIRI_TEMP".into(), Some(tmpdir.to_owned().into())));
// If a test ICEs, we want to see a backtrace.
config.program.envs.push(("RUST_BACKTRACE".into(), Some("1".into())));

// Add some flags we always want.
config.program.args.push(
format!(
"--sysroot={}",
env::var("MIRI_SYSROOT").expect("MIRI_SYSROOT must be set to run the ui test suite")
)
.into(),
);
match mode {
// rustc mode doesn't want miri specific flags
Mode::Pass { rustc: true } => {}
_ => {
// If a test ICEs, we want to see a backtrace.
config.program.envs.push(("RUST_BACKTRACE".into(), Some("1".into())));
config.program.args.push(
format!(
"--sysroot={}",
env::var("MIRI_SYSROOT")
.expect("MIRI_SYSROOT must be set to run the ui test suite")
)
.into(),
);
}
}

config.program.args.push("-Dwarnings".into());
config.program.args.push("-Dunused".into());
config.program.args.push("-Ainternal_features".into());
Expand Down Expand Up @@ -274,7 +387,7 @@ regexes! {
// Windows file paths
r"\\" => "/",
// erase Rust stdlib path
"[^ \n`]*/(rust[^/]*|checkout)/library/" => "RUSTLIB/",
"[^ \n`]*/(rust[^/]*|checkout|rustc/[0-9a-f]+)/library/" => "RUSTLIB/",
// erase platform file paths
"sys/pal/[a-z]+/" => "sys/pal/PLATFORM/",
// erase paths into the crate registry
Expand Down Expand Up @@ -327,13 +440,21 @@ fn main() -> Result<()> {
}
}

ui(Mode::Pass, "tests/pass", &target, WithoutDependencies, tmpdir.path())?;
ui(Mode::Pass, "tests/pass-dep", &target, WithDependencies, tmpdir.path())?;
ui(Mode::Pass { rustc: false }, "tests/pass", &target, WithoutDependencies, tmpdir.path())?;
for rustc in [false, true] {
ui(Mode::Pass { rustc }, "tests/pass-dep", &target, WithDependencies, tmpdir.path())?;
}
ui(Mode::Panic, "tests/panic", &target, WithDependencies, tmpdir.path())?;
ui(Mode::Fail, "tests/fail", &target, WithoutDependencies, tmpdir.path())?;
ui(Mode::Fail, "tests/fail-dep", &target, WithDependencies, tmpdir.path())?;
if cfg!(unix) {
ui(Mode::Pass, "tests/native-lib/pass", &target, WithoutDependencies, tmpdir.path())?;
ui(
Mode::Pass { rustc: false },
"tests/native-lib/pass",
&target,
WithoutDependencies,
tmpdir.path(),
)?;
ui(Mode::Fail, "tests/native-lib/fail", &target, WithoutDependencies, tmpdir.path())?;
}

Expand Down

0 comments on commit ca3fd79

Please sign in to comment.