phink_lib/cli/ui/
logger.rs1use crate::{
2 cli::config::{
3 PFiles,
4 PhinkFiles,
5 },
6 cover::coverage::InputCoverage,
7 fuzzer::parser::OneInput,
8};
9use std::{
10 fs::{
11 File,
12 OpenOptions,
13 },
14 io,
15 io::{
16 BufReader,
17 BufWriter,
18 Read,
19 Write,
20 },
21 path::PathBuf,
22 time::{
23 SystemTime,
24 UNIX_EPOCH,
25 },
26};
27
28pub const LAST_SEED_FILENAME: &str = "last_seed.phink";
29
30pub struct LogWriter {
31 input: OneInput,
32 coverage: InputCoverage,
33}
34
35impl LogWriter {
36 pub fn new(input: OneInput, coverage: InputCoverage) -> Self {
37 LogWriter { input, coverage }
38 }
39
40 pub fn should_save() -> bool {
41 SystemTime::now()
42 .duration_since(UNIX_EPOCH)
43 .unwrap()
44 .as_secs()
45 % 2
46 == 0
47 }
48
49 pub fn save(&self, output: PathBuf) -> io::Result<()> {
50 let file = OpenOptions::new()
51 .create(true)
52 .write(true)
53 .truncate(true)
54 .open(PhinkFiles::new(output).path(PFiles::LastSeed))?;
55 let mut writer = BufWriter::new(file);
56
57 let input = &self.input;
58 writeln!(
59 writer,
60 "Got {} coverage size with {} message.s {:?}\nBytes: 0x{}\n",
61 self.coverage.coverage_len(),
62 input.messages.len(),
63 self.coverage.messages_coverage(),
64 hex::encode(&input.raw_binary)
65 )?;
66
67 for message in input.messages.iter() {
68 writeln!(writer, "{}", message.print())?;
69 }
70
71 writer.flush()?;
72 Ok(())
73 }
74}
75
76pub struct LogDisplayer {
77 output: PathBuf,
78}
79
80impl LogDisplayer {
81 pub fn new(output: PathBuf) -> Self {
82 Self { output }
83 }
84 pub fn load(&self) -> Option<String> {
85 let buf = PhinkFiles::new(self.output.clone()).path(PFiles::LastSeed);
86 let maybe_file = File::open(buf.clone());
87 if let Ok(file) = maybe_file {
88 return Some(Self::parse(file))
89 }
90 None
91 }
92
93 fn parse(file: File) -> String {
94 let mut contents = String::new();
95
96 BufReader::new(file)
97 .read_to_string(&mut contents)
98 .expect("Failed to read file");
99
100 contents
101 }
102}
103#[cfg(test)]
104mod tests {
105 use super::*;
106 #[test]
107 fn test_seed_displayer_load() {
108 let logger_display = LogDisplayer::new(PathBuf::from("tests/fixtures"));
109 let seeds = logger_display.load().unwrap();
110 assert!(seeds.contains("crash_with_invariant"));
111 }
112}