Skip to main content

mantra_schema/report/
review.rs

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    /// The schema version.
20    /// [req("exchange.versioned")]
21    #[serde(serialize_with = "crate::serialize_schema_version")]
22    pub schema_version: Option<String>,
23    pub product: ProductMetadata,
24    /// The name of the review.
25    /// [req("review.id")]
26    pub name: String,
27    /// The UTC date and time the review was started.
28    /// [req("review.id")]
29    #[serde(with = "time::serde::iso8601")]
30    #[schemars(with = "String")]
31    pub utc_date: time::OffsetDateTime,
32    pub state: ReviewState,
33    /// The authors that were part of the review.
34    /// [req("review.authors")]
35    pub authors: Vec<String>,
36    /// Optional description of the review.
37    /// [req("review.description")]
38    pub description: Option<String>,
39    /// Optional origin of the review.
40    /// [req("review.origin")]
41    pub origin: Option<Origin>,
42    pub base_origin: Option<Origin>,
43    /// Optional properties related to this review.
44    pub properties: Option<Properties>,
45    /// Optional revisions for the review.
46    pub revisions: Option<Vec<Revision>>,
47    /// List of requirements that are verified in this review.
48    /// [req("review.verify_req")]
49    pub requirements: Option<Vec<VerifiedRequirement>>,
50    /// List of test run overrides added with this review.
51    /// [req("review.test_case_state", "review.coverage")]
52    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/// Represents a test case state override in a review.
218/// [req("review.test_case_state", "review.coverage")]
219#[derive(
220    Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
221)]
222pub struct ResolvedOverrideTestCase {
223    /// Name of the test case whose state and/or related code coverage is overridden in a review.
224    pub test_case: TestCaseReference,
225    pub state: Option<ResolvedOverrideTestCaseState>,
226    pub coverage: Option<Vec<ResolvedOverrideFileCoverage>>,
227}
228
229/// Represents a test case state override in a review.
230/// [req("review.test_case_state")]
231#[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}