1 #![deny(rust_2018_idioms)]
2 
3 use std::fs;
4 use std::io::{Read, Seek, SeekFrom, Write};
5 use std::sync::mpsc::{sync_channel, TryRecvError};
6 use std::thread;
7 
8 #[test]
test_basic()9 fn test_basic() {
10     let mut tmpfile = tempfile::tempfile().unwrap();
11     write!(tmpfile, "abcde").unwrap();
12     tmpfile.seek(SeekFrom::Start(0)).unwrap();
13     let mut buf = String::new();
14     tmpfile.read_to_string(&mut buf).unwrap();
15     assert_eq!("abcde", buf);
16 }
17 
18 #[test]
test_cleanup()19 fn test_cleanup() {
20     let tmpdir = tempfile::tempdir().unwrap();
21     {
22         let mut tmpfile = tempfile::tempfile_in(&tmpdir).unwrap();
23         write!(tmpfile, "abcde").unwrap();
24     }
25     let num_files = fs::read_dir(&tmpdir).unwrap().count();
26     assert!(num_files == 0);
27 }
28 
29 #[test]
test_pathological_cleaner()30 fn test_pathological_cleaner() {
31     let tmpdir = tempfile::tempdir().unwrap();
32     let (tx, rx) = sync_channel(0);
33     let cleaner_thread = thread::spawn(move || {
34         let tmp_path = rx.recv().unwrap();
35         while rx.try_recv() == Err(TryRecvError::Empty) {
36             let files = fs::read_dir(&tmp_path).unwrap();
37             for f in files {
38                 // skip errors
39                 if f.is_err() {
40                     continue;
41                 }
42                 let f = f.unwrap();
43                 let _ = fs::remove_file(f.path());
44             }
45         }
46     });
47 
48     // block until cleaner_thread makes progress
49     tx.send(tmpdir.path().to_owned()).unwrap();
50     // need 40-400 iterations to encounter race with cleaner on original system
51     for _ in 0..10000 {
52         let mut tmpfile = tempfile::tempfile_in(&tmpdir).unwrap();
53         write!(tmpfile, "abcde").unwrap();
54         tmpfile.seek(SeekFrom::Start(0)).unwrap();
55         let mut buf = String::new();
56         tmpfile.read_to_string(&mut buf).unwrap();
57         assert_eq!("abcde", buf);
58     }
59 
60     // close the channel to make cleaner_thread exit
61     drop(tx);
62     cleaner_thread.join().expect("The cleaner thread failed");
63 }
64