]> git.lizzy.rs Git - rust.git/blob - tests/idem.rs
9f6b3602061478610e5cdfb1a275eacc2205f77e
[rust.git] / tests / idem.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![feature(std_misc)]
12 extern crate rustfmt;
13
14 use std::collections::HashMap;
15 use std::fs;
16 use std::io::Read;
17 use rustfmt::*;
18
19 // For now, the only supported regression tests are idempotent tests - the input and
20 // output must match exactly.
21 // FIXME(#28) would be good to check for error messages and fail on them, or at least report.
22 #[test]
23 fn idempotent_tests() {
24     println!("Idempotent tests:");
25
26     // Get all files in the tests/idem directory
27     let files = fs::read_dir("tests/idem").unwrap();
28     let files2 = fs::read_dir("tests").unwrap();
29     let files3 = fs::read_dir("src/bin").unwrap();
30     // For each file, run rustfmt and collect the output
31
32     let mut count = 0;
33     let mut fails = 0;
34     for entry in files.chain(files2).chain(files3) {
35         let path = entry.unwrap().path();
36         let file_name = path.to_str().unwrap();
37         if !file_name.ends_with(".rs") {
38             continue;
39         }
40         println!("Testing '{}'...", file_name);
41         match idempotent_check(file_name.to_owned()) {
42             Ok(()) => {},
43             Err(m) => {
44                 print_mismatches(m);
45                 fails += 1;
46             },
47         }
48         count += 1;
49     }
50     // And also dogfood rustfmt!
51     println!("Testing 'src/lib.rs'...");
52     match idempotent_check("src/lib.rs".to_owned()) {
53         Ok(()) => {},
54         Err(m) => {
55             print_mismatches(m);
56             fails += 1;
57         },
58     }
59     count += 1;
60
61     // Display results
62     println!("Ran {} idempotent tests; {} failures.", count, fails);
63     assert!(fails == 0, "{} idempotent tests failed", fails);
64 }
65
66 // Compare output to input.
67 fn print_mismatches(result: HashMap<String, String>) {
68     for (file_name, fmt_text) in result {
69         println!("Mismatch in {}.", file_name);
70         println!("{}", fmt_text);
71     }
72 }
73
74 // Ick, just needed to get a &'static to handle_result.
75 static HANDLE_RESULT: &'static Fn(HashMap<String, String>) = &handle_result;
76
77 pub fn idempotent_check(filename: String) -> Result<(), HashMap<String, String>> {
78     use std::thread;
79     use std::fs;
80     use std::io::Read;
81     let args = vec!["rustfmt".to_owned(), filename];
82     thread::spawn(move || {
83         run(args, WriteMode::Return(HANDLE_RESULT));
84     }).join().map_err(|mut any|
85         any.downcast_mut::<HashMap<String, String>>()
86            .unwrap() // i know it is a hashmap
87            .drain() // i only get a reference :(
88            .collect() // so i need to turn it into an iter and then back
89     )
90 }
91
92 // Compare output to input.
93 fn handle_result(result: HashMap<String, String>) {
94     let mut failures = HashMap::new();
95
96     for (file_name, fmt_text) in result {
97         let mut f = fs::File::open(&file_name).unwrap();
98         let mut text = String::new();
99         // TODO: speedup by running through bytes iterator
100         f.read_to_string(&mut text).unwrap();
101         if fmt_text != text {
102             failures.insert(file_name, fmt_text);
103         }
104     }
105     if !failures.is_empty() {
106         panic!(failures);
107     }
108 }