Skip to content
Merged
Show file tree
Hide file tree
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: 0 additions & 1 deletion rust-tests/.gitignore

This file was deleted.

51 changes: 0 additions & 51 deletions rust-tests/run.sh

This file was deleted.

9 changes: 2 additions & 7 deletions scripts/rmc-regression.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,14 @@ check-cbmc-version.py --major 5 --minor 30
# Standalone rmc tests
pushd $RUST_DIR
./x.py build -i --stage 1 library/std ${EXTRA_X_PY_BUILD_ARGS}
cd rust-tests
for TEST_DIR in cbmc-reg smack-regressions prusti-regressions; do
./run.sh $TEST_DIR
done
./run.sh firecracker-like 2
./x.py test -i --stage 1 cbmc firecracker prusti smack

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯


# Standalone cargo-rmc tests
cd ../cargo-rmc-tests
cd cargo-rmc-tests
for DIR in */; do
./run.py $DIR
done
popd

# run-make tests
./x.py test -i --stage 1 src/test/run-make --test-args gotoc
./x.py test -i --stage 1 src/test/cbmc
7 changes: 6 additions & 1 deletion src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,9 +434,14 @@ impl<'a> Builder<'a> {
test::RustdocJson,
// Run bootstrap close to the end as it's unlikely to fail
test::Bootstrap,
// RMC regression tests
test::CBMC,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment here to mark the beginning of RMC tests?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

test::Firecracker,
test::Prusti,
test::Serial,
test::SMACK,
// Run run-make last, since these won't pass without make on Windows
test::RunMake,
test::CBMC,
),
Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
Kind::Doc => describe!(
Expand Down
8 changes: 8 additions & 0 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,14 @@ default_test!(Assembly { path: "src/test/assembly", mode: "assembly", suite: "as

default_test!(CBMC { path: "src/test/cbmc", mode: "rmc", suite: "cbmc" });

default_test!(Firecracker { path: "src/test/firecracker", mode: "rmc", suite: "firecracker" });

default_test!(Prusti { path: "src/test/prusti", mode: "rmc", suite: "prusti" });

default_test!(Serial { path: "src/test/serial", mode: "rmc", suite: "serial" });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we are not running these at the moment, but do you know how much they would take to complete?


default_test!(SMACK { path: "src/test/smack", mode: "rmc", suite: "smack" });

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct Compiletest {
compiler: Compiler,
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file modified src/test/cbmc/Bool-BoolOperators/main.rs
100755 → 100644
Empty file.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT

// cbmc-flags: --bounds-check

#![feature(core_intrinsics)]
use std::intrinsics::ctlz_nonzero;

/// rmc bounds_fail.rs -- --bounds-check
fn main() {
let uv8: u8 = 0;
let uv16: u16 = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT

// cbmc-flags: --bounds-check

#![feature(core_intrinsics)]
use std::intrinsics::cttz_nonzero;

/// rmc bounds_fail.rs -- --bounds-check
fn main() {
let uv8: u8 = 0;
let uv16: u16 = 0;
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT

// cbmc-flags: --unwind 10

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No --unwinding-assertions?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for any reasonably small unwind value (I gave up at 1000). We might be able to add the flag if we set an upper bound to x.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see. This would be a good candidate for the RMC flag that allows you to opt-out from basic safety checks like --unwinding-assertions


fn __nondet<T>() -> T {
unimplemented!()
}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT

// cbmc-flags: --unwind 10 --unwinding-assertions

fn __nondet<T>() -> T {
unimplemented!()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT

// cbmc-flags: --unwind 11 --unwinding-assertions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was not failing before because we had not included --unwinding-assertions, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.


fn __nondet<T>() -> T {
unimplemented!()
}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT
/// rmc main.rs -- --unwind 6 --unwinding-assertions

// cbmc-flags: --unwind 6 --unwinding-assertions

fn main() {
let name: &str = "hello";
assert!(name == "hello");
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT

// cbmc-flags: --unwind 2 --unwinding-assertions

fn doswitch_int() -> i32 {
for i in [99].iter() {
if *i == 99 {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT

// cbmc-flags: --unwind 2 --unwinding-assertions

fn main() {
let mut iter = "A few words".split_whitespace();
match iter.next() {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT

// cbmc-flags: --unwind 4 --unwinding-assertions

use std::cmp::Ordering::*;

/// this is interestingly a wrong implementation at
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// @flag --no-memory-splitting --unroll=4
// @expect verified

// cbmc-flags: --unwind 5 --unwinding-assertions

fn __nondet<T>() -> T {
unimplemented!()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// @flag --no-memory-splitting --unroll=10
// @expect error

// cbmc-flags: --unwind 5 --unwinding-assertions

fn __nondet<T>() -> T {
unimplemented!()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// @flag --no-memory-splitting --unroll=4
// @expect verified

// cbmc-flags: --unwind 5 --unwinding-assertions

fn fac(n: u64) -> u64 {
match n {
0 => 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// @flag --no-memory-splitting --unroll=10
// @expect error

// cbmc-flags: --unwind 5 --unwinding-assertions

fn fac(n: u64) -> u64 {
match n {
0 => 1,
Expand Down
32 changes: 32 additions & 0 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ impl EarlyProps {
let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);

if config.mode == Mode::RMC {
// If the path to the test contains "fixme" or "ignore", skip it.
let path = testfile.to_str().unwrap();
if path.contains("fixme") || path.contains("ignore") {
props.ignore = true;
}
}

iter_header(testfile, None, rdr, &mut |ln| {
// we should check if any only-<platform> exists and if it exists
// and does not matches the current platform, skip the test
Expand Down Expand Up @@ -277,6 +285,10 @@ pub struct TestProps {
pub error_patterns: Vec<String>,
// Extra flags to pass to the compiler
pub compile_flags: Vec<String>,
// Extra flags to pass to RMC
pub rmc_flags: Vec<String>,
// Extra flags to pass to CBMC
pub cbmc_flags: Vec<String>,
// Extra flags to pass when the compiled code is run (such as --bench)
pub run_flags: Option<String>,
// If present, the name of a file that this test should match when
Expand Down Expand Up @@ -360,6 +372,8 @@ impl TestProps {
TestProps {
error_patterns: vec![],
compile_flags: vec![],
rmc_flags: vec![],
cbmc_flags: vec![],
run_flags: None,
pp_exact: None,
aux_builds: vec![],
Expand Down Expand Up @@ -436,6 +450,14 @@ impl TestProps {
self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));
}

if let Some(flags) = config.parse_rmc_flags(ln) {
self.rmc_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));
}

if let Some(flags) = config.parse_cbmc_flags(ln) {
self.cbmc_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));
}

if let Some(edition) = config.parse_edition(ln) {
self.compile_flags.push(format!("--edition={}", edition));
}
Expand Down Expand Up @@ -729,6 +751,16 @@ impl Config {
self.parse_name_value_directive(line, "compile-flags")
}

/// Parses strings of the form `// rmc-flags: ...` and returns the options listed after `rmc-flags:`
fn parse_rmc_flags(&self, line: &str) -> Option<String> {
self.parse_name_value_directive(line, "rmc-flags")
}

/// Parses strings of the form `// cbmc-flags: ...` and returns the options listed after `cbmc-flags:`
fn parse_cbmc_flags(&self, line: &str) -> Option<String> {
self.parse_name_value_directive(line, "cbmc-flags")
}

fn parse_and_update_revisions(&self, line: &str, existing: &mut Vec<String>) {
if let Some(raw) = self.parse_name_value_directive(line, "revisions") {
let mut duplicates: HashSet<_> = existing.iter().cloned().collect();
Expand Down
22 changes: 17 additions & 5 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ impl<'test> TestCx<'test> {
panic!("revision name must begin with rpass, rfail, or cfail");
}
}
RMC => !self.testpaths.file.to_str().unwrap().contains("fail"),
mode => panic!("unimplemented for mode {:?}", mode),
}
}
Expand Down Expand Up @@ -2382,19 +2383,30 @@ impl<'test> TestCx<'test> {
}
}

/// Runs RMC on the test file specified by `self.testpaths.file`.
/// An error message is printed to stdout if verfication fails.
/// Runs RMC on the test file specified by `self.testpaths.file`. An error
/// message is printed to stdout if verification result is not expected.
fn run_rmc_test(&self) {
// Other modes call self.compile_test(...). However, we cannot call it here for two reasons:
// 1. It calls rustc instead of RMC
// 2. It may pass some options that do not make sense for RMC
// So we create our own command to execute RMC and pass it to self.compose_and_run_compiler(...) directly.
let mut rmc = Command::new("rmc");
// Pass the test path along with RMC and CBMC flags parsed from comments at the top of the test file.
rmc.args(&self.props.rmc_flags)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a short comment about this arguments extension.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Please take a look.

.arg(&self.testpaths.file)
.arg("--")
.args(&self.props.cbmc_flags);
self.add_rmc_dir_to_path(&mut rmc);
rmc.arg(&self.testpaths.file);
let proc_res = self.compose_and_run_compiler(rmc, None);
if !proc_res.status.success() {
self.fatal_proc_rec("verification failed!", &proc_res);
// Print an error if the verification result is not expected.
if self.should_compile_successfully(self.pass_mode()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a short comment here too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

if !proc_res.status.success() {
self.fatal_proc_rec("test failed: expected success, got failure", &proc_res);
}
} else {
if proc_res.status.success() {
self.fatal_proc_rec("test failed: expected failure, got success", &proc_res);
}
}
}

Expand Down