aboutsummaryrefslogtreecommitdiff
path: root/crates/test_utils/src/lib.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-12-24 14:40:11 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-12-24 14:40:11 +0000
commit67e768466ff2e2611eead0f30b2e9c4083c80c20 (patch)
tree8984028019837c91131fc30f60eecf8c2a457368 /crates/test_utils/src/lib.rs
parentabe09eb5edfe8f4c58baa16140acbd414635836f (diff)
parent4befde1eee5b1e2b7ddc9bf764b77f82b792c318 (diff)
Merge #327
327: Beginnings of type inference r=flodiebold a=flodiebold I was a bit bored, so I thought I'd try to start implementing the type system and see how far I come :wink: This is obviously still extremely WIP, only very basic stuff working, but I thought I'd post this now to get some feedback as to whether this approach makes sense at all. There's no user-visible effect yet, but the type inference has tests similar to the ones for the parser. My next step will probably be to implement struct types, after which this could probably be used to complete fields. I realize this may all get thrown away when/if the compiler query system gets usable, but I feel like there are lots of IDE features that could be implemented with somewhat working type inference in the meantime :smile: Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/test_utils/src/lib.rs')
-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}