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