oven_cli/pipeline/
state.rs1use crate::db::RunStatus;
2
3impl RunStatus {
4 #[must_use]
13 pub const fn next(self, has_findings: bool, cycle: u32) -> Self {
14 match self {
15 Self::Pending => Self::Implementing,
16 Self::Implementing | Self::Fixing => Self::Reviewing,
17 Self::Reviewing if has_findings && cycle < 2 => Self::Fixing,
18 Self::Reviewing if has_findings => Self::Failed,
19 Self::Reviewing => Self::Merging,
20 Self::Merging => Self::Complete,
21 Self::Complete | Self::Failed => Self::Failed,
22 }
23 }
24
25 pub const fn is_terminal(self) -> bool {
26 matches!(self, Self::Complete | Self::Failed)
27 }
28}
29
30#[cfg(test)]
31mod tests {
32 use proptest::prelude::*;
33
34 use super::*;
35
36 const ALL_STATUSES: [RunStatus; 7] = [
37 RunStatus::Pending,
38 RunStatus::Implementing,
39 RunStatus::Reviewing,
40 RunStatus::Fixing,
41 RunStatus::Merging,
42 RunStatus::Complete,
43 RunStatus::Failed,
44 ];
45
46 proptest! {
47 #[test]
48 fn next_never_panics(idx in 0..7usize, has_findings: bool, cycle in 0..50u32) {
49 let status = ALL_STATUSES[idx];
50 let _ = status.next(has_findings, cycle);
52 }
53
54 #[test]
55 fn terminal_states_stay_terminal(has_findings: bool, cycle in 0..50u32) {
56 assert!(RunStatus::Complete.next(has_findings, cycle).is_terminal());
57 assert!(RunStatus::Failed.next(has_findings, cycle).is_terminal());
58 }
59
60 #[test]
61 fn reviewing_with_findings_past_max_always_fails(cycle in 2..50u32) {
62 assert_eq!(RunStatus::Reviewing.next(true, cycle), RunStatus::Failed);
63 }
64
65 #[test]
66 fn reviewing_clean_always_merges(cycle in 0..50u32) {
67 assert_eq!(RunStatus::Reviewing.next(false, cycle), RunStatus::Merging);
68 }
69 }
70
71 #[test]
72 fn pending_to_implementing() {
73 assert_eq!(RunStatus::Pending.next(false, 0), RunStatus::Implementing);
74 }
75
76 #[test]
77 fn implementing_to_reviewing() {
78 assert_eq!(RunStatus::Implementing.next(false, 0), RunStatus::Reviewing);
79 }
80
81 #[test]
82 fn clean_review_to_merging() {
83 assert_eq!(RunStatus::Reviewing.next(false, 1), RunStatus::Merging);
84 }
85
86 #[test]
87 fn findings_under_max_cycles_to_fixing() {
88 assert_eq!(RunStatus::Reviewing.next(true, 1), RunStatus::Fixing);
89 }
90
91 #[test]
92 fn findings_at_max_cycles_to_failed() {
93 assert_eq!(RunStatus::Reviewing.next(true, 2), RunStatus::Failed);
94 }
95
96 #[test]
97 fn fixing_back_to_reviewing() {
98 assert_eq!(RunStatus::Fixing.next(false, 1), RunStatus::Reviewing);
99 }
100
101 #[test]
102 fn merging_to_complete() {
103 assert_eq!(RunStatus::Merging.next(false, 0), RunStatus::Complete);
104 }
105
106 #[test]
107 fn terminal_states_go_to_failed() {
108 assert_eq!(RunStatus::Complete.next(false, 0), RunStatus::Failed);
109 assert_eq!(RunStatus::Failed.next(false, 0), RunStatus::Failed);
110 }
111
112 #[test]
113 fn is_terminal() {
114 assert!(RunStatus::Complete.is_terminal());
115 assert!(RunStatus::Failed.is_terminal());
116 assert!(!RunStatus::Pending.is_terminal());
117 assert!(!RunStatus::Implementing.is_terminal());
118 assert!(!RunStatus::Reviewing.is_terminal());
119 assert!(!RunStatus::Fixing.is_terminal());
120 assert!(!RunStatus::Merging.is_terminal());
121 }
122}