Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kani-cov: A coverage tool for Kani #3121

Merged
merged 78 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
c487f2a
`kanicov`: A tool to visualize coverage in Kani
adpaco-aws Apr 3, 2024
eddb363
Rename and more
adpaco-aws Apr 9, 2024
935dace
Merge branch 'main' into kanicov-tool
adpaco-aws Aug 21, 2024
13c26fd
Scaffold for `kani-cov`
adpaco-aws Aug 22, 2024
bee8f2d
Parse and combine raw results
adpaco-aws Aug 22, 2024
e0b7a10
Merge branch 'main' into kanicov-tool
adpaco-aws Aug 28, 2024
0aa25b9
Add missing copyright notices
adpaco-aws Aug 28, 2024
debeef4
Remove `atty` dependency
adpaco-aws Aug 29, 2024
9e9575a
Add license to Cargo.toml
adpaco-aws Aug 29, 2024
dd53e38
Move unused code to report
adpaco-aws Aug 29, 2024
ad632f3
Save combined results through merge
adpaco-aws Aug 29, 2024
a659c1a
Start summary command
adpaco-aws Aug 29, 2024
76351fd
Some format fixes
adpaco-aws Aug 29, 2024
304cfd2
Fixes for `clippy`
adpaco-aws Aug 29, 2024
c69f465
Add description to Cargo.toml
adpaco-aws Aug 29, 2024
d0bb478
Parse function info with tree-sitter
adpaco-aws Aug 30, 2024
5512d28
Use file-function pairs to combine results
adpaco-aws Aug 31, 2024
0e1dcc0
Change combined results again
adpaco-aws Aug 31, 2024
fabdf44
Produce markdown table with `summary`
adpaco-aws Sep 13, 2024
855d0a6
Sketch Json format for summary
adpaco-aws Sep 13, 2024
0df18b9
Refator some code so it's shared with `report`
adpaco-aws Sep 13, 2024
50bb553
Init. version for terminal reports
adpaco-aws Sep 16, 2024
5b4d717
Simplify processing for markers
adpaco-aws Sep 17, 2024
e1d0160
Remove some formatting code that's not needed anymore
adpaco-aws Sep 17, 2024
6d47c0b
Remove leftover debugging info
adpaco-aws Sep 17, 2024
ae48e21
Complete terminal highlight algorithm
adpaco-aws Sep 19, 2024
8c79baf
Change `coverage` mode to get `kani-cov` reports
adpaco-aws Sep 19, 2024
39f5ac2
Bless expected files
adpaco-aws Sep 19, 2024
778816a
Complete blessing for `coverage` tests
adpaco-aws Sep 19, 2024
b33fd5c
Merge branch 'main' into kanicov-tool
adpaco-aws Sep 20, 2024
06b97f0
Reformat
adpaco-aws Sep 20, 2024
781ba58
Clippy fixes
adpaco-aws Sep 20, 2024
7d7ef6c
Clean up: unused imports and commented out code
adpaco-aws Sep 20, 2024
a997656
Merge branch 'main' into kanicov-tool
adpaco-aws Sep 20, 2024
5cd0687
Report format
adpaco-aws Sep 20, 2024
4694294
Introduce format for reports
adpaco-aws Sep 20, 2024
21f2bd8
Add documentation for several functions
adpaco-aws Sep 20, 2024
923e606
Most clippy fixes
adpaco-aws Sep 20, 2024
812231e
More documentation
adpaco-aws Sep 20, 2024
745a55f
Documentation for main methods
adpaco-aws Sep 20, 2024
a0df867
Fix collapsible match
adpaco-aws Sep 23, 2024
4cc3561
Check if building `kani-cov` works
adpaco-aws Sep 23, 2024
9e28668
Reformat
adpaco-aws Sep 23, 2024
9c02d9f
Bless tests with known issues
adpaco-aws Sep 23, 2024
b2926e3
Complete documentation
adpaco-aws Sep 23, 2024
d20fa28
Reformat
adpaco-aws Sep 23, 2024
94bb87a
Merge branch 'main' into kanicov-tool
adpaco-aws Sep 23, 2024
eba08bb
Merge branch 'main' into kanicov-tool
adpaco-aws Sep 24, 2024
16a23c9
Reformat
adpaco-aws Sep 24, 2024
64ed9ea
Improvements and docs for `compiletest` code
adpaco-aws Oct 1, 2024
da47a24
Add examples for `kani-cov` subcommands
adpaco-aws Oct 1, 2024
a9b7dbf
Document `SummaryFormat`
adpaco-aws Oct 1, 2024
9b8ac3f
Address two minor comments
adpaco-aws Oct 1, 2024
524dc91
Replace `BTreeMap` with `HashMap`
adpaco-aws Oct 1, 2024
c4461be
Include file in coverage region display
adpaco-aws Oct 1, 2024
c7e2661
Auto-format
adpaco-aws Oct 1, 2024
66a5396
Improvements for tree-sitter code
adpaco-aws Oct 1, 2024
4b7e294
Simplify code to retrieve cov results
adpaco-aws Oct 1, 2024
91ed88e
Redo file-function pair collection
adpaco-aws Oct 1, 2024
dabf0c9
Undo change in command
adpaco-aws Oct 1, 2024
28e392e
Merge branch 'main' into kanicov-tool
adpaco-aws Oct 1, 2024
d29c3f3
Update `Cargo.lock` file
adpaco-aws Oct 1, 2024
7741fb1
Use aliases for coverage types
adpaco-aws Oct 4, 2024
c7443f5
Use `usize` instead of `u32`
adpaco-aws Oct 4, 2024
babdc85
Document `CovResult`
adpaco-aws Oct 4, 2024
0137b03
Format
adpaco-aws Oct 4, 2024
d0d1cf4
Fix bug and use partition
adpaco-aws Oct 4, 2024
094ad75
Update tests after fix
adpaco-aws Oct 4, 2024
a6abae5
Merge branch 'main' into kanicov-tool
adpaco-aws Oct 4, 2024
8ea744d
more `clippy` fixes
adpaco-aws Oct 4, 2024
ffa738a
Reformat code
adpaco-aws Oct 4, 2024
3f9b01b
Do not filter out results with out-of-bound regions
adpaco-aws Oct 7, 2024
4f0b913
Auto-fmt
adpaco-aws Oct 7, 2024
421cde4
Update tests
adpaco-aws Oct 7, 2024
c7606f3
More typenames and use across all of `kani-cov`
adpaco-aws Oct 7, 2024
cb123e5
Merge branch 'main' into kanicov-tool
adpaco-aws Oct 7, 2024
7311f49
clippy fixes
adpaco-aws Oct 7, 2024
42314e8
Merge branch 'main' into kanicov-tool
adpaco-aws Oct 9, 2024
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
42 changes: 42 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,20 @@ dependencies = [
"tracing-tree 0.4.0",
]

[[package]]
name = "kani-cov"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"console",
"serde",
"serde_derive",
"serde_json",
"tree-sitter",
"tree-sitter-rust",
]

[[package]]
name = "kani-driver"
version = "0.56.0"
Expand Down Expand Up @@ -1811,6 +1825,34 @@ dependencies = [
"tracing-subscriber",
]

[[package]]
name = "tree-sitter"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20f4cd3642c47a85052a887d86704f4eac272969f61b686bdd3f772122aabaff"
dependencies = [
"cc",
"regex",
"regex-syntax 0.8.5",
"tree-sitter-language",
]

[[package]]
name = "tree-sitter-language"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2545046bd1473dac6c626659cc2567c6c0ff302fc8b84a56c4243378276f7f57"

[[package]]
name = "tree-sitter-rust"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "277690f420bf90741dea984f3da038ace46c4fe6047cba57a66822226cde1c93"
dependencies = [
"cc",
"tree-sitter",
]

[[package]]
name = "typed-arena"
version = "2.0.2"
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ members = [
"library/std",
"tools/compiletest",
"tools/build-kani",
"tools/kani-cov",
"tools/scanner",
"kani-driver",
"kani-compiler",
Expand Down
3 changes: 3 additions & 0 deletions scripts/kani-regression.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ echo "--- Compiletest configuration"
cargo run -p compiletest --quiet -- --suite kani --mode cargo-kani --dry-run --verbose
echo "-----------------------------"

# Build `kani-cov`
cargo build -p kani-cov

# Extract testing suite information and run compiletest
for testp in "${TESTS[@]}"; do
testl=($testp)
Expand Down
34 changes: 21 additions & 13 deletions tests/coverage/abort/expected
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
Source-based code coverage results:

main.rs (main)\
* 9:1 - 9:11 COVERED\
* 10:9 - 10:10 COVERED\
* 10:14 - 10:18 COVERED\
* 13:13 - 13:29 COVERED\
* 14:10 - 15:18 COVERED\
* 17:13 - 17:29 UNCOVERED\
* 18:10 - 18:11 COVERED\
* 20:5 - 20:12 UNCOVERED\
* 20:20 - 20:41 UNCOVERED\
* 21:1 - 21:2 UNCOVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | \
4| | //! Test that the abort() function is respected and nothing beyond it will execute.\
5| | \
6| | use std::process;\
7| | \
8| | #[kani::proof]\
9| 1| fn main() {\
10| 1| for i in 0..4 {\
11| | if i == 1 {\
12| | // This comes first and it should be reachable.\
13| 1| process::abort();\
14| 1| }\
15| 1| if i == 2 {\
16| | // This should never happen.\
17| 0| ```process::exit(1)''';\
18| 1| } \
19| | }\
20| 0| ```assert!'''(false, ```"This is unreachable"''');\
21| | }\
27 changes: 18 additions & 9 deletions tests/coverage/assert/expected
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
Source-based code coverage results:

test.rs (foo)
* 5:1 - 7:13 COVERED\
* 9:9 - 10:17 COVERED\
* 10:18 - 13:10 UNCOVERED\
* 13:10 - 13:11 UNCOVERED\
* 14:12 - 17:6 COVERED\
* 18:1 - 18:2 COVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | \
4| | #[kani::proof]\
5| 1| fn foo() {\
6| 1| let x: i32 = kani::any();\
7| 1| if x > 5 {\
8| | // fails\
9| 1| assert!(x < 4);\
10| 1| if x < 3 ```{'''\
11| 0| ``` // unreachable'''\
12| 0| ``` assert!(x == 2);'''\
13| 0| ``` }'''``` '''\
14| 1| } else {\
15| 1| // passes\
16| 1| assert!(x <= 5);\
17| 1| }\
18| | }\
19 changes: 11 additions & 8 deletions tests/coverage/assert_eq/expected
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
Source-based code coverage results:

test.rs (main)\
* 5:1 - 6:29 COVERED\
* 7:25 - 7:27 COVERED\
* 7:37 - 7:39 COVERED\
* 8:15 - 10:6 UNCOVERED\
* 10:6 - 10:7 COVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | \
4| | #[kani::proof]\
5| 1| fn main() {\
6| 1| let x: i32 = kani::any();\
7| 1| let y = if x > 10 { 15 } else { 33 };\
8| 0| if y > 50 ```{'''\
9| 0| ``` assert_eq!(y, 55);'''\
10| 1| ``` }'''\
11| | }\
23 changes: 14 additions & 9 deletions tests/coverage/assert_ne/expected
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
Source-based code coverage results:

test.rs (main)\
* 5:1 - 7:13 COVERED\
* 8:13 - 10:18 COVERED\
* 10:19 - 12:10 UNCOVERED\
* 12:10 - 12:11 COVERED\
* 13:6 - 13:7 COVERED\
* 14:1 - 14:2 COVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | \
4| | #[kani::proof]\
5| 1| fn main() {\
6| 1| let x: u32 = kani::any();\
7| 1| if x > 0 {\
8| 1| let y = x / 2;\
9| 1| // y is strictly less than x\
10| 1| if y == x ```{'''\
11| 0| ``` assert_ne!(y, 1);'''\
12| 1| ``` }'''\
13| 1| }\
14| | }\
32 changes: 19 additions & 13 deletions tests/coverage/break/expected
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
Source-based code coverage results:

main.rs (find_positive)\
* 4:1 - 4:47 COVERED\
* 5:10 - 5:13 COVERED\
* 5:17 - 5:21 COVERED\
* 7:20 - 7:29 COVERED\
* 8:10 - 8:11 COVERED\
* 11:5 - 11:9 UNCOVERED\
* 12:1 - 12:2 COVERED

main.rs (main)\
* 15:1 - 19:2 COVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | \
4| 1| fn find_positive(nums: &[i32]) -> Option<i32> {\
5| 1| for &num in nums {\
6| | if num > 0 {\
7| 1| return Some(num);\
8| 1| } \
9| | }\
10| | // `None` is unreachable because there is at least one positive number.\
11| 0| ```None'''\
12| | }\
13| | \
14| | #[kani::proof]\
15| 1| fn main() {\
16| 1| let numbers = [-3, -1, 0, 2, 4];\
17| 1| let result = find_positive(&numbers);\
18| 1| assert_eq!(result, Some(2));\
19| | }\
27 changes: 16 additions & 11 deletions tests/coverage/compare/expected
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
Source-based code coverage results:

main.rs (compare)\
* 4:1 - 6:14 COVERED\
* 6:17 - 6:18 COVERED\
* 6:28 - 6:29 UNCOVERED

main.rs (main)\
* 10:1 - 13:14 COVERED\
* 13:15 - 15:6 COVERED\
* 15:6 - 15:7 COVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | \
4| 1| fn compare(x: u16, y: u16) -> u16 {\
5| 1| // The case where `x < y` isn't possible so its region is `UNCOVERED`\
6| 1| if x >= y { 1 } else { ```0''' }\
7| | }\
8| | \
9| | #[kani::proof]\
10| 1| fn main() {\
11| 1| let x: u16 = kani::any();\
12| 1| let y: u16 = kani::any();\
13| 1| if x >= y {\
14| 1| compare(x, y);\
15| 1| } \
16| | }\
23 changes: 14 additions & 9 deletions tests/coverage/contradiction/expected
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
Source-based code coverage results:

main.rs (contradiction)\
* 4:1 - 7:13 COVERED\
* 8:12 - 8:17 COVERED\
* 8:18 - 10:10 UNCOVERED\
* 10:10 - 10:11 COVERED\
* 11:12 - 13:6 COVERED\
* 14:1 - 14:2 COVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | #[kani::proof]\
4| 1| fn contradiction() {\
5| 1| let x: u8 = kani::any();\
6| 1| let mut y: u8 = 0;\
7| 1| if x > 5 {\
8| 1| if x < 2 ```{'''\
9| 0| ``` y = x;'''\
10| 1| ``` }'''\
11| 1| } else {\
12| 1| assert!(x < 10);\
13| 1| }\
14| | }\
25 changes: 15 additions & 10 deletions tests/coverage/debug-assert/expected
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
Source-based code coverage results:

main.rs (main)\
* 10:1 - 10:11 COVERED\
* 11:9 - 11:10 COVERED\
* 11:14 - 11:18 COVERED\
* 12:30 - 12:71 UNCOVERED\
* 13:9 - 13:23 UNCOVERED\
* 13:25 - 13:53 UNCOVERED\
* 15:1 - 15:2 UNCOVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | \
4| | //! This test checks that the regions after the `debug_assert` macro are\
5| | //! `UNCOVERED`. In fact, for this example, the region associated to `"This\
6| | //! should fail and stop the execution"` is also `UNCOVERED` because the macro\
7| | //! calls span two regions each.\
8| | \
9| | #[kani::proof]\
10| 1| fn main() {\
11| 1| for i in 0..4 {\
12| 0| debug_assert!(i > 0, ```"This should fail and stop the execution"''');\
13| 0| ```assert!(i == 0''', ```"This should be unreachable"''');\
14| | }\
15| | }\
20 changes: 11 additions & 9 deletions tests/coverage/div-zero/expected
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
Source-based code coverage results:

test.rs (div)\
* 4:1 - 5:14 COVERED\
* 5:17 - 5:22 COVERED\
* 5:32 - 5:33 UNCOVERED

test.rs (main)\
* 9:1 - 11:2 COVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | \
4| 1| fn div(x: u16, y: u16) -> u16 {\
5| 1| if y != 0 { x / y } else { ```0''' }\
6| | }\
7| | \
8| | #[kani::proof]\
9| 1| fn main() {\
10| 1| div(11, 3);\
11| | }\
31 changes: 19 additions & 12 deletions tests/coverage/early-return/expected
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
Source-based code coverage results:

main.rs (find_index)\
* 4:1 - 4:59 COVERED\
* 5:10 - 5:21 COVERED\
* 7:20 - 7:31 COVERED\
* 8:10 - 8:11 COVERED\
* 10:5 - 10:9 UNCOVERED\
* 11:1 - 11:2 COVERED

main.rs (main)\
* 14:1 - 19:2 COVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | \
4| 1| fn find_index(nums: &[i32], target: i32) -> Option<usize> {\
5| 1| for (index, &num) in nums.iter().enumerate() {\
6| | if num == target {\
7| 1| return Some(index);\
8| 1| } \
9| | }\
10| 0| ```None'''\
11| | }\
12| | \
13| | #[kani::proof]\
14| 1| fn main() {\
15| 1| let numbers = [10, 20, 30, 40, 50];\
16| 1| let target = 30;\
17| 1| let result = find_index(&numbers, target);\
18| 1| assert_eq!(result, Some(2));\
19| | }\
37 changes: 26 additions & 11 deletions tests/coverage/if-statement-multi/expected
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
Source-based code coverage results:

test.rs (main)\
* 21:1 - 26:2 COVERED

test.rs (test_cov)\
* 16:1 - 17:15 COVERED\
* 17:19 - 17:28 UNCOVERED\
* 17:31 - 17:35 COVERED\
* 17:45 - 17:50 UNCOVERED\
* 18:1 - 18:2 COVERED
1| | // Copyright Kani Contributors\
2| | // SPDX-License-Identifier: Apache-2.0 OR MIT\
3| | // kani-flags: --coverage -Zsource-coverage\
4| | \
5| | //! Checks that we are covering all regions except\
6| | //! * the `val == 42` condition\
7| | //! * the `false` branch\
8| | //!\
9| | //! No coverage information is shown for `_other_function` because it's sliced\
10| | //! off: <https://github.com/model-checking/kani/issues/3445>\
11| | \
12| 0| ```fn _other_function() {'''\
13| 0| ``` println!("Hello, world!");'''\
14| 0| ```}'''\
15| | \
16| 1| fn test_cov(val: u32) -> bool {\
17| 1| if val < 3 || ```val == 42''' { true } else { ```false''' }\
18| | }\
19| | \
20| | #[cfg_attr(kani, kani::proof)]\
21| 1| fn main() {\
22| 1| let test1 = test_cov(1);\
23| 1| let test2 = test_cov(2);\
24| 1| assert!(test1);\
25| 1| assert!(test2);\
26| | }\
Loading
Loading