forked from verus-lang/verus
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexamples.rs
More file actions
162 lines (146 loc) · 5.83 KB
/
Copy pathexamples.rs
File metadata and controls
162 lines (146 loc) · 5.83 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
#![feature(rustc_private)]
#[macro_use]
mod common;
use common::*;
use rust_verify_test_macros::examples_in_dir;
use std::path::{Path, PathBuf};
#[derive(Debug)]
enum Mode {
ExpectSuccess,
ExpectErrors,
ExpectFailures,
ExpectWarnings,
}
examples_in_dir!("../../examples");
examples_in_dir!("../../examples/guide");
examples_in_dir!("../../examples/resource");
examples_in_dir!("../../examples/state_machines");
examples_in_dir!("../../examples/summer_school");
examples_in_dir!("../../examples/state_machines/tutorial");
examples_in_dir!("../../examples/state_machines/reference-examples");
examples_in_dir!("../../examples/std_test");
examples_in_dir!("../../examples/cuckoo_hash_table");
#[cfg(feature = "singular")]
examples_in_dir!("../../examples/integer_ring");
fn run_example_for_file(file_path: &str) {
let relative_path = Path::new(file_path);
let mut path = std::path::PathBuf::from("rust_verify");
path.extend(relative_path);
let path = path.to_str().expect("invalid example path");
let mut reader =
std::io::BufReader::new(std::fs::File::open(relative_path).expect("cannot open file"));
let mut first_line = String::new();
let first_line_elements: Vec<_> = {
use std::io::BufRead;
reader.read_line(&mut first_line).expect("unable to read first line");
first_line.trim().split(" ").collect()
};
let mut mode = Mode::ExpectSuccess;
let mut options = vec![];
if let ["//", "rust_verify/tests/example.rs", command, ..] = &first_line_elements[..] {
match *command {
"expect-success" => mode = Mode::ExpectSuccess,
"expect-errors" => mode = Mode::ExpectErrors,
"expect-failures" => mode = Mode::ExpectFailures,
"expect-warnings" => mode = Mode::ExpectWarnings,
"expand-errors" => {
mode = Mode::ExpectFailures;
options.push("--expand-errors");
}
"no-report-long-running" => {
mode = Mode::ExpectSuccess;
options.push("--no-report-long-running");
}
"ignore" => {
if first_line_elements.len() > 3 {
// We require that any comment is separated by a `---` which acts as a good
// visual separator.
if first_line_elements[3] != "---" {
panic!(
"Expected '---' to separate the extra comment from the 'ignore' declaration. Found {:?}",
first_line_elements[3],
);
} else if first_line_elements.len() == 4 {
panic!(
"Expected comment after visual separator '---' but no comment found."
);
}
} else {
panic!(
"{}",
"Expected '--- {reason}' after the 'ignore', but none was provided."
);
}
return;
}
_ => panic!(
"invalid command {:?} for example file test: use one of 'expect-success', 'expect-errors', 'expect-failures', 'expand-errors', 'no-report-long-running', or 'ignore'",
command
),
}
}
let relative_path = PathBuf::from(relative_path);
// Create a temp directory under target/ for --out-dir output
let target_dir = std::env::current_exe().unwrap();
let target_dir = target_dir.parent().unwrap().parent().unwrap();
let example_out_dir = target_dir
.join("test_inputs")
.join(format!("example-{}", relative_path.file_stem().unwrap().to_str().unwrap()));
if example_out_dir.exists() {
std::fs::remove_dir_all(&example_out_dir).unwrap();
}
std::fs::create_dir_all(&example_out_dir).unwrap();
let output = run_verus(&options, &example_out_dir, &relative_path, true, true);
use regex::Regex;
let re = Regex::new(r"verification results:: (\d+) verified, (\d+) errors").unwrap();
let stdout = std::str::from_utf8(&output.stdout).expect("invalid stdout encoding");
let stderr = std::str::from_utf8(&output.stderr).expect("invalid stderr encoding").trim();
let mut errors = Vec::new();
let mut expand_errors_notes = Vec::new();
let mut is_failure = false;
let (warnings, _notes) =
parse_diags(stderr, &mut errors, &mut expand_errors_notes, &mut is_failure);
let verifier_output: Option<(u64, u64)> = re.captures_iter(stdout).next().map(|x| {
(
x[1].parse().expect("invalid verifier output"),
x[2].parse().expect("invalid verifier output"),
)
});
let success = match mode {
Mode::ExpectSuccess => {
output.status.success()
&& match verifier_output {
Some((_, 0)) => true,
_ => false,
}
&& !is_failure
&& warnings.len() == 0
}
Mode::ExpectErrors => !output.status.success(),
Mode::ExpectWarnings => {
output.status.success()
&& match verifier_output {
Some((_, 0)) => true,
_ => false,
}
&& warnings.len() > 0
}
Mode::ExpectFailures => {
!output.status.success()
&& match verifier_output {
Some((_, failures)) if failures > 0 => true,
_ => false,
}
}
};
if !success {
eprintln!("- example {} - mode: {:?} - failed -", &path, mode);
if warnings.len() > 0 {
for w in warnings {
eprintln!("- warning - {}", w.rendered);
}
}
eprintln!("- stdout -\n{}\n", stdout);
panic!();
}
}