1use relative_path::RelativePathBuf;
2use time::OffsetDateTime;
3
4use crate::{
5 ConversionError, Line, Origin, Properties, REVIEWS_FOLDER_NAME, Revision,
6 encoding::TargetEncoding,
7 product::ProductId,
8 report::{
9 product::ProductMetadata, requirement::RequirementReference, test_case::TestCaseReference,
10 test_run::TestRunReference,
11 },
12 requirements::ReqId,
13 test_runs::TestCaseState,
14};
15
16#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
17#[serde(rename_all = "snake_case")]
18pub struct ReviewReportSchema {
19 #[serde(serialize_with = "crate::serialize_schema_version")]
22 pub schema_version: Option<String>,
23 pub product: ProductMetadata,
24 pub name: String,
27 #[serde(with = "time::serde::iso8601")]
30 #[schemars(with = "String")]
31 pub utc_date: time::OffsetDateTime,
32 pub state: ReviewState,
33 pub authors: Vec<String>,
36 pub description: Option<String>,
39 pub origin: Option<Origin>,
42 pub base_origin: Option<Origin>,
43 pub properties: Option<Properties>,
45 pub revisions: Option<Vec<Revision>>,
47 pub requirements: Option<Vec<VerifiedRequirement>>,
50 pub test_run_overrides: Option<Vec<ResolvedOverrideTestRun>>,
53 pub ignored_entries: Option<IgnoredEntries>,
54}
55
56#[derive(
57 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
58)]
59#[serde(rename_all = "snake_case")]
60pub struct VerifiedRequirement {
61 pub req: RequirementReference,
62 pub comment: String,
63}
64
65#[derive(
66 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
67)]
68#[serde(rename_all = "snake_case")]
69pub struct IgnoredEntries {
70 pub total: i64,
71 pub requirements: Option<Vec<IgnoredManualRequirementVerification>>,
72 pub test_case_state_overrides: Option<Vec<IgnoredTestCaseStateOverride>>,
73 pub test_case_line_coverage_overrides: Option<Vec<IgnoredTestCaseLineCoverageOverride>>,
74 pub test_run_line_coverage_overrides: Option<Vec<IgnoredTestRunLineCoverageOverride>>,
75}
76
77#[derive(
78 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
79)]
80#[serde(rename_all = "snake_case")]
81pub struct IgnoredManualRequirementVerification {
82 pub id: ReqId,
83 pub comment: String,
84}
85
86#[derive(
87 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
88)]
89#[serde(rename_all = "snake_case")]
90pub struct IgnoredTestCaseStateOverride {
91 pub test_run_name: String,
92 #[serde(with = "time::serde::iso8601")]
93 #[schemars(with = "String")]
94 pub test_run_date: OffsetDateTime,
95 pub test_case_name: String,
96 pub state: TestCaseState,
97 pub comment: String,
98}
99
100#[derive(
101 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
102)]
103#[serde(rename_all = "snake_case")]
104pub struct IgnoredTestCaseLineCoverageOverride {
105 pub test_run_name: String,
106 #[serde(with = "time::serde::iso8601")]
107 #[schemars(with = "String")]
108 pub test_run_date: OffsetDateTime,
109 pub test_case_name: String,
110 #[schemars(with = "String")]
111 pub cov_filepath: RelativePathBuf,
112 pub cov_line: Line,
113 pub hits: Option<i64>,
114 pub comment: String,
115}
116
117#[derive(
118 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
119)]
120#[serde(rename_all = "snake_case")]
121pub struct IgnoredTestRunLineCoverageOverride {
122 pub test_run_name: String,
123 #[serde(with = "time::serde::iso8601")]
124 #[schemars(with = "String")]
125 pub test_run_date: OffsetDateTime,
126 #[schemars(with = "String")]
127 pub cov_filepath: RelativePathBuf,
128 pub cov_line: Line,
129 pub hits: Option<i64>,
130 pub comment: String,
131}
132
133#[derive(
134 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
135)]
136#[serde(rename_all = "snake_case")]
137pub struct ReviewReference {
138 pub product_id: ProductId,
139 pub name: String,
140 #[serde(with = "time::serde::iso8601")]
141 #[schemars(with = "String")]
142 pub utc_date: time::OffsetDateTime,
143 pub state: ReviewState,
144}
145
146impl ReviewReference {
147 pub fn url_path(&self) -> RelativePathBuf {
148 self.encode_path(TargetEncoding::Url)
149 }
150
151 pub fn os_path(&self) -> RelativePathBuf {
152 self.encode_path(TargetEncoding::Os)
153 }
154
155 fn encode_path(&self, target: TargetEncoding) -> RelativePathBuf {
156 let product_path = match target {
157 TargetEncoding::Os => self.product_id.os_path(),
158 TargetEncoding::Url => self.product_id.url_path(),
159 };
160
161 let limit_name = crate::encoding::limit_str_len(&self.name);
162 let encoded_ref = format!(
163 "{}_{}",
164 super::encode_utc_date(&self.utc_date),
165 crate::encoding::encode(&limit_name, target)
166 );
167
168 product_path.join(REVIEWS_FOLDER_NAME).join(encoded_ref)
169 }
170}
171
172#[derive(
173 Debug,
174 Clone,
175 Copy,
176 PartialEq,
177 Eq,
178 Hash,
179 serde::Serialize,
180 serde::Deserialize,
181 schemars::JsonSchema,
182)]
183#[serde(rename_all = "snake_case")]
184pub enum ReviewState {
185 Obsolete = 0,
186 Valid = 1,
187}
188
189impl ReviewState {
190 pub fn as_nr(&self) -> i32 {
191 *self as i32
192 }
193}
194
195impl TryFrom<i64> for ReviewState {
196 type Error = ConversionError;
197
198 fn try_from(value: i64) -> Result<Self, Self::Error> {
199 match value {
200 0 => Ok(ReviewState::Obsolete),
201 1 => Ok(ReviewState::Valid),
202 _ => Err(ConversionError::UnknownState),
203 }
204 }
205}
206
207#[derive(
208 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
209)]
210#[serde(rename_all = "snake_case")]
211pub struct ResolvedOverrideTestRun {
212 pub test_run: TestRunReference,
213 pub test_cases: Option<Vec<ResolvedOverrideTestCase>>,
214 pub coverage: Option<Vec<ResolvedOverrideFileCoverage>>,
215}
216
217#[derive(
220 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
221)]
222pub struct ResolvedOverrideTestCase {
223 pub test_case: TestCaseReference,
225 pub state: Option<ResolvedOverrideTestCaseState>,
226 pub coverage: Option<Vec<ResolvedOverrideFileCoverage>>,
227}
228
229#[derive(
232 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
233)]
234pub struct ResolvedOverrideTestCaseState {
235 pub old: TestCaseState,
236 pub new: TestCaseState,
237 pub comment: String,
238}
239
240#[derive(
241 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
242)]
243pub struct ResolvedOverrideFileCoverage {
244 #[schemars(with = "String")]
245 pub filepath: RelativePathBuf,
246 pub lines: Vec<ResolvedOverrideCoveredLineInfo>,
247}
248
249#[derive(
250 Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
251)]
252pub struct ResolvedOverrideCoveredLineInfo {
253 pub nr: Line,
254 pub old_hits: Option<i64>,
255 pub new_hits: Option<i64>,
256 pub comment: String,
257}