rucksack_db/testing/
db.rs

1use std::{fs, path::PathBuf};
2
3use anyhow::{anyhow, Result};
4
5use rucksack_lib::file;
6
7#[derive(Clone, Debug, Default)]
8pub struct TempDB {
9    backups_path: PathBuf,
10    pub base: PathBuf,
11    data_path: PathBuf,
12    file_name: String,
13    file_path: PathBuf,
14}
15
16pub fn new() -> TempDB {
17    TempDB {
18        base: tempfile::tempdir().unwrap().path().to_owned(),
19
20        ..Default::default()
21    }
22}
23
24impl TempDB {
25    pub fn backups_path(&mut self) -> Result<PathBuf> {
26        if !self.backups_path.as_os_str().is_empty() {
27            return Ok(self.backups_path.clone());
28        };
29        self.backups_path = self.base.clone();
30        self.backups_path.push("backups");
31        file::create_dirs(self.backups_path.clone())?;
32        Ok(self.backups_path.clone())
33    }
34
35    pub fn data_path(&mut self) -> Result<PathBuf> {
36        if !self.data_path.as_os_str().is_empty() {
37            return Ok(self.data_path.clone());
38        };
39        self.data_path = self.base.clone();
40        self.data_path.push("data");
41        file::create_dirs(self.data_path.clone())?;
42        Ok(self.data_path.clone())
43    }
44
45    pub fn file_path(&mut self) -> Result<PathBuf> {
46        if !self.file_path.as_os_str().is_empty() {
47            return Ok(self.file_path.clone());
48        };
49        self.file_path = self.data_path()?;
50        self.file_path.push("secrets");
51        self.file_path.with_extension("db");
52        Ok(self.file_path.clone())
53    }
54
55    pub fn file_name(&mut self) -> Result<String> {
56        if !self.file_name.is_empty() {
57            return Ok(self.file_name.clone());
58        };
59        let f = self.file_path()?;
60        self.file_name = f.display().to_string();
61        Ok(self.file_name.clone())
62    }
63
64    pub fn setup(&mut self) -> Result<()> {
65        let _ = self.data_path()?;
66        let _ = self.backups_path()?;
67        let _ = self.file_path()?;
68        Ok(())
69    }
70
71    pub fn teardown(&self) -> Result<()> {
72        match fs::remove_dir_all(self.base.clone()) {
73            Ok(r) => Ok(r),
74            Err(e) => Err(anyhow!(e)),
75        }
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn test_new() {
85        let temp_db = new();
86        // Just check that base path is set, not that it exists
87        // (tempdir is dropped immediately so path doesn't exist)
88        assert!(!temp_db.base.as_os_str().is_empty());
89    }
90
91    #[test]
92    fn test_default() {
93        let temp_db = TempDB::default();
94        assert!(temp_db.file_name.is_empty());
95        assert!(temp_db.data_path.as_os_str().is_empty());
96    }
97
98    #[test]
99    fn test_backups_path() {
100        let mut temp_db = new();
101        let backups_path = temp_db.backups_path().unwrap();
102        assert!(backups_path.exists());
103        assert!(backups_path.ends_with("backups"));
104
105        // Calling again should return cached path
106        let backups_path2 = temp_db.backups_path().unwrap();
107        assert_eq!(backups_path, backups_path2);
108    }
109
110    #[test]
111    fn test_data_path() {
112        let mut temp_db = new();
113        let data_path = temp_db.data_path().unwrap();
114        assert!(data_path.exists());
115        assert!(data_path.ends_with("data"));
116
117        // Calling again should return cached path
118        let data_path2 = temp_db.data_path().unwrap();
119        assert_eq!(data_path, data_path2);
120    }
121
122    #[test]
123    fn test_file_path() {
124        let mut temp_db = new();
125        let file_path = temp_db.file_path().unwrap();
126        assert!(file_path.to_string_lossy().contains("secrets"));
127
128        // Calling again should return cached path
129        let file_path2 = temp_db.file_path().unwrap();
130        assert_eq!(file_path, file_path2);
131    }
132
133    #[test]
134    fn test_file_name() {
135        let mut temp_db = new();
136        let file_name = temp_db.file_name().unwrap();
137        assert!(!file_name.is_empty());
138        assert!(file_name.contains("secrets"));
139
140        // Calling again should return cached name
141        let file_name2 = temp_db.file_name().unwrap();
142        assert_eq!(file_name, file_name2);
143    }
144
145    #[test]
146    fn test_setup() {
147        let mut temp_db = new();
148        let result = temp_db.setup();
149        assert!(result.is_ok());
150        assert!(temp_db.data_path.exists());
151        assert!(temp_db.backups_path.exists());
152    }
153
154    #[test]
155    fn test_teardown() {
156        let mut temp_db = new();
157        let base_path = temp_db.base.clone();
158        let _ = temp_db.setup();
159        assert!(base_path.exists());
160
161        let result = temp_db.teardown();
162        assert!(result.is_ok());
163        assert!(!base_path.exists());
164    }
165
166    #[test]
167    fn test_clone() {
168        let temp_db1 = new();
169        let temp_db2 = temp_db1.clone();
170        assert_eq!(temp_db1.base, temp_db2.base);
171    }
172}