@@ -2418,18 +2418,56 @@ impl<'test> TestCx<'test> {
2418
2418
. args ( & self . props . cbmc_flags ) ;
2419
2419
self . add_rmc_dir_to_path ( & mut rmc) ;
2420
2420
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
+ )
2425
2430
}
2426
2431
} 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
+ }
2429
2453
}
2430
2454
}
2431
2455
}
2432
2456
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
+
2433
2471
/// Runs cargo-rmc on the function specified by the stem of `self.testpaths.file`.
2434
2472
/// An error message is printed to stdout if verification output does not
2435
2473
/// contain the expected output in `self.testpaths.file`.
0 commit comments