Skip to content

Commit 949f4a5

Browse files
authored
Merge pull request #49 from os-checker/kani-list
Feat: define KaniList for parsing the output of `kani list`
2 parents 967230e + 81bcc8a commit 949f4a5

14 files changed

+280
-20
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
/target
22

3+
# kani list
4+
kani-list.json
5+
36
# ignore kani folder for grep or files findings
47
# kani

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2024"
77
clap = { version = "4.5.35", features = ["derive"] }
88
serde = { version = "1", features = ["derive"] }
99
serde_json = { version = "1", features = ["preserve_order"] }
10-
indexmap = "2.9.0"
10+
indexmap = { version = "2.9.0", features = ["serde"] }
1111

1212
# error handling
1313
eyre = "0.6"

src/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use indexmap::{IndexMap, IndexSet};
12
use serde::{Deserialize, Serialize};
23

34
/// A Rust funtion with its file source, attributes, and raw function content.
@@ -83,3 +84,30 @@ pub fn kani_path() -> String {
8384
assert!(std::fs::exists(&path).unwrap());
8485
path
8586
}
87+
88+
/// Output of `kani list` command.
89+
#[derive(Debug, Serialize, Deserialize, Clone)]
90+
#[serde(rename_all = "kebab-case")]
91+
pub struct KaniList {
92+
pub kani_version: String,
93+
pub file_version: String,
94+
pub standard_harnesses: IndexMap<String, IndexSet<String>>,
95+
pub contract_harnesses: IndexMap<String, IndexSet<String>>,
96+
pub contracts: IndexSet<ContractedFunction>,
97+
pub totals: Total,
98+
}
99+
100+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
101+
pub struct ContractedFunction {
102+
pub function: String,
103+
pub file: String,
104+
pub harnesses: Vec<String>,
105+
}
106+
107+
#[derive(Debug, Serialize, Deserialize, Clone)]
108+
#[serde(rename_all = "kebab-case")]
109+
pub struct Total {
110+
pub standard_harnesses: usize,
111+
pub contract_harnesses: usize,
112+
pub functions_under_contract: usize,
113+
}

tests/kani_list.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use distributed_verification::KaniList;
2+
use std::process::Command;
3+
4+
mod utils;
5+
use utils::*;
6+
7+
#[test]
8+
fn validate_kani_list_json() -> Result<()> {
9+
let proofs = get_proofs("tests/proofs")?;
10+
11+
for path in &proofs {
12+
let kani_list = get_kani_list(path.to_str().unwrap());
13+
let file_stem = file_stem(path);
14+
let list_path = format!("kani_list/{file_stem}.txt");
15+
dbg!(&list_path);
16+
expect_file![list_path].assert_debug_eq(&kani_list);
17+
}
18+
19+
Ok(())
20+
}
21+
22+
fn get_kani_list(file: &str) -> KaniList {
23+
// kani list -Zlist -Zfunction-contracts --format=json file.rs
24+
let args = ["list", "-Zlist", "-Zfunction-contracts", "--format=json", file];
25+
let output = Command::new("kani").args(args).output().unwrap();
26+
assert!(
27+
output.status.success(),
28+
"Failed to run `kani list -Zlist -Zfunction-contracts --format=json {file}`:\n{}",
29+
std::str::from_utf8(&output.stderr).unwrap()
30+
);
31+
32+
// read kani-list.json
33+
let file_json = std::fs::File::open("kani-list.json").unwrap();
34+
serde_json::from_reader(file_json).unwrap()
35+
}

tests/kani_list/ad_hoc.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
KaniList {
2+
kani_version: "0.60.0",
3+
file_version: "0.1",
4+
standard_harnesses: {
5+
"tests/proofs/ad_hoc.rs": {
6+
"adhoc::callee_defined_in_proof",
7+
"adhoc::closure_in_proof",
8+
"adhoc::proof_in_fn_item::proof",
9+
},
10+
},
11+
contract_harnesses: {},
12+
contracts: {},
13+
totals: Total {
14+
standard_harnesses: 3,
15+
contract_harnesses: 0,
16+
functions_under_contract: 0,
17+
},
18+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
KaniList {
2+
kani_version: "0.60.0",
3+
file_version: "0.1",
4+
standard_harnesses: {},
5+
contract_harnesses: {
6+
"tests/proofs/gen_contracts_by_macros.rs": {
7+
"verify::proof1",
8+
"verify::proof2",
9+
"verify::proof3",
10+
},
11+
},
12+
contracts: {
13+
ContractedFunction {
14+
function: "verify::contract1",
15+
file: "tests/proofs/gen_contracts_by_macros.rs",
16+
harnesses: [
17+
"verify::proof1",
18+
],
19+
},
20+
ContractedFunction {
21+
function: "verify::contract2",
22+
file: "tests/proofs/gen_contracts_by_macros.rs",
23+
harnesses: [
24+
"verify::proof2",
25+
],
26+
},
27+
ContractedFunction {
28+
function: "verify::contract3",
29+
file: "tests/proofs/gen_contracts_by_macros.rs",
30+
harnesses: [
31+
"verify::proof3",
32+
],
33+
},
34+
},
35+
totals: Total {
36+
standard_harnesses: 0,
37+
contract_harnesses: 3,
38+
functions_under_contract: 3,
39+
},
40+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
KaniList {
2+
kani_version: "0.60.0",
3+
file_version: "0.1",
4+
standard_harnesses: {
5+
"tests/proofs/gen_proofs_by_macros.rs": {
6+
"verify::proof1",
7+
"verify::proof2",
8+
"verify::proof3",
9+
},
10+
},
11+
contract_harnesses: {},
12+
contracts: {},
13+
totals: Total {
14+
standard_harnesses: 3,
15+
contract_harnesses: 0,
16+
functions_under_contract: 0,
17+
},
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
KaniList {
2+
kani_version: "0.60.0",
3+
file_version: "0.1",
4+
standard_harnesses: {
5+
"tests/proofs/gen_proofs_by_nested_macros.rs": {
6+
"verify::proof1",
7+
"verify::proof2",
8+
"verify::proof3",
9+
},
10+
},
11+
contract_harnesses: {},
12+
contracts: {},
13+
totals: Total {
14+
standard_harnesses: 3,
15+
contract_harnesses: 0,
16+
functions_under_contract: 0,
17+
},
18+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
KaniList {
2+
kani_version: "0.60.0",
3+
file_version: "0.1",
4+
standard_harnesses: {},
5+
contract_harnesses: {
6+
"tests/proofs/proofs_for_contract.rs": {
7+
"verify::single_contract",
8+
"verify::single_contract_requires",
9+
"verify::single_with_contract_ensures",
10+
"verify::two_contracts_requires_and_ensures",
11+
},
12+
},
13+
contracts: {
14+
ContractedFunction {
15+
function: "verify::contract",
16+
file: "tests/proofs/proofs_for_contract.rs",
17+
harnesses: [
18+
"verify::single_contract",
19+
],
20+
},
21+
ContractedFunction {
22+
function: "verify::contract_ensures",
23+
file: "tests/proofs/proofs_for_contract.rs",
24+
harnesses: [
25+
"verify::single_with_contract_ensures",
26+
],
27+
},
28+
ContractedFunction {
29+
function: "verify::contract_requires",
30+
file: "tests/proofs/proofs_for_contract.rs",
31+
harnesses: [
32+
"verify::single_contract_requires",
33+
"verify::two_contracts_requires_and_ensures",
34+
],
35+
},
36+
},
37+
totals: Total {
38+
standard_harnesses: 0,
39+
contract_harnesses: 4,
40+
functions_under_contract: 3,
41+
},
42+
}

0 commit comments

Comments
 (0)