use std::ops::Deref;
use relative_path::RelativePathBuf;
use time::OffsetDateTime;
use crate::{Line, Origin, Properties, Revision, test_runs::TestCaseState};
use super::requirements::ReqId;
pub const REVIEW_DATE_FORMAT: &[time::format_description::BorrowedFormatItem<'static>] = time::macros::format_description!(
"[year]-[month]-[day][first [T] [ ]][hour]:[minute][optional [:[second][optional [.[subsecond]]]]]utc[offset_hour sign:mandatory]"
);
time::serde::format_description!(pub review_date_format, OffsetDateTime, REVIEW_DATE_FORMAT);
pub fn date_from_str(date: &str) -> Result<OffsetDateTime, time::error::Parse> {
OffsetDateTime::parse(date, REVIEW_DATE_FORMAT)
.or_else(|_| super::test_runs::test_date_from_str(date))
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub struct ReviewSchema {
#[serde(serialize_with = "crate::serialize_schema_version")]
pub schema_version: Option<String>,
pub reviews: Vec<Review>,
pub properties: Option<Properties>,
pub origin: Option<Origin>,
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub struct Review {
pub name: String,
#[serde(with = "review_date_format")]
#[schemars(
with = "String",
regex(
pattern = r"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})(T| )(?<hour>\d{2}):(?<minute>\d{2})(?<second>:\d{2}(?<subsecond>\.\d{3})?)?utc(?<utc>(-|+)\d{2})"
)
)]
pub utc_date: OffsetDateTime,
pub authors: Vec<String>,
pub description: Option<String>,
pub origin: Option<Origin>,
pub properties: Option<Properties>,
pub revisions: Option<Vec<Revision>>,
#[serde(alias = "requirement", default)]
pub requirements: Vec<VerifiedRequirementGroup>,
#[serde(alias = "override", default)]
pub test_run_overrides: Vec<OverrideTestRun>,
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(deny_unknown_fields)]
pub struct VerifiedRequirementGroup {
#[serde(alias = "ids")]
pub id: OneOrMultRequirementIds,
pub comment: String,
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(untagged)]
pub enum OneOrMultRequirementIds {
One(ReqId),
Mult(Vec<ReqId>),
}
impl std::fmt::Display for OneOrMultRequirementIds {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self {
OneOrMultRequirementIds::One(req_id) => write!(f, "{}", req_id),
OneOrMultRequirementIds::Mult(req_ids) => {
write!(
f,
"{}",
req_ids
.iter()
.map(|r| r.deref().clone())
.collect::<Vec<String>>()
.join(",")
)
}
}
}
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub struct OverrideTestRun {
pub name: String,
#[serde(with = "time::serde::iso8601")]
#[schemars(with = "String")]
pub utc_date: time::OffsetDateTime,
#[serde(alias = "test", default)]
pub test_cases: Vec<OverrideTestCase>,
#[serde(default)]
pub coverage: Vec<OverrideFileCoverage>,
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(deny_unknown_fields)]
pub struct OverrideTestCase {
pub name: String,
pub state: Option<OverrideTestCaseState>,
#[serde(default)]
pub coverage: Vec<OverrideFileCoverage>,
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(deny_unknown_fields)]
pub struct OverrideTestCaseState {
pub new: TestCaseState,
pub comment: String,
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(deny_unknown_fields)]
pub struct OverrideFileCoverage {
#[schemars(with = "String")]
pub filepath: RelativePathBuf,
#[serde(default)]
pub lines: Vec<OverrideCoveredLineInfo>,
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, schemars::JsonSchema,
)]
#[serde(deny_unknown_fields)]
pub struct OverrideCoveredLineInfo {
#[serde(alias = "nr")]
pub nrs: Vec<Line>,
pub hits: Option<i64>,
pub comment: String,
}