Skip to content

Commit d394148

Browse files
authored
Add support to compiletest's cargo-kani mode for tests with multi-level directories (rust-lang#1259)
1 parent 7c6ad14 commit d394148

File tree

11 files changed

+133
-13
lines changed

11 files changed

+133
-13
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright Kani Contributors
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
[workspace]
4+
5+
members = [
6+
"crate1",
7+
"crate2",
8+
"crate2/nested_crate",
9+
]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright Kani Contributors
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
[package]
4+
name = "crate1"
5+
version = "0.1.0"
6+
edition = "2021"
7+
8+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
9+
10+
[dependencies]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Status: SUCCESS\
2+
Description: "assertion failed: v.len() == 3"
3+
VERIFICATION:- SUCCESSFUL
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
#[kani::proof]
5+
fn a_check() {
6+
let v = vec![1, 2, 3];
7+
assert_eq!(v.len(), 3);
8+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright Kani Contributors
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
[package]
4+
name = "crate2"
5+
version = "0.1.0"
6+
edition = "2021"
7+
8+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
9+
10+
[dependencies]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Status: SUCCESS\
2+
Description: "assertion failed: result == 4"
3+
VERIFICATION:- SUCCESSFUL
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright Kani Contributors
2+
# SPDX-License-Identifier: Apache-2.0 OR MIT
3+
[package]
4+
name = "nested_crate"
5+
version = "0.1.0"
6+
edition = "2021"
7+
8+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
9+
10+
[dependencies]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
#[kani::proof]
5+
fn yet_another_check() {
6+
let x: u16 = kani::any();
7+
let y = x;
8+
assert_eq!(y - x, 0);
9+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Status: SUCCESS\
2+
Description: "assertion failed: y - x == 0"
3+
4+
VERIFICATION:- SUCCESSFUL
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
#[kani::proof]
5+
fn another_check() {
6+
let result = 2 + 2;
7+
assert_eq!(result, 4);
8+
}

tools/compiletest/src/main.rs

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,21 @@ fn collect_tests_from_dir(
372372
relative_dir_path: &Path,
373373
inputs: &Stamp,
374374
tests: &mut Vec<test::TestDescAndFn>,
375+
) -> io::Result<()> {
376+
match config.mode {
377+
Mode::CargoKani => {
378+
collect_expected_tests_from_dir(config, dir, relative_dir_path, inputs, tests)
379+
}
380+
_ => collect_rs_tests_from_dir(config, dir, relative_dir_path, inputs, tests),
381+
}
382+
}
383+
384+
fn collect_expected_tests_from_dir(
385+
config: &Config,
386+
dir: &Path,
387+
relative_dir_path: &Path,
388+
inputs: &Stamp,
389+
tests: &mut Vec<test::TestDescAndFn>,
375390
) -> io::Result<()> {
376391
// If we find a test foo/bar.rs, we have to build the
377392
// output directory `$build/foo` so we can write
@@ -387,20 +402,51 @@ fn collect_tests_from_dir(
387402
// output directory corresponding to each to avoid race conditions during
388403
// the testing phase. We immediately return after adding the tests to avoid
389404
// treating `*.rs` files as tests.
390-
if config.mode == Mode::CargoKani && dir.join("Cargo.toml").exists() {
391-
for file in fs::read_dir(dir)? {
392-
let file_path = file?.path();
393-
if file_path.to_str().unwrap().ends_with(".expected")
394-
|| "expected" == file_path.file_name().unwrap()
395-
{
396-
fs::create_dir_all(&build_dir.join(file_path.file_stem().unwrap())).unwrap();
397-
let paths =
398-
TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
399-
tests.extend(make_test(config, &paths, inputs));
400-
}
405+
assert_eq!(config.mode, Mode::CargoKani);
406+
407+
let has_cargo_toml = dir.join("Cargo.toml").exists();
408+
for file in fs::read_dir(dir)? {
409+
let file = file?;
410+
let file_path = file.path();
411+
if has_cargo_toml
412+
&& (file_path.to_str().unwrap().ends_with(".expected")
413+
|| "expected" == file_path.file_name().unwrap())
414+
{
415+
fs::create_dir_all(&build_dir.join(file_path.file_stem().unwrap())).unwrap();
416+
let paths =
417+
TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
418+
tests.extend(make_test(config, &paths, inputs));
419+
} else if file_path.is_dir() {
420+
// recurse on subdirectory
421+
let relative_file_path = relative_dir_path.join(file.file_name());
422+
debug!("found directory: {:?}", file_path.display());
423+
collect_expected_tests_from_dir(
424+
config,
425+
&file_path,
426+
&relative_file_path,
427+
inputs,
428+
tests,
429+
)?;
401430
}
402-
return Ok(());
403431
}
432+
Ok(())
433+
}
434+
435+
fn collect_rs_tests_from_dir(
436+
config: &Config,
437+
dir: &Path,
438+
relative_dir_path: &Path,
439+
inputs: &Stamp,
440+
tests: &mut Vec<test::TestDescAndFn>,
441+
) -> io::Result<()> {
442+
// If we find a test foo/bar.rs, we have to build the
443+
// output directory `$build/foo` so we can write
444+
// `$build/foo/bar` into it. We do this *now* in this
445+
// sequential loop because otherwise, if we do it in the
446+
// tests themselves, they race for the privilege of
447+
// creating the directories and sometimes fail randomly.
448+
let build_dir = output_relative_path(config, relative_dir_path);
449+
fs::create_dir_all(&build_dir).unwrap();
404450

405451
// Add each `.rs` file as a test, and recurse further on any
406452
// subdirectories we find, except for `aux` directories.
@@ -417,7 +463,7 @@ fn collect_tests_from_dir(
417463
let relative_file_path = relative_dir_path.join(file.file_name());
418464
if &file_name != "auxiliary" {
419465
debug!("found directory: {:?}", file_path.display());
420-
collect_tests_from_dir(config, &file_path, &relative_file_path, inputs, tests)?;
466+
collect_rs_tests_from_dir(config, &file_path, &relative_file_path, inputs, tests)?;
421467
}
422468
} else {
423469
debug!("found other file/directory: {:?}", file_path.display());

0 commit comments

Comments
 (0)