Skip to content

Commit 2d99a2b

Browse files
committed
Rearrange run result struct, add subresult codenames/severity
1 parent 423b231 commit 2d99a2b

File tree

12 files changed

+282
-184
lines changed

12 files changed

+282
-184
lines changed

fontspector-checkapi/src/check.rs

+63-32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
context::Context, font::FontCollection, prelude::FixFnResult, status::CheckFnResult, Registry,
3-
Status, Testable,
3+
Status, StatusCode, Testable,
44
};
55

66
pub type CheckId = String;
@@ -23,12 +23,35 @@ pub struct Check<'a> {
2323
// Are we? Really? I don't know. Let's find out...
2424
unsafe impl Sync for Check<'_> {}
2525

26+
#[derive(Debug, Clone)]
2627
pub struct CheckResult {
27-
pub status: Status,
2828
pub check_id: CheckId,
2929
pub check_name: String,
3030
pub check_rationale: String,
3131
pub filename: Option<String>,
32+
pub section: String,
33+
pub subresults: Vec<Status>,
34+
}
35+
36+
impl CheckResult {
37+
fn new(check: &Check, filename: Option<&str>, section: &str, subresults: Vec<Status>) -> Self {
38+
Self {
39+
check_id: check.id.to_string(),
40+
check_name: check.title.to_string(),
41+
check_rationale: check.rationale.to_string(),
42+
filename: filename.map(|x| x.to_string()),
43+
section: section.to_string(),
44+
subresults,
45+
}
46+
}
47+
48+
pub fn worst_status(&self) -> StatusCode {
49+
self.subresults
50+
.iter()
51+
.map(|x| x.severity)
52+
.max()
53+
.unwrap_or(StatusCode::Pass)
54+
}
3255
}
3356

3457
impl<'a> Check<'a> {
@@ -39,40 +62,48 @@ impl<'a> Check<'a> {
3962
.map_or(false, |ft| ft.applies(f))
4063
}
4164

42-
fn status_to_result(&'a self, status: Status, file: Option<&'a Testable>) -> CheckResult {
43-
CheckResult {
44-
status,
45-
check_id: self.id.to_string(),
46-
check_name: self.title.to_string(),
47-
check_rationale: self.rationale.to_string(),
48-
filename: file.map(|x| x.filename.clone()),
49-
}
65+
fn status_to_result(
66+
&'a self,
67+
subresults: Vec<Status>,
68+
file: Option<&'a Testable>,
69+
section: &str,
70+
) -> CheckResult {
71+
CheckResult::new(
72+
&self,
73+
file.map(|f| f.filename.as_ref()),
74+
section,
75+
subresults,
76+
)
5077
}
5178

52-
pub fn run_one(&'a self, f: &'a Testable, context: &Context) -> Vec<CheckResult> {
53-
if let Some(check_one) = self.check_one {
54-
match check_one(f, context) {
55-
Ok(results) => results.map(|r| self.status_to_result(r, Some(f))).collect(),
56-
Err(e) => {
57-
vec![self.status_to_result(Status::error(&format!("Error: {}", e)), Some(f))]
58-
}
59-
}
60-
} else {
61-
vec![]
62-
}
79+
pub fn run_one(
80+
&'a self,
81+
f: &'a Testable,
82+
context: &Context,
83+
section: &str,
84+
) -> Option<CheckResult> {
85+
self.check_one.map(|check_one| {
86+
let subresults = match check_one(f, context) {
87+
Ok(results) => results.collect::<Vec<_>>(),
88+
Err(e) => vec![Status::error(&format!("Error: {}", e))],
89+
};
90+
self.status_to_result(subresults, Some(f), section)
91+
})
6392
}
6493

65-
pub fn run_all(&'a self, f: &'a FontCollection, context: &Context) -> Vec<CheckResult> {
66-
if let Some(check_all) = self.check_all {
67-
match check_all(f, context) {
68-
Ok(results) => results.map(|r| self.status_to_result(r, None)).collect(),
69-
Err(e) => {
70-
vec![self.status_to_result(Status::error(&format!("Error: {}", e)), None)]
71-
}
72-
}
73-
} else {
74-
vec![]
75-
}
94+
pub fn run_all(
95+
&'a self,
96+
f: &'a FontCollection,
97+
context: &Context,
98+
section: &str,
99+
) -> Option<CheckResult> {
100+
self.check_all.map(|check_all| {
101+
let subresults = match check_all(f, context) {
102+
Ok(results) => results.collect::<Vec<_>>(),
103+
Err(e) => vec![Status::error(&format!("Error: {}", e))],
104+
};
105+
self.status_to_result(subresults, None, section)
106+
})
76107
}
77108
}
78109

fontspector-checkapi/src/status.rs

+26-17
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,16 @@ impl std::fmt::Display for StatusCode {
3333
#[derive(Debug, Clone)]
3434
pub struct Status {
3535
pub message: Option<String>,
36-
pub code: StatusCode,
36+
pub severity: StatusCode,
37+
pub code: Option<String>,
3738
}
3839

3940
impl std::fmt::Display for Status {
4041
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41-
write!(f, "**{:}**", self.code)?;
42+
write!(f, "**{:}**: ", self.severity)?;
43+
if let Some(code) = self.code.as_ref() {
44+
write!(f, "[{}]", code)?;
45+
}
4246
if let Some(message) = self.message.as_ref() {
4347
write!(f, ": {:}", message)?;
4448
}
@@ -51,38 +55,43 @@ impl Status {
5155
Box::new(vec![Status::pass()].into_iter())
5256
}
5357

54-
pub fn just_one_fail(s: &str) -> Box<dyn Iterator<Item = Status>> {
55-
Box::new(vec![Status::fail(s)].into_iter())
58+
pub fn just_one_fail(code: &str, message: &str) -> Box<dyn Iterator<Item = Status>> {
59+
Box::new(vec![Status::fail(code, message)].into_iter())
5660
}
5761

5862
pub fn pass() -> Self {
5963
Self {
6064
message: None,
61-
code: StatusCode::Pass,
65+
code: None,
66+
severity: StatusCode::Pass,
6267
}
6368
}
64-
pub fn fail(s: &str) -> Self {
69+
pub fn fail(code: &str, message: &str) -> Self {
6570
Self {
66-
message: Some(s.to_string()),
67-
code: StatusCode::Fail,
71+
message: Some(message.to_string()),
72+
code: Some(code.to_string()),
73+
severity: StatusCode::Fail,
6874
}
6975
}
70-
pub fn skip(s: &str) -> Self {
76+
pub fn skip(code: &str, message: &str) -> Self {
7177
Self {
72-
message: Some(s.to_string()),
73-
code: StatusCode::Skip,
78+
message: Some(message.to_string()),
79+
code: Some(code.to_string()),
80+
severity: StatusCode::Skip,
7481
}
7582
}
76-
pub fn info(s: &str) -> Self {
83+
pub fn info(code: &str, message: &str) -> Self {
7784
Self {
78-
message: Some(s.to_string()),
79-
code: StatusCode::Info,
85+
message: Some(message.to_string()),
86+
code: Some(code.to_string()),
87+
severity: StatusCode::Info,
8088
}
8189
}
82-
pub fn error(s: &str) -> Self {
90+
pub fn error(message: &str) -> Self {
8391
Self {
84-
message: Some(s.to_string()),
85-
code: StatusCode::Error,
92+
message: Some(message.to_string()),
93+
code: None,
94+
severity: StatusCode::Error,
8695
}
8796
}
8897
}

fontspector-cli/src/main.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@ mod reporters;
66

77
use args::Args;
88
use clap::Parser;
9-
use fontspector_checkapi::{Check, Context, Plugin, Registry, Testable};
9+
use fontspector_checkapi::{Check, CheckResult, Context, Plugin, Registry, Testable};
1010
use indicatif::ParallelProgressIterator;
1111
use profile_googlefonts::GoogleFonts;
1212
use profile_universal::Universal;
1313
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
14-
use reporters::{
15-
json::JsonReporter, organize, summary_results, terminal::TerminalReporter, worst_status,
16-
Reporter, RunResults,
17-
};
14+
use reporters::{json::JsonReporter, terminal::TerminalReporter, Reporter, RunResults};
1815
use serde_json::Map;
1916

2017
/// Filter out checks that don't apply
@@ -138,13 +135,13 @@ fn main() {
138135
let results: RunResults = checkorder
139136
.par_iter()
140137
.progress()
141-
.map(|(sectionname, testable, check, context)| {
142-
(sectionname, testable, check.run_one(testable, context))
138+
.flat_map(|(sectionname, testable, check, context)| {
139+
check.run_one(testable, context, sectionname)
143140
})
144-
.collect();
141+
.collect::<Vec<CheckResult>>()
142+
.into();
145143

146-
let worst_status = worst_status(&results);
147-
let organised_results = organize(results);
144+
let worst_status = results.worst_status();
148145

149146
let mut reporters: Vec<Box<dyn Reporter>> = vec![];
150147
if !args.quiet {
@@ -155,12 +152,12 @@ fn main() {
155152
}
156153

157154
for reporter in reporters {
158-
reporter.report(&organised_results, &args, &registry);
155+
reporter.report(&results, &args, &registry);
159156
}
160157

161158
if !args.quiet {
162159
// Summary report
163-
let summary = summary_results(&organised_results);
160+
let summary = results.summary();
164161
print!("\nSummary:\n ");
165162
for (status, count) in summary.iter() {
166163
print!("{:}: {:} ", status, count);

fontspector-cli/src/reporters/json.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::reporters::{summary_results, OrganisedResults, Reporter};
1+
use crate::reporters::{Reporter, RunResults};
22
use crate::Args;
33
use fontspector_checkapi::Registry;
44
use serde_json::{json, Map};
@@ -14,8 +14,9 @@ impl JsonReporter {
1414
}
1515
}
1616
impl Reporter for JsonReporter {
17-
fn report(&self, organised_results: &OrganisedResults, _args: &Args, _registry: &Registry) {
18-
let summary = summary_results(organised_results);
17+
fn report(&self, results: &RunResults, _args: &Args, _registry: &Registry) {
18+
let summary = results.summary();
19+
let organised_results = results.organize();
1920
let mut results = Map::new();
2021
for (testable, sectionresults) in organised_results.iter() {
2122
let mut testable_result = Map::new();
@@ -29,14 +30,22 @@ impl Reporter for JsonReporter {
2930
"check_id": r.check_id,
3031
"check_name": r.check_name,
3132
"check_rationale": r.check_rationale,
32-
"status": r.status.code,
33-
"status_message": r.status.message,
33+
"subresults": r.subresults
34+
.iter()
35+
.map(|r| {
36+
json!({
37+
"status": r.severity.to_string(),
38+
"code": r.code,
39+
"status_message": r.message,
40+
})
41+
})
42+
.collect::<Vec<_>>(),
3443
})
3544
})
3645
.collect(),
3746
);
3847
}
39-
results.insert(testable.filename.clone(), testable_result.into());
48+
results.insert(testable.clone(), testable_result.into());
4049
}
4150
let output = json!({
4251
"summary": summary,

0 commit comments

Comments
 (0)