Skip to content

Commit 73b9fbc

Browse files
bdalrhmtedinski
authored andcommitted
Add support for multiple expected failures. (rust-lang#280)
* Add support for multiple expected failures. * Check for expected failures on RMC's output instead of test file. * Address concerns.
1 parent 2f84b32 commit 73b9fbc

File tree

2 files changed

+49
-10
lines changed

2 files changed

+49
-10
lines changed

src/test/cbmc/DynTrait/vtable_size_align_drop_fail.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#![allow(deprecated)]
1414

1515
use std::intrinsics::size_of;
16+
use std::ptr::drop_in_place;
1617

1718
include!("../Helpers/vtable_utils_ignore.rs");
1819
include!("../../rmc-prelude.rs");
@@ -68,7 +69,7 @@ fn main() {
6869

6970
// Check layout/values for Sheep
7071
unsafe {
71-
let animal_sheep = random_animal(1);
72+
let animal_sheep = &*random_animal(1);
7273

7374
// Check that the struct's data is what we expect
7475
let data_ptr = data!(animal_sheep);
@@ -90,15 +91,15 @@ fn main() {
9091
}
9192
// Check layout/values for Cow
9293
unsafe {
93-
let animal_sheep = random_animal(1);
94+
let animal_cow = &*random_animal(6);
9495

9596
// Check that the struct's data is what we expect
96-
let data_ptr = data!(animal_sheep);
97+
let data_ptr = data!(animal_cow);
9798

9899
// Note: i8 ptr cast
99100
__VERIFIER_expect_fail(*(data_ptr as *mut i8) != 9, "Wrong data"); // From Cow
100101

101-
let vtable_ptr = vtable!(animal_sheep);
102+
let vtable_ptr = vtable!(animal_cow);
102103

103104
// Drop pointer
104105
__VERIFIER_expect_fail(

src/tools/compiletest/src/runtest.rs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,18 +2418,56 @@ impl<'test> TestCx<'test> {
24182418
.args(&self.props.cbmc_flags);
24192419
self.add_rmc_dir_to_path(&mut rmc);
24202420
let proc_res = self.compose_and_run_compiler(rmc, None);
2421-
// Print an error if the verification result is not expected.
2422-
if self.should_compile_successfully(self.pass_mode()) {
2423-
if !proc_res.status.success() {
2424-
self.fatal_proc_rec("test failed: expected success, got failure", &proc_res);
2421+
// If the test file contains expected failures in some locations, ensure
2422+
// that verification does indeed fail in those locations
2423+
if proc_res.stdout.contains("EXPECTED FAIL") {
2424+
let lines = TestCx::verify_expect_fail(&proc_res.stdout);
2425+
if !lines.is_empty() {
2426+
self.fatal_proc_rec(
2427+
&format!("test failed: expected failure in lines {:?}, got success", lines),
2428+
&proc_res,
2429+
)
24252430
}
24262431
} else {
2427-
if proc_res.status.success() {
2428-
self.fatal_proc_rec("test failed: expected failure, got success", &proc_res);
2432+
// The code above depends too much on the exact string output of
2433+
// RMC. If the output of RMC changes in the future, the check below
2434+
// will (hopefully) force some tests to fail and remind us to
2435+
// update the code above as well.
2436+
if fs::read_to_string(&self.testpaths.file).unwrap().contains("__VERIFIER_expect_fail")
2437+
{
2438+
self.fatal_proc_rec(
2439+
"found call to `__VERIFIER_expect_fail` with no corresponding \
2440+
\"EXPECTED FAIL\" in RMC's output",
2441+
&proc_res,
2442+
)
2443+
}
2444+
// Print an error if the verification result is not expected.
2445+
if self.should_compile_successfully(self.pass_mode()) {
2446+
if !proc_res.status.success() {
2447+
self.fatal_proc_rec("test failed: expected success, got failure", &proc_res);
2448+
}
2449+
} else {
2450+
if proc_res.status.success() {
2451+
self.fatal_proc_rec("test failed: expected failure, got success", &proc_res);
2452+
}
24292453
}
24302454
}
24312455
}
24322456

2457+
/// If the test file contains expected failures in some locations, ensure
2458+
/// that verification does not succeed in those locations.
2459+
fn verify_expect_fail(str: &str) -> Vec<usize> {
2460+
let re = Regex::new(r"line [0-9]+ EXPECTED FAIL: SUCCESS").unwrap();
2461+
let mut lines = vec![];
2462+
for m in re.find_iter(str) {
2463+
let splits = m.as_str().split_ascii_whitespace();
2464+
let num_str = splits.skip(1).next().unwrap();
2465+
let num = num_str.parse().unwrap();
2466+
lines.push(num);
2467+
}
2468+
lines
2469+
}
2470+
24332471
/// Runs cargo-rmc on the function specified by the stem of `self.testpaths.file`.
24342472
/// An error message is printed to stdout if verification output does not
24352473
/// contain the expected output in `self.testpaths.file`.

0 commit comments

Comments
 (0)