Skip to main content

cli_assert/
files.rs

1use std::path::{Path, PathBuf};
2use std::sync::atomic::{AtomicU64, Ordering};
3use std::time::{SystemTime, UNIX_EPOCH};
4
5pub struct TempFile {
6  /// Temporary directory.
7  dir: TempDir,
8  /// Full path to file in temporary directory.
9  path: PathBuf,
10}
11
12impl TempFile {
13  /// Creates a new file with specified name in temporary directory.
14  pub fn new(file_name: impl AsRef<Path>) -> Self {
15    let dir = TempDir::default();
16    let path = dir.path().join(file_name);
17    std::fs::File::create_new(&path).unwrap();
18    Self { dir, path }
19  }
20
21  /// Writes data to file.
22  pub fn write(&self, data: impl AsRef<[u8]>) {
23    std::fs::write(&self.path, data.as_ref()).unwrap();
24  }
25
26  /// Asserts the expected file content.
27  pub fn assert(&self, expected: impl AsRef<[u8]>) {
28    let actual = std::fs::read(&self.path).unwrap();
29    let expected = expected.as_ref();
30    if actual != expected {
31      println!("expected content: {:?}", expected);
32      println!("  actual content: {:?}", actual);
33      panic!("unexpected content")
34    }
35  }
36
37  /// Returns the directory name.
38  pub fn dir(&self) -> &Path {
39    self.dir.path()
40  }
41
42  /// Returns the file path.
43  pub fn path(&self) -> &Path {
44    &self.path
45  }
46
47  /// Sets read-only permission on file.
48  pub fn set_readonly(&self, readonly: bool) {
49    let mut permissions = std::fs::metadata(self.path()).unwrap().permissions();
50    permissions.set_readonly(readonly);
51    std::fs::set_permissions(self.path(), permissions).unwrap();
52  }
53}
54
55pub struct TempDir {
56  path: PathBuf,
57}
58
59impl Default for TempDir {
60  fn default() -> Self {
61    Self::new()
62  }
63}
64
65impl TempDir {
66  /// Creates a new temporary directory.
67  pub fn new() -> Self {
68    static COUNTER: AtomicU64 = AtomicU64::new(0);
69    let pid = std::process::id();
70    let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos();
71    let count = COUNTER.fetch_add(1, Ordering::Relaxed);
72    let name = format!("cli-assert-{pid}-{nanos}-{count}");
73    let path = std::env::temp_dir().join(name);
74    std::fs::create_dir(&path).unwrap();
75    TempDir { path }
76  }
77
78  /// Returns a path to temporary directory.
79  pub fn path(&self) -> &Path {
80    &self.path
81  }
82}
83
84impl Drop for TempDir {
85  fn drop(&mut self) {
86    _ = std::fs::remove_dir_all(&self.path);
87  }
88}