blob: e8732adc96a15f8a2be7d2d5438808d4aa14bd10 [file] [log] [blame]
Jooyung Hanf48ceb42021-06-01 18:00:04 +09001// Copyright 2021, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! IO utilities
16
17use std::fs::File;
18use std::io;
19use std::path::Path;
20use std::thread;
21use std::time::{Duration, Instant};
22
23const SLEEP_DURATION: Duration = Duration::from_millis(5);
24
25/// waits for a file with a timeout and returns it
26pub fn wait_for_file<P: AsRef<Path>>(path: P, timeout: Duration) -> io::Result<File> {
27 let begin = Instant::now();
28 loop {
29 match File::open(&path) {
30 Ok(file) => return Ok(file),
31 Err(error) => {
32 if error.kind() != io::ErrorKind::NotFound {
33 return Err(error);
34 }
35 if begin.elapsed() > timeout {
36 return Err(io::Error::from(io::ErrorKind::NotFound));
37 }
38 thread::sleep(SLEEP_DURATION);
39 }
40 }
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use std::io::{Read, Write};
48
49 #[test]
50 fn test_wait_for_file() -> io::Result<()> {
51 let test_dir = tempfile::TempDir::new().unwrap();
52 let test_file = test_dir.path().join("test.txt");
53 thread::spawn(move || -> io::Result<()> {
54 thread::sleep(Duration::from_secs(1));
55 File::create(test_file)?.write_all(b"test")
56 });
57
58 let test_file = test_dir.path().join("test.txt");
59 let mut file = wait_for_file(&test_file, Duration::from_secs(5))?;
60 let mut buffer = String::new();
61 file.read_to_string(&mut buffer)?;
62 assert_eq!("test", buffer);
63 Ok(())
64 }
65
66 #[test]
67 fn test_wait_for_file_fails() {
68 let test_dir = tempfile::TempDir::new().unwrap();
69 let test_file = test_dir.path().join("test.txt");
70 let file = wait_for_file(&test_file, Duration::from_secs(1));
71 assert!(file.is_err());
72 assert_eq!(io::ErrorKind::NotFound, file.unwrap_err().kind());
73 }
74}