]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | //! Provides a simple way to set up compiletest sample testsuites used in testing. |
2 | //! | |
3 | //! Inspired by cargo's `cargo-test-support` crate: | |
4 | //! https://github.com/rust-lang/cargo/tree/master/crates/cargo-test-support | |
5 | use std::env; | |
6 | use std::fs; | |
7 | use std::path::{Path, PathBuf}; | |
8 | use std::cell::RefCell; | |
9 | use std::sync::atomic::{AtomicUsize, Ordering}; | |
10 | ||
11 | ||
12 | static COMPILETEST_INTEGRATION_TEST_DIR: &str = "cit"; | |
13 | ||
14 | thread_local! { | |
15 | static TEST_ID: RefCell<Option<usize>> = RefCell::new(None); | |
16 | } | |
17 | ||
18 | lazy_static::lazy_static! { | |
19 | pub static ref GLOBAL_ROOT: PathBuf = { | |
20 | let mut path = env::current_exe().unwrap(); | |
21 | path.pop(); // chop off exe name | |
22 | path.pop(); // chop off 'deps' part | |
23 | path.pop(); // chop off 'debug' | |
24 | ||
25 | path.push(COMPILETEST_INTEGRATION_TEST_DIR); | |
26 | path.mkdir_p(); | |
27 | path | |
28 | }; | |
29 | } | |
30 | ||
31 | pub fn testsuite(mode: &str) -> TestsuiteBuilder { | |
32 | let builder = TestsuiteBuilder::new(mode); | |
33 | builder.build(); | |
34 | builder | |
35 | } | |
36 | ||
37 | pub struct TestsuiteBuilder { | |
38 | pub root: PathBuf, | |
39 | } | |
40 | ||
41 | impl TestsuiteBuilder { | |
42 | pub fn new(mode: &str) -> Self { | |
43 | static NEXT_ID: AtomicUsize = AtomicUsize::new(0); | |
44 | ||
45 | let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); | |
46 | TEST_ID.with(|n| *n.borrow_mut() = Some(id)); | |
47 | let root = GLOBAL_ROOT.join(format!("id{}", TEST_ID.with(|n|n.borrow().unwrap()))).join(mode); | |
48 | root.mkdir_p(); | |
49 | ||
50 | Self { | |
51 | root, | |
52 | } | |
53 | } | |
54 | ||
55 | ||
56 | /// Creates a new file to be used for the integration test | |
57 | pub fn mk_file(&self, path: &str, body: &str) { | |
58 | self.root.mkdir_p(); | |
59 | fs::write(self.root.join(&path), &body) | |
60 | .unwrap_or_else(|e| panic!("could not create file {}: {}", path, e)); | |
61 | } | |
62 | ||
63 | /// Returns the contents of the file | |
64 | pub fn file_contents(&self, name: &str) -> String { | |
65 | fs::read_to_string(self.root.join(name)).expect("Unable to read file") | |
66 | } | |
67 | ||
68 | // Sets up a new testsuite root directory | |
69 | fn build(&self) { | |
70 | // Cleanup before we run the next test | |
71 | self.rm_root(); | |
72 | ||
73 | // Create the new directory | |
74 | self.root.mkdir_p(); | |
75 | } | |
76 | ||
77 | /// Deletes the root directory and all its contents | |
78 | fn rm_root(&self) { | |
79 | self.root.rm_rf(); | |
80 | } | |
81 | } | |
82 | ||
83 | pub trait PathExt { | |
84 | fn rm_rf(&self); | |
85 | fn mkdir_p(&self); | |
86 | } | |
87 | ||
88 | impl PathExt for Path { | |
89 | fn rm_rf(&self) { | |
90 | if self.is_dir() { | |
91 | if let Err(e) = fs::remove_dir_all(self) { | |
92 | panic!("failed to remove {:?}: {:?}", self, e) | |
93 | } | |
94 | } else { | |
95 | if let Err(e) = fs::remove_file(self) { | |
96 | panic!("failed to remove {:?}: {:?}", self, e) | |
97 | } | |
98 | } | |
99 | } | |
100 | ||
101 | fn mkdir_p(&self) { | |
102 | fs::create_dir_all(self) | |
103 | .unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e)) | |
104 | } | |
105 | } |