1use relative_path::RelativePathBuf;
2
3use crate::{
4 ConversionError, FmtHash,
5 report::{
6 Aggregated, annotations::TraceReference, requirement::RequirementReference,
7 test_case::TestCaseReference, test_run::TestRunReference,
8 },
9};
10
11#[derive(
12 Debug,
13 Clone,
14 Copy,
15 Default,
16 PartialEq,
17 serde::Serialize,
18 serde::Deserialize,
19 schemars::JsonSchema,
20)]
21#[serde(rename_all = "snake_case")]
22pub struct TestsSummary {
23 pub total: i64,
24 pub passed: Aggregated,
25 pub failed: Aggregated,
26 pub skipped: Aggregated,
27 pub unknown: Aggregated,
28 pub obsolete: Aggregated,
29}
30
31impl TestsSummary {
32 pub fn add(&mut self, other: &Self) {
33 self.total += other.total;
34
35 self.passed.cnt += other.passed.cnt;
36 self.failed.cnt += other.failed.cnt;
37 self.skipped.cnt += other.skipped.cnt;
38 self.unknown.cnt += other.unknown.cnt;
39 self.obsolete.cnt += other.obsolete.cnt;
40
41 self.update_percentages();
42 }
43
44 pub fn update_percentages(&mut self) {
45 self.passed.update_percentage(self.total);
46 self.failed.update_percentage(self.total);
47 self.skipped.update_percentage(self.total);
48 self.unknown.update_percentage(self.total);
49 self.obsolete.update_percentage(self.total);
50 }
51}
52
53#[derive(
55 Debug,
56 Clone,
57 Copy,
58 PartialEq,
59 Eq,
60 Hash,
61 serde::Serialize,
62 serde::Deserialize,
63 schemars::JsonSchema,
64)]
65#[serde(rename_all = "snake_case")]
66pub enum TestState {
67 Failed = 0,
69 Passed = 1,
71 Skipped = 2,
73 Unknown = 3,
79 Obsolete = 4,
83}
84
85impl TestState {
86 pub fn as_nr(&self) -> i32 {
87 *self as i32
88 }
89}
90
91impl TryFrom<i64> for TestState {
92 type Error = ConversionError;
93
94 fn try_from(value: i64) -> Result<Self, Self::Error> {
95 if value == TestState::Failed.as_nr() as i64 {
96 Ok(TestState::Failed)
97 } else if value == TestState::Skipped.as_nr() as i64 {
98 Ok(TestState::Skipped)
99 } else if value == TestState::Passed.as_nr() as i64 {
100 Ok(TestState::Passed)
101 } else if value == TestState::Unknown.as_nr() as i64 {
102 Ok(TestState::Unknown)
103 } else if value == TestState::Obsolete.as_nr() as i64 {
104 Ok(TestState::Obsolete)
105 } else {
106 Err(ConversionError::UnknownState)
107 }
108 }
109}
110
111#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
112#[serde(rename_all = "snake_case")]
113pub struct TestCoverage {
114 pub summary: TestCoverageSummary,
115 pub covered_files: Vec<TestCoveredFile>,
116 pub covered_traces: Option<Vec<TraceReference>>,
117}
118
119#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
120#[serde(rename_all = "snake_case")]
121pub struct TestCoveredFile {
122 #[schemars(with = "Vec<String>")]
123 pub filepath: RelativePathBuf,
124 pub file_hash: Option<FmtHash>,
125}
126
127#[derive(
128 Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
129)]
130#[serde(rename_all = "snake_case")]
131pub struct TestCoverageSummary {
132 pub lines: CoverageSummary,
133}
134
135#[derive(
136 Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
137)]
138#[serde(rename_all = "snake_case")]
139pub struct CoverageSummary {
140 pub total: i64,
141 pub covered: Aggregated,
142 pub excluded: Aggregated,
143 pub overridden_covered: Aggregated,
144 pub overridden_uncovered: Aggregated,
145 pub uncovered: Aggregated,
146}
147
148impl CoverageSummary {
149 pub fn add(&mut self, other: &Self) {
150 self.total += other.total;
151
152 self.covered.cnt += other.covered.cnt;
153 self.excluded.cnt += other.excluded.cnt;
154 self.overridden_covered.cnt += other.overridden_covered.cnt;
155 self.overridden_uncovered.cnt += other.overridden_uncovered.cnt;
156 self.uncovered.cnt += other.uncovered.cnt;
157
158 self.update_percentages();
159 }
160
161 pub fn update_percentages(&mut self) {
162 self.covered.update_percentage(self.total);
163 self.excluded.update_percentage(self.total);
164 self.overridden_covered.update_percentage(self.total);
165 self.overridden_uncovered.update_percentage(self.total);
166 self.uncovered.update_percentage(self.total);
167 }
168}
169
170#[derive(
171 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
172)]
173pub struct TestRelatedRequirement {
174 pub req: RequirementReference,
175 pub kind: TestRelatedRequirementKind,
176}
177
178#[derive(
179 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
180)]
181#[serde(rename_all = "snake_case")]
182pub enum TestRelatedRequirementKind {
183 Direct,
184 Traced(Vec<TraceReference>),
185}
186
187#[derive(
188 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
189)]
190#[serde(rename_all = "snake_case")]
191pub enum TestReference {
192 TestRun(TestRunReference),
193 TestCase(TestCaseReference),
194}
195
196#[derive(
197 Debug,
198 Clone,
199 Copy,
200 PartialEq,
201 Eq,
202 Hash,
203 serde::Serialize,
204 serde::Deserialize,
205 schemars::JsonSchema,
206)]
207#[serde(rename_all = "snake_case")]
208pub enum ResolvedLineCoverageState {
209 Covered = 0,
210 Excluded = 1,
211 OverriddenCovered = 2,
212 OverriddenUncovered = 3,
213 Uncovered = 4,
214}
215
216impl ResolvedLineCoverageState {
217 pub fn as_nr(&self) -> i32 {
218 *self as i32
219 }
220}
221
222impl TryFrom<i64> for ResolvedLineCoverageState {
223 type Error = ConversionError;
224
225 fn try_from(value: i64) -> Result<Self, Self::Error> {
226 if value == ResolvedLineCoverageState::Covered.as_nr() as i64 {
227 Ok(ResolvedLineCoverageState::Covered)
228 } else if value == ResolvedLineCoverageState::Excluded.as_nr() as i64 {
229 Ok(ResolvedLineCoverageState::Excluded)
230 } else if value == ResolvedLineCoverageState::OverriddenCovered.as_nr() as i64 {
231 Ok(ResolvedLineCoverageState::OverriddenCovered)
232 } else if value == ResolvedLineCoverageState::OverriddenUncovered.as_nr() as i64 {
233 Ok(ResolvedLineCoverageState::OverriddenUncovered)
234 } else if value == ResolvedLineCoverageState::Uncovered.as_nr() as i64 {
235 Ok(ResolvedLineCoverageState::Uncovered)
236 } else {
237 Err(ConversionError::UnknownState)
238 }
239 }
240}