tempdir.rs 6.6 KB

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