Skip to content

Cargo miri tweaks and test that we can exclude tests #580

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

Merged
merged 8 commits into from
Dec 19, 2018
Merged
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
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -38,3 +38,4 @@ branches:
env:
global:
- RUST_TEST_NOCAPTURE=1
- RUST_BACKTRACE=1
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -39,17 +39,28 @@ example above), overriding it in your project directory as well, or use `rustup
default nightly` (or `rustup default nightly-YYYY-MM-DD`) to globally make
`nightly` the default toolchain.

Now you can run your project in miri:
Now you can run your project in Miri:

1. Run `cargo clean` to eliminate any cached dependencies. Miri needs your
dependencies to be compiled the right way, that would not happen if they have
previously already been compiled.
2. To run all tests in your project through Miri, use `cargo +nightly miri test`.
**NOTE**: This is currently broken, see the discussion in
[#479](https://github.com/solson/miri/issues/479).
3. If you have a binary project, you can run it through Miri using `cargo
+nightly miri run`.

When running code via `cargo miri`, the `cargo-miri` feature is set. You can
use this to exclude test cases that will fail under Miri because they do things
Miri does not support:

```rust
#[cfg(not(feature = "cargo-miri"))]
#[test]
fn does_not_work_on_miri() {
let x = 0u8;
assert!(&x as *const _ as usize % 4 < 4);
}
```

### Common Problems

When using the above instructions, you may encounter a number of confusing compiler
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ install:
build: false

test_script:
- set RUSTFLAGS=-g
- set RUST_TEST_NOCAPTURE=1
- set RUST_BACKTRACE=1
# Build miri
- cargo build --release --all-features --all-targets
12 changes: 8 additions & 4 deletions src/bin/cargo-miri.rs
Original file line number Diff line number Diff line change
@@ -123,8 +123,14 @@ fn xargo_version() -> Option<(u32, u32, u32)> {
let line = out.stderr.lines().nth(0)
.expect("malformed `xargo --version` output: not at least one line")
.expect("malformed `xargo --version` output: error reading first line");
let version = line.split(' ').nth(1)
.expect("malformed `xargo --version` output: not at least two words");
let (name, version) = {
let mut split = line.split(' ');
(split.next().expect("malformed `xargo --version` output: empty"),
split.next().expect("malformed `xargo --version` output: not at least two words"))
};
if name != "xargo" {
panic!("malformed `xargo --version` output: application name is not `xargo`");
}
let mut version_pieces = version.split('.');
let major = version_pieces.next()
.expect("malformed `xargo --version` output: not a major version piece")
@@ -414,8 +420,6 @@ where
args.push("--".to_owned());
}
args.push("--emit=dep-info,metadata".to_owned());
args.push("--cfg".to_owned());
args.push(r#"feature="cargo-miri""#.to_owned());

let path = std::env::current_exe().expect("current executable path invalid");
let exit_status = Command::new("cargo")
2 changes: 1 addition & 1 deletion src/fn_call.rs
Original file line number Diff line number Diff line change
@@ -398,7 +398,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
Err(_) => -1,
}
} else {
warn!("Ignored output to FD {}", fd);
eprintln!("Miri: Ignored output to FD {}", fd);
n as i64 // pretend it all went well
}; // now result is the value we return back to the program
this.write_scalar(
12 changes: 7 additions & 5 deletions test-cargo-miri/run-test.py
Original file line number Diff line number Diff line change
@@ -7,6 +7,10 @@

import sys, subprocess

def fail(msg):
print("TEST FAIL: {}".format(msg))
sys.exit(1)

def test(name, cmd, stdout_ref, stderr_ref):
print("==> Testing `{}` <==".format(name))
## Call `cargo miri`, capture all output
@@ -25,13 +29,11 @@ def test(name, cmd, stdout_ref, stderr_ref):
print(stderr, end="")
# Test for failures
if p.returncode != 0:
sys.exit(1)
fail("Non-zero exit status")
if stdout != open(stdout_ref).read():
print("stdout does not match reference")
sys.exit(1)
fail("stdout does not match reference")
if stderr != open(stderr_ref).read():
print("stderr does not match reference")
sys.exit(1)
fail("stderr does not match reference")

def test_cargo_miri_run():
test("cargo miri run", ["cargo", "miri", "run", "-q"], "stdout.ref", "stderr.ref")
8 changes: 8 additions & 0 deletions test-cargo-miri/tests/foo.rs
Original file line number Diff line number Diff line change
@@ -9,3 +9,11 @@ fn bar() {
fn baz() {
assert_eq!(5, 5);
}

// A test that won't work on miri
#[cfg(not(feature = "cargo-miri"))]
#[test]
fn does_not_work_on_miri() {
let x = 0u8;
assert!(&x as *const _ as usize % 4 < 4);
}