aboutsummaryrefslogtreecommitdiff
path: root/crates/test_utils
diff options
context:
space:
mode:
Diffstat (limited to 'crates/test_utils')
-rw-r--r--crates/test_utils/src/lib.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index beb936c61..012b1d0b4 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -1,4 +1,6 @@
1use std::fmt; 1use std::fmt;
2use std::fs;
3use std::path::{Path, PathBuf};
2 4
3use itertools::Itertools; 5use itertools::Itertools;
4use text_unit::{TextRange, TextUnit}; 6use text_unit::{TextRange, TextUnit};
@@ -262,3 +264,100 @@ pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a
262 _ => Some((expected, actual)), 264 _ => Some((expected, actual)),
263 } 265 }
264} 266}
267
268pub fn dir_tests<F>(test_data_dir: &Path, paths: &[&str], f: F)
269where
270 F: Fn(&str, &Path) -> String,
271{
272 for (path, input_code) in collect_tests(test_data_dir, paths) {
273 let parse_tree = f(&input_code, &path);
274 let path = path.with_extension("txt");
275 if !path.exists() {
276 println!("\nfile: {}", path.display());
277 println!("No .txt file with expected result, creating...\n");
278 println!("{}\n{}", input_code, parse_tree);
279 fs::write(&path, &parse_tree).unwrap();
280 panic!("No expected result")
281 }
282 let expected = read_text(&path);
283 let expected = expected.as_str();
284 let parse_tree = parse_tree.as_str();
285 assert_equal_text(expected, parse_tree, &path);
286 }
287}
288
289pub fn collect_tests(test_data_dir: &Path, paths: &[&str]) -> Vec<(PathBuf, String)> {
290 paths
291 .iter()
292 .flat_map(|path| {
293 let path = test_data_dir.to_owned().join(path);
294 test_from_dir(&path).into_iter()
295 })
296 .map(|path| {
297 let text = read_text(&path);
298 (path, text)
299 })
300 .collect()
301}
302
303fn test_from_dir(dir: &Path) -> Vec<PathBuf> {
304 let mut acc = Vec::new();
305 for file in fs::read_dir(&dir).unwrap() {
306 let file = file.unwrap();
307 let path = file.path();
308 if path.extension().unwrap_or_default() == "rs" {
309 acc.push(path);
310 }
311 }
312 acc.sort();
313 acc
314}
315
316pub fn project_dir() -> PathBuf {
317 let dir = env!("CARGO_MANIFEST_DIR");
318 PathBuf::from(dir)
319 .parent()
320 .unwrap()
321 .parent()
322 .unwrap()
323 .to_owned()
324}
325
326/// Read file and normalize newlines.
327///
328/// `rustc` seems to always normalize `\r\n` newlines to `\n`:
329///
330/// ```
331/// let s = "
332/// ";
333/// assert_eq!(s.as_bytes(), &[10]);
334/// ```
335///
336/// so this should always be correct.
337pub fn read_text(path: &Path) -> String {
338 fs::read_to_string(path)
339 .expect(&format!("File at {:?} should be valid", path))
340 .replace("\r\n", "\n")
341}
342
343const REWRITE: bool = false;
344
345fn assert_equal_text(expected: &str, actual: &str, path: &Path) {
346 if expected == actual {
347 return;
348 }
349 let dir = project_dir();
350 let pretty_path = path.strip_prefix(&dir).unwrap_or_else(|_| path);
351 if expected.trim() == actual.trim() {
352 println!("whitespace difference, rewriting");
353 println!("file: {}\n", pretty_path.display());
354 fs::write(path, actual).unwrap();
355 return;
356 }
357 if REWRITE {
358 println!("rewriting {}", pretty_path.display());
359 fs::write(path, actual).unwrap();
360 return;
361 }
362 assert_eq_text!(expected, actual, "file: {}", pretty_path.display());
363}