/
test_utils.rs
146 lines (135 loc) · 4.49 KB
/
test_utils.rs
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
// Copyright (C) 2022, Alex Badics
//
// This file is part of Hun-Law.
//
// Hun-law is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Hun-law is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Hun-law. If not, see <http://www.gnu.org/licenses/>.
use std::{
fmt::Display,
fs::File,
io::{self, Read},
path::Path,
};
use anyhow::{anyhow, Result};
use chrono::NaiveDate;
use colored::*;
use hun_law::{
identifier::ActIdentifier,
parser::{mk_act_section::ActRawText, structure::parse_act_structure},
structure::{Act, ActChild, ParagraphChildren, SAEBody},
util::{indentedline::IndentedLine, singleton_yaml},
};
use serde::Serialize;
use similar::{ChangeTag, TextDiff};
pub use tempfile::TempDir;
pub fn read_all(path: impl AsRef<Path>) -> io::Result<Vec<u8>> {
let mut result = Vec::new();
File::open(path)?.read_to_end(&mut result)?;
Ok(result)
}
struct PrettyDiff {
pub left: String,
pub right: String,
}
impl Display for PrettyDiff {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let diff = TextDiff::from_lines(&self.left, &self.right);
for (idx, group) in diff.grouped_ops(3).iter().enumerate() {
if idx > 0 {
println!("{:-^1$}", "-", 80);
}
for op in group {
for change in diff.iter_inline_changes(op) {
let tag = match change.tag() {
ChangeTag::Delete => "-".red(),
ChangeTag::Insert => "+".green(),
ChangeTag::Equal => " ".white(),
};
tag.fmt(f)?;
for (emphasized, value) in change.iter_strings_lossy() {
if emphasized {
write!(
f,
"{}",
value.color(tag.fgcolor().unwrap()).underline().bold()
)?;
} else {
write!(f, "{}", value.color(tag.fgcolor().unwrap()))?;
}
}
if change.missing_newline() {
writeln!(f)?;
}
}
}
}
Ok(())
}
}
pub fn ensure_eq<T, U>(expected: &T, actual: &U, message: &str) -> Result<()>
where
T: Serialize + ?Sized + PartialEq<U>,
U: Serialize + ?Sized,
{
// This is duplicated from ensure_eq, but that's because the structures may be 'equal' even
// when ther YML form is not.
if expected != actual {
Err(anyhow!(
"{}\n{}",
message,
PrettyDiff {
left: singleton_yaml::to_string(expected).unwrap(),
right: singleton_yaml::to_string(actual).unwrap(),
}
))
} else {
Ok(())
}
}
pub fn to_indented_lines(data: &[u8]) -> Vec<IndentedLine> {
std::str::from_utf8(data)
.unwrap()
.split('\n')
.map(IndentedLine::from_test_str)
.collect()
}
pub fn parse_txt_as_act(path: &Path) -> Result<Act> {
let data_as_lines = to_indented_lines(&read_all(path)?);
parse_act_structure(&ActRawText {
identifier: ActIdentifier {
year: 2345,
number: 0xd,
},
subject: "A tesztelésről".to_string(),
publication_date: NaiveDate::from_ymd(2345, 6, 7),
body: data_as_lines,
})
}
// clean out the quoted blocks' contents, because we don't want to
// pollute the test yamls with serialized indented lines
pub fn clean_quoted_blocks(act: &mut Act) {
for act_child in &mut act.children {
if let ActChild::Article(article) = act_child {
for paragraph in &mut article.children {
if let SAEBody::Children {
children: ParagraphChildren::QuotedBlock(qbs),
..
} = &mut paragraph.body
{
for qb in qbs {
qb.lines = vec![]
}
}
}
}
}
}