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
use anyhow::anyhow;
use move_command_line_common::testing::read_env_update_baseline;
use prettydiff::{basic::DiffOp, diff_lines};
use regex::Regex;
use std::{
fs::{self, remove_file, File},
io::{Read, Write},
path::Path,
};
pub fn verify_or_update_baseline(baseline_file_name: &Path, text: &str) -> anyhow::Result<()> {
let update_baseline = read_env_update_baseline();
if update_baseline {
if !text.is_empty() {
baseline_file_name.parent().map(fs::create_dir_all);
let mut file = File::create(baseline_file_name)?;
write!(file, "{}", clean_for_baseline(text))?;
} else {
let _ = remove_file(baseline_file_name);
}
Ok(())
} else {
let mut contents = String::new();
if baseline_file_name.exists() {
let mut file = File::open(baseline_file_name)?;
file.read_to_string(&mut contents)?;
}
diff(clean_for_baseline(text).as_ref(), &contents)
}
}
fn clean_for_baseline(content: &str) -> String {
let rex = Regex::new(r"(/var|/tmp)(/[^/]*)*/(?P<basename>[^.]*\.)").expect("regexp ok");
let mut res = String::new();
for line in content.lines() {
let line = line.trim_end();
let line = rex.replace_all(line, "$basename");
res.push_str(line.to_string().as_str());
res.push('\n');
}
res = res.trim_end().to_string(); res.push('\n'); res
}
fn diff(old_content: &str, new_content: &str) -> anyhow::Result<()> {
if old_content.trim() == new_content.trim() {
return Ok(());
}
let print_lines = |result: &mut Vec<String>, lines: &[&str], prefix: &str| {
for line in lines {
result.push(format!("{}{}", prefix, line));
}
};
let print_context = |result: &mut Vec<String>, lines: &[&str]| {
if lines.len() <= 3 {
print_lines(result, lines, "= ");
} else {
print_lines(result, &lines[..1], "= ");
result.push(format!("= ... ({} lines)", lines.len() - 2));
print_lines(result, &lines[lines.len() - 1..], "= ");
}
};
let diff = diff_lines(new_content, old_content);
let mut result = vec!["
New output differs from baseline!
Call this test with env variable UPBL=1 to regenerate or remove old baseline files.
Then use your favorite changelist diff tool to verify you are good with the changes.
Or check the rudimentary diff below:
"
.to_string()];
for d in diff.diff() {
match d {
DiffOp::Equal(lines) => print_context(&mut result, lines),
DiffOp::Insert(lines) => print_lines(&mut result, lines, "+ "),
DiffOp::Remove(lines) => print_lines(&mut result, lines, "- "),
DiffOp::Replace(old, new) => {
print_lines(&mut result, old, "- ");
print_lines(&mut result, new, "+ ");
}
}
}
Err(anyhow!(result.join("\n")))
}