cargo_coverage_gate/
error.rs1use serde_json::Value;
18
19#[ohno::error]
30#[from(
31 LoadMetadataError,
32 InvalidThresholdValueError,
33 ThresholdOutOfRangeError,
34 ParseLcovError,
35 ReadLcovError,
36 UnknownPackageSelectorError
37)]
38pub struct CoverageGateError;
39
40#[ohno::error]
42#[display("failed to load workspace metadata")]
43#[from(cargo_metadata::Error)]
44pub(crate) struct LoadMetadataError;
45
46#[ohno::error]
49#[display("{source}: `coverage-gate.min-lines-percent` must be a number, got {min}")]
50pub(crate) struct InvalidThresholdValueError {
51 pub source: String,
52 pub min: Value,
53}
54
55#[ohno::error]
58#[display(
59 "invalid coverage-gate min-lines-percent value `{value}` for {source}: \
60 expected a value in {lower:.1}..={upper:.1}"
61)]
62pub(crate) struct ThresholdOutOfRangeError {
63 pub source: String,
64 pub value: f64,
65 pub lower: f64,
66 pub upper: f64,
67}
68
69#[ohno::error]
71#[display("lcov tracefile is not well-formed")]
72#[from(lcov::report::ParseError)]
73pub(crate) struct ParseLcovError;
74
75#[ohno::error]
78#[display("failed to read lcov tracefile `{path}`")]
79pub(crate) struct ReadLcovError {
80 pub path: String,
81}
82
83#[ohno::error]
85#[display("`--package` selector `{selector}` did not match any workspace member")]
86pub(crate) struct UnknownPackageSelectorError {
87 pub selector: String,
88}
89
90#[cfg(test)]
91#[cfg_attr(coverage_nightly, coverage(off))]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn umbrella_propagates_load_metadata_chain() {
97 let inner = LoadMetadataError::caused_by(std::io::Error::other("no manifest"));
98 let outer: CoverageGateError = inner.into();
99 let rendered = outer.to_string();
100 assert!(rendered.contains("failed to load workspace metadata"));
101 assert!(rendered.contains("no manifest"));
102 }
103
104 #[test]
105 fn umbrella_propagates_parse_lcov() {
106 let inner = ParseLcovError::new();
107 let outer: CoverageGateError = inner.into();
108 let rendered = outer.to_string();
109 assert!(rendered.contains("lcov tracefile"));
110 }
111
112 #[test]
113 fn unknown_package_selector_carries_pattern() {
114 let err = UnknownPackageSelectorError::new("nope-*".to_owned());
115 let rendered = err.to_string();
116 assert!(rendered.contains("nope-*"));
117 assert!(rendered.contains("did not match"));
118 }
119
120 #[test]
121 fn threshold_out_of_range_renders_value_and_bounds() {
122 let err = ThresholdOutOfRangeError::new("alpha".to_owned(), 150.0, 0.0, 100.0);
123 let rendered = err.to_string();
124 assert!(rendered.contains("150"));
125 assert!(rendered.contains("alpha"));
126 assert!(rendered.contains("0.0..=100.0"));
127 }
128}