aboutsummaryrefslogtreecommitdiff
path: root/tools/src/bin/collect-tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tools/src/bin/collect-tests.rs')
-rw-r--r--tools/src/bin/collect-tests.rs130
1 files changed, 130 insertions, 0 deletions
diff --git a/tools/src/bin/collect-tests.rs b/tools/src/bin/collect-tests.rs
new file mode 100644
index 000000000..df9d2db81
--- /dev/null
+++ b/tools/src/bin/collect-tests.rs
@@ -0,0 +1,130 @@
1extern crate file;
2extern crate itertools;
3extern crate walkdir;
4
5use walkdir::WalkDir;
6use itertools::Itertools;
7
8use std::path::{Path, PathBuf};
9use std::collections::HashSet;
10use std::fs;
11
12fn main() {
13 let verify = ::std::env::args().any(|arg| arg == "--verify");
14
15 let d = grammar_dir();
16 let tests = tests_from_dir(&d);
17 let existing = existing_tests();
18
19 for t in existing.difference(&tests) {
20 panic!("Test is deleted: {}\n{}", t.name, t.text);
21 }
22
23 let new_tests = tests.difference(&existing);
24 for (i, t) in new_tests.enumerate() {
25 if verify {
26 panic!("Inline test is not recorded: {}", t.name);
27 }
28
29 let name = format!("{:04}_{}.rs", existing.len() + i + 1, t.name);
30 println!("Creating {}", name);
31 let path = inline_tests_dir().join(name);
32 file::put_text(&path, &t.text).unwrap();
33 }
34}
35
36#[derive(Debug, Eq)]
37struct Test {
38 name: String,
39 text: String,
40}
41
42impl PartialEq for Test {
43 fn eq(&self, other: &Test) -> bool {
44 self.name.eq(&other.name)
45 }
46}
47
48impl ::std::hash::Hash for Test {
49 fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
50 self.name.hash(state)
51 }
52}
53
54fn tests_from_dir(dir: &Path) -> HashSet<Test> {
55 let mut res = HashSet::new();
56 for entry in WalkDir::new(dir) {
57 let entry = entry.unwrap();
58 if !entry.file_type().is_file() {
59 continue;
60 }
61 if entry.path().extension().unwrap_or_default() != "rs" {
62 continue;
63 }
64 let text = file::get_text(entry.path()).unwrap();
65
66 for test in collect_tests(&text) {
67 if let Some(old_test) = res.replace(test) {
68 panic!("Duplicate test: {}", old_test.name)
69 }
70 }
71 }
72 res
73}
74
75fn collect_tests(s: &str) -> Vec<Test> {
76 let mut res = vec![];
77 let prefix = "// ";
78 let comment_blocks = s.lines()
79 .map(str::trim_left)
80 .group_by(|line| line.starts_with(prefix));
81
82 for (is_comment, block) in comment_blocks.into_iter() {
83 if !is_comment {
84 continue;
85 }
86 let mut block = block.map(|line| &line[prefix.len()..]);
87 let first = block.next().unwrap();
88 if !first.starts_with("test ") {
89 continue;
90 }
91 let name = first["test ".len()..].to_string();
92 let text: String = itertools::join(block.chain(::std::iter::once("")), "\n");
93 assert!(!text.trim().is_empty() && text.ends_with("\n"));
94 res.push(Test { name, text })
95 }
96 res
97}
98
99fn existing_tests() -> HashSet<Test> {
100 let mut res = HashSet::new();
101 for file in fs::read_dir(&inline_tests_dir()).unwrap() {
102 let file = file.unwrap();
103 let path = file.path();
104 if path.extension().unwrap_or_default() != "rs" {
105 continue;
106 }
107 let name = path.file_name().unwrap().to_str().unwrap();
108 let name = name["0000_".len()..name.len() - 3].to_string();
109 let text = file::get_text(&path).unwrap();
110 res.insert(Test { name, text });
111 }
112 res
113}
114
115fn inline_tests_dir() -> PathBuf {
116 let res = base_dir().join("tests/data/parser/inline");
117 if !res.is_dir() {
118 fs::create_dir_all(&res).unwrap();
119 }
120 res
121}
122
123fn grammar_dir() -> PathBuf {
124 base_dir().join("src/parser/event_parser/grammar")
125}
126
127fn base_dir() -> PathBuf {
128 let dir = env!("CARGO_MANIFEST_DIR");
129 PathBuf::from(dir).parent().unwrap().to_owned()
130}