1use std::collections::BTreeMap;
8use std::path::PathBuf;
9
10use serde::{Deserialize, Serialize};
11
12use crate::model::serde_util::{is_false, is_zero};
13
14use crate::app_src::AppSrcSpec;
15use crate::model::names::{ApplicationName, ModuleName};
16
17#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
20#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
21pub struct SuiteRef {
22 pub application: ApplicationName,
23 pub module: ModuleName,
24 pub path: PathBuf,
25}
26
27#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
30#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31#[serde(tag = "kind", rename_all = "snake_case")]
32pub enum SuiteInclusionReason {
33 TestModified { path: PathBuf },
35 UnitOrPropSweep {
39 application: ApplicationName,
40 triggering_modules: Vec<ModuleName>,
41 },
42 SameAppCaller {
45 application: ApplicationName,
46 module: ModuleName,
47 },
48 CrossAppCaller {
51 library_application: ApplicationName,
52 module: ModuleName,
53 },
54 ConfiguredRule {
56 rule_name: String,
57 triggering_path: PathBuf,
58 },
59 BehaviourImplementerSweep {
62 behaviour: ModuleName,
63 implementer: ModuleName,
64 },
65}
66
67#[derive(Debug, Clone, Default)]
70pub struct PlanInput {
71 pub repo_root: PathBuf,
72 pub modified_paths: Vec<PathBuf>,
73 pub apps: Vec<AppSrcSpec>,
74 pub library_apps: Vec<ApplicationName>,
75 pub extra_rules: Vec<ExtraRule>,
76 pub implementer_index: BTreeMap<ModuleName, Vec<ModuleName>>,
81 pub dep_module_index: BTreeMap<String, Vec<ModuleName>>,
82}
83
84#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
86#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
87pub struct SuitePlanEntry {
88 pub suite: SuiteRef,
89 pub reasons: Vec<SuiteInclusionReason>,
90}
91
92#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
97#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
98pub struct UncoveredApplication {
99 pub application: ApplicationName,
100 pub modified_modules: usize,
101 pub discovered_suites: usize,
102 pub suites: Vec<ModuleName>,
105}
106
107#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
112#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
113pub struct BroadImpactModule {
114 pub module: ModuleName,
115 #[serde(default, skip_serializing_if = "Option::is_none")]
116 pub application: Option<ApplicationName>,
117 pub suite_fanout: usize,
118 pub total_suites: usize,
119}
120
121#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
124#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
125pub struct SuitePlan {
126 pub entries: Vec<SuitePlanEntry>,
127 #[serde(default, skip_serializing_if = "Vec::is_empty")]
128 pub uncovered: Vec<UncoveredApplication>,
129 #[serde(default, skip_serializing_if = "is_zero")]
132 pub unattributed_paths: usize,
133 #[serde(default, skip_serializing_if = "Vec::is_empty")]
136 pub broad_impact: Vec<BroadImpactModule>,
137}
138
139impl SuitePlan {
140 pub fn is_empty(&self) -> bool {
141 self.entries.is_empty()
142 }
143
144 pub fn len(&self) -> usize {
145 self.entries.len()
146 }
147}
148
149#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
155pub struct ExtraRule {
156 pub name: String,
157 pub trigger: ExtraRuleTrigger,
158 #[serde(default)]
159 pub include_suites: Vec<SuiteRefSpec>,
160 #[serde(default)]
161 pub include_suite_templates: Vec<String>,
162 #[serde(default, skip_serializing_if = "Option::is_none")]
163 pub line_match: Option<LineMatch>,
164 #[serde(default, skip_serializing_if = "is_false")]
165 pub include_suite_for_dep_modules: bool,
166}
167
168#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
169pub struct LineMatch {
170 pub pattern: String,
171 #[serde(default)]
172 pub captures: Vec<String>,
173}
174
175#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
179#[serde(tag = "kind", rename_all = "snake_case")]
180#[allow(clippy::enum_variant_names)]
181pub enum ExtraRuleTrigger {
182 PathSuffix { suffix: String },
184 PathContains { fragment: String },
186 PathRegex {
191 pattern: String,
192 #[serde(default)]
193 captures: Vec<String>,
194 },
195}
196
197#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
200pub struct SuiteRefSpec {
201 pub application: ApplicationName,
202 pub module: ModuleName,
203}