phink_lib/cli/ui/monitor/
corpus.rs1use crate::cli::{
2 config::PFiles,
3 ui::traits::FromPath,
4};
5use std::{
6 fs,
7 path::PathBuf,
8 time::UNIX_EPOCH,
9};
10
11#[derive(Clone, Debug)]
12pub struct CorpusWatcher {
13 corpus_folder: PathBuf,
14}
15
16#[derive(Clone, Debug)]
17pub struct PlotEntry {
18 x: f64,
19 y: f64,
20}
21
22impl PlotEntry {
23 pub fn new(x: f64, y: f64) -> PlotEntry {
24 PlotEntry { x, y }
25 }
26}
27
28impl From<PlotEntry> for (f64, f64) {
29 fn from(entry: PlotEntry) -> Self {
30 (entry.x, entry.y)
31 }
32}
33
34impl FromPath for CorpusWatcher {
35 type Output = CorpusWatcher;
36
37 fn create_instance(log_fullpath: PathBuf) -> Self::Output {
38 CorpusWatcher {
39 corpus_folder: log_fullpath,
40 }
41 }
42
43 fn get_filetype() -> PFiles {
44 PFiles::CorpusPath
45 }
46}
47
48impl CorpusWatcher {
49 pub fn as_tuple_slice(&mut self) -> Vec<(f64, f64)> {
50 self.data().iter().map(|entry| (entry.x, entry.y)).collect()
51 }
52
53 pub fn data(&mut self) -> Vec<PlotEntry> {
54 let mut data: Vec<PlotEntry> = Vec::new();
55 if let Ok(entries) = fs::read_dir(&self.corpus_folder) {
56 let mut entries: Vec<_> = entries.filter_map(Result::ok).collect();
57
58 entries.sort_by_key(|entry| entry.metadata().unwrap().created().unwrap());
60
61 for (i, entry) in entries.into_iter().enumerate() {
62 let x = entry
63 .metadata()
64 .unwrap()
65 .created()
66 .unwrap()
67 .duration_since(UNIX_EPOCH)
68 .unwrap()
69 .as_secs_f64();
70
71 data.push(PlotEntry::new(x, i as f64));
72 }
73 }
74
75 data
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use crate::EmptyResult;
83 use std::{
84 fs,
85 io::Write,
86 path::Path,
87 thread::sleep,
88 time::Duration,
89 };
90 use tempfile::{
91 NamedTempFile,
92 TempDir,
93 };
94
95 #[test]
96 fn test_from_fullpath_existing_folder() {
97 let temp_dir = TempDir::new().unwrap();
98 let path = temp_dir.path().to_path_buf();
99
100 let result = CorpusWatcher::from_fullpath(path.clone());
101 assert!(result.is_ok());
102
103 let mut watcher = result.unwrap();
104 assert_eq!(watcher.corpus_folder, path);
105 assert!(watcher.data().is_empty());
106 }
107
108 #[test]
109 fn test_from_fullpath_non_existing_folder() {
110 let non_existing_path = PathBuf::from("/non/existing/path");
111 let result = CorpusWatcher::from_fullpath(non_existing_path);
112 assert!(result.is_err());
113 }
114 #[test]
115 fn test_corpus_watcher_data() -> EmptyResult {
116 let corpus_path = Path::new("tests/fixtures/corpus").to_path_buf();
117
118 let mut watcher = CorpusWatcher::from_fullpath(corpus_path.clone())?;
119
120 let mut temp_file = NamedTempFile::new_in(corpus_path.clone())?;
125 writeln!(temp_file, "just a random seed")?;
126
127 sleep(Duration::from_secs(1)); let data_after_one_file = watcher.data();
129 assert_eq!(data_after_one_file.get(3).unwrap().y, 3f64); let mut temp_file = NamedTempFile::new_in(corpus_path.clone())?;
133 writeln!(temp_file, "just a random seed but again")?;
134
135 sleep(Duration::from_secs(1)); let data_after_one_file = watcher.data();
137 assert_eq!(data_after_one_file.get(2).unwrap().y, 2f64); Ok(())
145 }
146
147 #[test]
148 fn test_from_output_non_existing_folder() {
149 let non_existing_path = PathBuf::from("/non/existing/path");
150 let result = CorpusWatcher::from_output(non_existing_path);
151 assert!(result.is_err());
152 }
153
154 #[test]
155 fn test_data_empty_folder() {
156 let temp_dir = TempDir::new().unwrap();
157 let path = temp_dir.path().to_path_buf();
158
159 let mut watcher = CorpusWatcher::from_fullpath(path).unwrap();
160 let data = watcher.data();
161
162 assert_eq!(data.len(), 0);
163 }
164
165 #[test]
166 fn test_data_non_empty_folder() {
167 let temp_dir = TempDir::new().unwrap();
168 let path = temp_dir.path().to_path_buf();
169
170 fs::File::create(path.join("file1.txt")).unwrap();
172 fs::File::create(path.join("file2.txt")).unwrap();
173
174 let mut watcher = CorpusWatcher::from_fullpath(path).unwrap();
175 let data = watcher.data();
176
177 assert_eq!(data.len(), 2);
178 assert_eq!(data[1].y, 1.0);
179 }
180
181 #[test]
182 fn test_plot_entry_conversion() {
183 let entry = PlotEntry { x: 1.0, y: 2.0 };
184 let tuple: (f64, f64) = entry.into();
185 assert_eq!(tuple, (1.0, 2.0));
186 }
187}