Skip to content

Commit 0bb1325

Browse files
authored
Add a regression test for running verify-std command. (rust-lang#3236)
In rust-lang#3226, we added a new command that allow Kani to verify properties in a custom standard library. In this PR, we create a script test that create a modified version of the standard library and runs Kani against it. I also moved the script based tests to run after the more generic regression jobs. I think the script jobs are a bit harder to debug, they may take longer, and they are usually very specific to a few features. So probably best if we run the more generic tests first.
1 parent dcbf3aa commit 0bb1325

File tree

6 files changed

+110
-1
lines changed

6 files changed

+110
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,5 @@ exclude = [
6868
"tests/script-based-pre",
6969
"tests/script-based-pre/build-cache-bin/target/new_dep",
7070
"tests/script-based-pre/build-cache-dirty/target/new_dep",
71+
"tests/script-based-pre/verify_std_cmd/tmp_dir/target/kani_verify_std",
7172
]

kani-driver/src/call_cargo.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ impl KaniSession {
5757
let mut rustc_args = self.kani_rustc_flags(LibConfig::new_no_core(lib_path));
5858
rustc_args.push(to_rustc_arg(self.kani_compiler_flags()).into());
5959
rustc_args.push(self.reachability_arg().into());
60+
// Ignore global assembly, since `compiler_builtins` has some.
61+
rustc_args.push(to_rustc_arg(vec!["--ignore-global-asm".to_string()]).into());
6062

6163
let mut cargo_args: Vec<OsString> = vec!["build".into()];
6264
cargo_args.append(&mut cargo_config_args());

scripts/kani-regression.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ RUSTFLAGS=--cfg=kani_sysroot cargo test -p kani_macros --features syn/extra-trai
4949

5050
# Declare testing suite information (suite and mode)
5151
TESTS=(
52-
"script-based-pre exec"
5352
"kani kani"
5453
"expected expected"
5554
"ui expected"
@@ -59,6 +58,7 @@ TESTS=(
5958
"smack kani"
6059
"cargo-kani cargo-kani"
6160
"cargo-ui cargo-kani"
61+
"script-based-pre exec"
6262
"coverage coverage-based"
6363
"kani-docs cargo-kani"
6464
"kani-fixme kani-fixme"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright Kani Contributors
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
script: verify_std.sh
4+
expected: verify_std.expected
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[TEST] Run kani verify-std
2+
Checking harness kani::check_success...
3+
VERIFICATION:- SUCCESSFUL
4+
5+
Checking harness kani::check_panic...
6+
VERIFICATION:- SUCCESSFUL (encountered one or more panics as expected)
7+
8+
Checking harness num::verify::check_non_zero...
9+
VERIFICATION:- SUCCESSFUL
10+
11+
Complete - 3 successfully verified harnesses, 0 failures, 3 total.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env bash
2+
# Copyright Kani Contributors
3+
# SPDX-License-Identifier: Apache-2.0 OR MIT
4+
5+
# Test `kani verify-std` subcommand.
6+
# 1. Make a copy of the rust standard library.
7+
# 2. Add a few Kani definitions to it + a few harnesses
8+
# 3. Execute Kani
9+
10+
set +e
11+
12+
TMP_DIR="tmp_dir"
13+
14+
rm -rf ${TMP_DIR}
15+
mkdir ${TMP_DIR}
16+
17+
# Create a custom standard library.
18+
echo "[TEST] Copy standard library from the current toolchain"
19+
SYSROOT=$(rustc --print sysroot)
20+
STD_PATH="${SYSROOT}/lib/rustlib/src/rust/library"
21+
cp -r "${STD_PATH}" "${TMP_DIR}"
22+
23+
# Insert a small harness in one of the standard library modules.
24+
CORE_CODE='
25+
#[cfg(kani)]
26+
#[unstable(feature = "kani", issue = "none")]
27+
pub mod kani {
28+
pub use kani_core::proof;
29+
30+
#[rustc_diagnostic_item = "KaniAnyRaw"]
31+
#[inline(never)]
32+
pub fn any_raw_inner<T>() -> T {
33+
loop {}
34+
}
35+
36+
#[inline(never)]
37+
#[rustc_diagnostic_item = "KaniAssert"]
38+
pub const fn assert(cond: bool, msg: &'\''static str) {
39+
let _ = cond;
40+
let _ = msg;
41+
}
42+
43+
#[kani_core::proof]
44+
#[kani_core::should_panic]
45+
fn check_panic() {
46+
let num: u8 = any_raw_inner();
47+
assert!(num != 0, "Found zero");
48+
}
49+
50+
#[kani_core::proof]
51+
fn check_success() {
52+
let orig: u8 = any_raw_inner();
53+
let mid = orig as i8;
54+
let new = mid as u8;
55+
assert!(orig == new, "Conversion round trip works");
56+
}
57+
}
58+
'
59+
60+
STD_CODE='
61+
#[cfg(kani)]
62+
mod verify {
63+
use core::kani;
64+
#[kani::proof]
65+
fn check_non_zero() {
66+
let orig: u32 = kani::any_raw_inner();
67+
if let Some(val) = core::num::NonZeroU32::new(orig) {
68+
assert!(orig == val.into());
69+
} else {
70+
assert!(orig == 0);
71+
};
72+
}
73+
}
74+
'
75+
76+
echo "[TEST] Modify library"
77+
echo "${CORE_CODE}" >> ${TMP_DIR}/library/core/src/lib.rs
78+
echo "${STD_CODE}" >> ${TMP_DIR}/library/std/src/num.rs
79+
80+
# Note: Prepending with sed doesn't work on MacOs the same way it does in linux.
81+
# sed -i '1s/^/#![cfg_attr(kani, feature(kani))]\n/' ${TMP_DIR}/library/std/src/lib.rs
82+
cp ${TMP_DIR}/library/std/src/lib.rs ${TMP_DIR}/std_lib.rs
83+
echo '#![cfg_attr(kani, feature(kani))]' > ${TMP_DIR}/library/std/src/lib.rs
84+
cat ${TMP_DIR}/std_lib.rs >> ${TMP_DIR}/library/std/src/lib.rs
85+
86+
echo "[TEST] Run kani verify-std"
87+
export RUST_BACKTRACE=1
88+
kani verify-std -Z unstable-options "${TMP_DIR}/library" --target-dir "${TMP_DIR}/target"
89+
90+
# Cleanup
91+
rm -r ${TMP_DIR}

0 commit comments

Comments
 (0)