1 // Copyright 2013-2014 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 #![deny(rust_2018_idioms)]
12 
13 use std::env;
14 use std::fs;
15 use std::path::Path;
16 use std::sync::mpsc::channel;
17 use std::thread;
18 
19 use tempfile::{Builder, TempDir};
20 
21 macro_rules! t {
22     ($e:expr) => {
23         match $e {
24             Ok(n) => n,
25             Err(e) => panic!("error: {}", e),
26         }
27     };
28 }
29 
30 trait PathExt {
exists(&self) -> bool31     fn exists(&self) -> bool;
is_dir(&self) -> bool32     fn is_dir(&self) -> bool;
33 }
34 
35 impl PathExt for Path {
exists(&self) -> bool36     fn exists(&self) -> bool {
37         fs::metadata(self).is_ok()
38     }
is_dir(&self) -> bool39     fn is_dir(&self) -> bool {
40         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
41     }
42 }
43 
test_tempdir()44 fn test_tempdir() {
45     let path = {
46         let p = t!(Builder::new().prefix("foobar").tempdir_in(&Path::new(".")));
47         let p = p.path();
48         assert!(p.to_str().unwrap().contains("foobar"));
49         p.to_path_buf()
50     };
51     assert!(!path.exists());
52 }
53 
54 #[test]
test_customnamed()55 fn test_customnamed() {
56     let tmpfile = Builder::new()
57         .prefix("prefix")
58         .suffix("suffix")
59         .rand_bytes(12)
60         .tempdir()
61         .unwrap();
62     let name = tmpfile.path().file_name().unwrap().to_str().unwrap();
63     assert!(name.starts_with("prefix"));
64     assert!(name.ends_with("suffix"));
65     assert_eq!(name.len(), 24);
66 }
67 
test_rm_tempdir()68 fn test_rm_tempdir() {
69     let (tx, rx) = channel();
70     let f = move || -> () {
71         let tmp = t!(TempDir::new());
72         tx.send(tmp.path().to_path_buf()).unwrap();
73         panic!("panic to unwind past `tmp`");
74     };
75     let _ = thread::spawn(f).join();
76     let path = rx.recv().unwrap();
77     assert!(!path.exists());
78 
79     let tmp = t!(TempDir::new());
80     let path = tmp.path().to_path_buf();
81     let f = move || -> () {
82         let _tmp = tmp;
83         panic!("panic to unwind past `tmp`");
84     };
85     let _ = thread::spawn(f).join();
86     assert!(!path.exists());
87 
88     let path;
89     {
90         let f = move || t!(TempDir::new());
91 
92         let tmp = thread::spawn(f).join().unwrap();
93         path = tmp.path().to_path_buf();
94         assert!(path.exists());
95     }
96     assert!(!path.exists());
97 
98     let path;
99     {
100         let tmp = t!(TempDir::new());
101         path = tmp.into_path();
102     }
103     assert!(path.exists());
104     t!(fs::remove_dir_all(&path));
105     assert!(!path.exists());
106 }
107 
test_rm_tempdir_close()108 fn test_rm_tempdir_close() {
109     let (tx, rx) = channel();
110     let f = move || -> () {
111         let tmp = t!(TempDir::new());
112         tx.send(tmp.path().to_path_buf()).unwrap();
113         t!(tmp.close());
114         panic!("panic when unwinding past `tmp`");
115     };
116     let _ = thread::spawn(f).join();
117     let path = rx.recv().unwrap();
118     assert!(!path.exists());
119 
120     let tmp = t!(TempDir::new());
121     let path = tmp.path().to_path_buf();
122     let f = move || -> () {
123         let tmp = tmp;
124         t!(tmp.close());
125         panic!("panic when unwinding past `tmp`");
126     };
127     let _ = thread::spawn(f).join();
128     assert!(!path.exists());
129 
130     let path;
131     {
132         let f = move || t!(TempDir::new());
133 
134         let tmp = thread::spawn(f).join().unwrap();
135         path = tmp.path().to_path_buf();
136         assert!(path.exists());
137         t!(tmp.close());
138     }
139     assert!(!path.exists());
140 
141     let path;
142     {
143         let tmp = t!(TempDir::new());
144         path = tmp.into_path();
145     }
146     assert!(path.exists());
147     t!(fs::remove_dir_all(&path));
148     assert!(!path.exists());
149 }
150 
151 // Ideally these would be in std::os but then core would need
152 // to depend on std
recursive_mkdir_rel()153 fn recursive_mkdir_rel() {
154     let path = Path::new("frob");
155     let cwd = env::current_dir().unwrap();
156     println!(
157         "recursive_mkdir_rel: Making: {} in cwd {} [{}]",
158         path.display(),
159         cwd.display(),
160         path.exists()
161     );
162     t!(fs::create_dir(&path));
163     assert!(path.is_dir());
164     t!(fs::create_dir_all(&path));
165     assert!(path.is_dir());
166 }
167 
recursive_mkdir_dot()168 fn recursive_mkdir_dot() {
169     let dot = Path::new(".");
170     t!(fs::create_dir_all(&dot));
171     let dotdot = Path::new("..");
172     t!(fs::create_dir_all(&dotdot));
173 }
174 
recursive_mkdir_rel_2()175 fn recursive_mkdir_rel_2() {
176     let path = Path::new("./frob/baz");
177     let cwd = env::current_dir().unwrap();
178     println!(
179         "recursive_mkdir_rel_2: Making: {} in cwd {} [{}]",
180         path.display(),
181         cwd.display(),
182         path.exists()
183     );
184     t!(fs::create_dir_all(&path));
185     assert!(path.is_dir());
186     assert!(path.parent().unwrap().is_dir());
187     let path2 = Path::new("quux/blat");
188     println!(
189         "recursive_mkdir_rel_2: Making: {} in cwd {}",
190         path2.display(),
191         cwd.display()
192     );
193     t!(fs::create_dir("quux"));
194     t!(fs::create_dir_all(&path2));
195     assert!(path2.is_dir());
196     assert!(path2.parent().unwrap().is_dir());
197 }
198 
199 // Ideally this would be in core, but needs TempFile
test_remove_dir_all_ok()200 pub fn test_remove_dir_all_ok() {
201     let tmpdir = t!(TempDir::new());
202     let tmpdir = tmpdir.path();
203     let root = tmpdir.join("foo");
204 
205     println!("making {}", root.display());
206     t!(fs::create_dir(&root));
207     t!(fs::create_dir(&root.join("foo")));
208     t!(fs::create_dir(&root.join("foo").join("bar")));
209     t!(fs::create_dir(&root.join("foo").join("bar").join("blat")));
210     t!(fs::remove_dir_all(&root));
211     assert!(!root.exists());
212     assert!(!root.join("bar").exists());
213     assert!(!root.join("bar").join("blat").exists());
214 }
215 
dont_double_panic()216 pub fn dont_double_panic() {
217     let r: Result<(), _> = thread::spawn(move || {
218         let tmpdir = TempDir::new().unwrap();
219         // Remove the temporary directory so that TempDir sees
220         // an error on drop
221         t!(fs::remove_dir(tmpdir.path()));
222         // Panic. If TempDir panics *again* due to the rmdir
223         // error then the process will abort.
224         panic!();
225     })
226     .join();
227     assert!(r.is_err());
228 }
229 
in_tmpdir<F>(f: F) where F: FnOnce(),230 fn in_tmpdir<F>(f: F)
231 where
232     F: FnOnce(),
233 {
234     let tmpdir = t!(TempDir::new());
235     assert!(env::set_current_dir(tmpdir.path()).is_ok());
236 
237     f();
238 }
239 
pass_as_asref_path()240 pub fn pass_as_asref_path() {
241     let tempdir = t!(TempDir::new());
242     takes_asref_path(&tempdir);
243 
244     fn takes_asref_path<T: AsRef<Path>>(path: T) {
245         let path = path.as_ref();
246         assert!(path.exists());
247     }
248 }
249 
250 #[test]
main()251 fn main() {
252     in_tmpdir(test_tempdir);
253     in_tmpdir(test_rm_tempdir);
254     in_tmpdir(test_rm_tempdir_close);
255     in_tmpdir(recursive_mkdir_rel);
256     in_tmpdir(recursive_mkdir_dot);
257     in_tmpdir(recursive_mkdir_rel_2);
258     in_tmpdir(test_remove_dir_all_ok);
259     in_tmpdir(dont_double_panic);
260     in_tmpdir(pass_as_asref_path);
261 }
262