forked from verus-lang/verus
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcargo.rs
More file actions
168 lines (145 loc) · 5.75 KB
/
cargo.rs
File metadata and controls
168 lines (145 loc) · 5.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#![feature(rustc_private)]
#[macro_use]
mod common;
use std::fs;
use common::*;
use rust_verify_test_macros::cargo_examples;
use std::path::PathBuf;
use tempfile::tempdir;
use toml::{Table, Value};
fn compute_test_dir(dir: &str) -> std::path::PathBuf {
let current_exe = std::env::current_exe().unwrap();
current_exe.parent().unwrap().parent().unwrap().parent().unwrap().parent().unwrap().join(dir)
}
fn parse_toml_file(path: &std::path::Path) -> Table {
let toml_content = fs::read_to_string(path)
.unwrap_or_else(|_| panic!("cannot open Cargo.toml file: {}", path.display()));
toml_content.parse::<Table>().unwrap()
}
fn find_verus_config<'a>(table: &'a Table, entry: &str) -> Option<&'a str> {
if let Some(package) = table.get("package") {
if let Some(meta) = package.get("metadata") {
if let Some(verus) = meta.get("verus") {
if let Some(value) = verus.get(entry) {
if value.is_bool() {
return Some(if value.as_bool().unwrap() { "true" } else { "false" });
} else if value.is_str() {
return Some(value.as_str().unwrap());
} else {
return None;
}
}
}
}
}
None
}
fn run_cargo_verus_for_dir(dir: &str) {
let test_dir = compute_test_dir(dir);
// Check for additional Verus-related metadata
let toml_path = test_dir.join("Cargo.toml");
let toml_table = parse_toml_file(&toml_path);
// See if this test is currently being ignored
let ignore = find_verus_config(&toml_table, "test_ignore").map_or(false, |v| v == "true");
if ignore {
eprintln!("Ignoring cargo verus test in {}", dir);
return;
}
// Check for extra verus args
let mut extra_verus_args = vec![];
if let Some(args) = find_verus_config(&toml_table, "test_args") {
extra_verus_args.extend(args.split(" "));
}
// Don't reuse any artifacts from previous runs
let args = vec!["clean"];
let run = run_cargo(&args, &test_dir.as_path());
assert!(run.status.success());
let mut args = vec!["verify"];
args.push("--");
args.extend(&extra_verus_args);
let run = run_cargo_verus(&args, &test_dir.as_path());
assert!(run.status.success());
let mut args = vec!["build"];
args.push("--");
args.extend(&extra_verus_args);
let run = run_cargo_verus(&args, &test_dir.as_path());
assert!(run.status.success());
}
fn run_vanilla_cargo_for_dir(dir: &str) {
let test_dir = compute_test_dir(dir);
// Check for additional Verus-related metadata
let toml_path = test_dir.join("Cargo.toml");
let toml_table = parse_toml_file(&toml_path);
// See if this test is currently being ignored
let ignore = find_verus_config(&toml_table, "test_ignore").map_or(false, |v| v == "true");
if ignore {
eprintln!("Ignoring cargo verus test in {}", dir);
return;
}
// Don't reuse any artifacts from previous runs
let args = vec!["clean"];
let run = run_cargo(&args, &test_dir.as_path());
assert!(run.status.success());
let args = vec!["check"];
let run = run_cargo(&args, &test_dir.as_path());
assert!(run.status.success());
let args = vec!["build"];
let run = run_cargo(&args, &test_dir.as_path());
assert!(run.status.success());
}
// If vstd is modified as part of a change, the tests should use the local
// version rather than what's on crates.io. This is not a great solution to
// handle this though..
fn adjust_version(mut project_path: PathBuf) {
project_path.push("Cargo.toml");
let mut toml_table = parse_toml_file(&project_path);
let Some(Value::Table(dependencies)) = toml_table.get_mut("dependencies") else {
panic!("no dependencies");
};
let Some(version) = dependencies.get_mut("vstd") else {
panic!("no vstd version");
};
let mut cur_file = std::env::current_dir().expect("current dir");
cur_file.pop();
cur_file.push("vstd");
let mut new_vstd_entry = Table::new();
new_vstd_entry.insert(
"path".to_string(),
Value::String(cur_file.to_str().expect("valid unicode path").to_owned()),
);
*version = Value::Table(new_vstd_entry);
std::fs::write(project_path, toml_table.to_string()).expect("write toml");
}
#[test]
fn cargo_new_verifies() {
// Run cargo verus new in temp_dir
let temp_dir = tempdir().expect("Failed to create temporary directory");
let args = vec!["new", "--bin", "test_project"];
let temp_dir_path = temp_dir.path().to_owned();
// replace above line by this to debug this test:
// let temp_dir_path = temp_dir.keep();
let run = run_cargo_verus(&args, &temp_dir_path);
let mut project_path = temp_dir_path.clone();
project_path.push("test_project");
adjust_version(project_path);
assert!(run.status.success());
let args = vec!["verify"];
let run = run_cargo_verus(&args, temp_dir_path.join("test_project").as_path());
assert!(run.status.success());
}
#[test]
fn cargo_new_builds() {
// Run cargo verus new in temp_dir
let temp_dir = tempdir().expect("Failed to create temporary directory");
let args = vec!["new", "--bin", "test_project"];
let run = run_cargo_verus(&args, temp_dir.path());
adjust_version(temp_dir.path().join("test_project"));
assert!(run.status.success());
let args = vec!["build"];
let run = run_cargo_verus(&args, temp_dir.path().join("test_project").as_path());
assert!(run.status.success());
}
// Tests that run `cargo verus {verify, build}` on each crate in the cargo-tests/verified directory
cargo_examples!(true);
// Tests that run `cargo {check, build}` on each crate in the cargo-tests/unverified directory
cargo_examples!(false);