arduino_report_size_deltas/reports/
mod.rs1use crate::{CommentAssemblyError, JsonError};
7use std::{fs, path::Path};
8pub mod structs;
9use structs::{Report, ReportOld};
10
11pub(crate) fn parse_json<P: AsRef<Path>>(path: P) -> Result<Report, JsonError> {
16 let asset = fs::read_to_string(path)?;
17 match serde_json::from_str::<Report>(&asset) {
18 Ok(report) => Ok(report),
19 Err(e) => {
20 if e.is_data() {
21 match serde_json::from_str::<ReportOld>(&asset) {
24 Ok(report) => Ok(report.into()),
25 Err(e_old) => {
26 eprintln!("Parsing old format failed: {e_old}");
27 Err(JsonError::Serde(e))
28 }
29 }
30 } else {
31 Err(JsonError::Serde(e))
32 }
33 }
34 }
35}
36
37pub fn parse_artifacts<P: AsRef<Path>>(
40 sketches_path: P,
41) -> Result<Vec<Report>, CommentAssemblyError> {
42 let mut reports = vec![];
43 for entry in fs::read_dir(&sketches_path)? {
44 let path = entry?.path();
45 if path.is_dir() {
46 reports.extend(parse_artifacts(path)?);
47 } else if path
48 .extension()
49 .is_some_and(|ext| ext.to_string_lossy() == "json")
50 {
51 let report = parse_json(&path)?;
52 if report.is_valid() {
53 reports.push(report);
54 } else {
55 log::warn!("Skipping {path:?} since it does not contain sufficient information.");
56 }
57 } else {
58 log::debug!("Ignoring non-JSON file: {}", path.to_string_lossy());
59 }
60 }
61 Ok(reports)
62}
63
64#[cfg(test)]
65mod test {
66 use std::io::Write;
67
68 use super::{JsonError, parse_json};
69 use tempfile::NamedTempFile;
70
71 #[test]
73 fn parse_new() {
74 for entry in std::fs::read_dir("tests/size-deltas-reports-new").unwrap() {
75 let path = entry.unwrap().path();
76 if path.extension().unwrap().to_string_lossy() == "json" {
77 println!("Parsing {path:?}");
78 let report = parse_json(&path).unwrap();
79 assert!(!report.boards.is_empty());
80 assert!(report.is_valid());
81 } else {
82 println!("Skipped parsing non-JSON file: {}", path.to_string_lossy());
83 }
84 }
85 }
86
87 #[test]
89 fn parse_old() {
90 for entry in std::fs::read_dir("tests/size-deltas-reports-old").unwrap() {
91 let path = entry.unwrap().path();
92 println!("Parsing {path:?}");
93 let report = parse_json(path).unwrap();
94 assert!(!report.boards.is_empty());
95 assert!(!report.is_valid());
96 }
97 }
98
99 #[test]
100 fn absent_file() {
101 let result = parse_json("not-a-file.json");
102 assert!(result.is_err_and(|e| matches!(e, JsonError::FileReadFail(_))));
103 }
104
105 #[test]
106 fn bad_json() {
107 let bad_asset = NamedTempFile::new().unwrap();
108 let result = parse_json(&bad_asset);
109 assert!(result.is_err_and(|e| matches!(e, JsonError::Serde(_))));
110 }
111
112 #[test]
113 fn bad_report() {
114 let mut bad_asset = NamedTempFile::new().unwrap();
115 bad_asset.write_all("{}".as_bytes()).unwrap();
116 let result = parse_json(&bad_asset);
117 assert!(result.is_err_and(|e| matches!(e, JsonError::Serde(_))));
118 }
119}