Nothing to see here, move along
at main 225 lines 6.7 kB view raw
1use lancer_core::error::KernelError; 2use lancer_core::process_state::ProcessState; 3 4#[test] 5fn all_valid_transitions_succeed() { 6 let valid_pairs: &[(ProcessState, ProcessState)] = &[ 7 (ProcessState::Free, ProcessState::Created), 8 (ProcessState::Created, ProcessState::Ready), 9 (ProcessState::Ready, ProcessState::Running), 10 (ProcessState::Running, ProcessState::Ready), 11 (ProcessState::Running, ProcessState::Blocked), 12 (ProcessState::Blocked, ProcessState::Ready), 13 (ProcessState::Running, ProcessState::Dead), 14 (ProcessState::Ready, ProcessState::Dead), 15 (ProcessState::Blocked, ProcessState::Dead), 16 (ProcessState::Created, ProcessState::Dead), 17 (ProcessState::Dead, ProcessState::Free), 18 (ProcessState::Running, ProcessState::Zombie), 19 (ProcessState::Ready, ProcessState::Zombie), 20 (ProcessState::Blocked, ProcessState::Zombie), 21 (ProcessState::Created, ProcessState::Zombie), 22 (ProcessState::Zombie, ProcessState::Free), 23 ]; 24 25 valid_pairs.iter().for_each(|&(from, to)| { 26 let mut state = from; 27 assert!( 28 state.transition(to).is_ok(), 29 "transition {:?} -> {:?} should succeed", 30 from, 31 to 32 ); 33 assert_eq!(state, to); 34 }); 35} 36 37#[test] 38fn all_invalid_transitions_fail() { 39 let valid_count = ProcessState::ALL 40 .iter() 41 .flat_map(|&from| ProcessState::ALL.iter().map(move |&to| (from, to))) 42 .filter(|&(from, to)| { 43 let mut state = from; 44 match state.transition(to) { 45 Ok(()) => { 46 assert!( 47 ProcessState::is_valid_transition(from, to), 48 "transition {:?} -> {:?} succeeded but is_valid_transition says no", 49 from, 50 to 51 ); 52 true 53 } 54 Err(KernelError::BadState) => { 55 assert!( 56 !ProcessState::is_valid_transition(from, to), 57 "transition {:?} -> {:?} failed but is_valid_transition says yes", 58 from, 59 to 60 ); 61 false 62 } 63 Err(e) => panic!("unexpected error {:?} for {:?} -> {:?}", e, from, to), 64 } 65 }) 66 .count(); 67 68 assert_eq!(valid_count, 16, "expected exactly 16 valid transitions"); 69} 70 71#[test] 72fn self_transitions_are_invalid() { 73 ProcessState::ALL.iter().for_each(|&state| { 74 assert!( 75 !ProcessState::is_valid_transition(state, state), 76 "self-transition {:?} -> {:?} should be invalid", 77 state, 78 state 79 ); 80 }); 81} 82 83#[test] 84fn free_can_only_reach_created() { 85 let reachable: Vec<ProcessState> = ProcessState::ALL 86 .iter() 87 .copied() 88 .filter(|&to| ProcessState::is_valid_transition(ProcessState::Free, to)) 89 .collect(); 90 91 assert_eq!(reachable, vec![ProcessState::Created]); 92} 93 94#[test] 95fn dead_can_only_reach_free() { 96 let reachable: Vec<ProcessState> = ProcessState::ALL 97 .iter() 98 .copied() 99 .filter(|&to| ProcessState::is_valid_transition(ProcessState::Dead, to)) 100 .collect(); 101 102 assert_eq!(reachable, vec![ProcessState::Free]); 103} 104 105#[test] 106fn full_lifecycle() { 107 let mut state = ProcessState::Free; 108 state.transition(ProcessState::Created).unwrap(); 109 state.transition(ProcessState::Ready).unwrap(); 110 state.transition(ProcessState::Running).unwrap(); 111 state.transition(ProcessState::Blocked).unwrap(); 112 state.transition(ProcessState::Ready).unwrap(); 113 state.transition(ProcessState::Dead).unwrap(); 114 state.transition(ProcessState::Free).unwrap(); 115 assert_eq!(state, ProcessState::Free); 116} 117 118#[test] 119fn every_non_free_state_can_die() { 120 [ 121 ProcessState::Created, 122 ProcessState::Ready, 123 ProcessState::Running, 124 ProcessState::Blocked, 125 ] 126 .iter() 127 .for_each(|&from| { 128 assert!( 129 ProcessState::is_valid_transition(from, ProcessState::Dead), 130 "{:?} should be able to transition to Dead", 131 from 132 ); 133 }); 134} 135 136#[test] 137fn every_non_free_state_can_zombify() { 138 [ 139 ProcessState::Created, 140 ProcessState::Ready, 141 ProcessState::Running, 142 ProcessState::Blocked, 143 ] 144 .iter() 145 .for_each(|&from| { 146 assert!( 147 ProcessState::is_valid_transition(from, ProcessState::Zombie), 148 "{:?} should be able to transition to Zombie", 149 from 150 ); 151 }); 152} 153 154#[test] 155fn zombie_can_only_reach_free() { 156 let reachable: Vec<ProcessState> = ProcessState::ALL 157 .iter() 158 .copied() 159 .filter(|&to| ProcessState::is_valid_transition(ProcessState::Zombie, to)) 160 .collect(); 161 162 assert_eq!(reachable, vec![ProcessState::Free]); 163} 164 165#[test] 166fn zombie_cannot_transition_to_ready_or_running() { 167 [ 168 ProcessState::Ready, 169 ProcessState::Running, 170 ProcessState::Dead, 171 ] 172 .iter() 173 .for_each(|&to| { 174 let mut state = ProcessState::Zombie; 175 assert!( 176 state.transition(to).is_err(), 177 "Zombie -> {:?} should be invalid", 178 to, 179 ); 180 }); 181} 182 183#[test] 184fn zombie_lifecycle() { 185 let mut state = ProcessState::Free; 186 state.transition(ProcessState::Created).unwrap(); 187 state.transition(ProcessState::Ready).unwrap(); 188 state.transition(ProcessState::Running).unwrap(); 189 state.transition(ProcessState::Zombie).unwrap(); 190 state.transition(ProcessState::Free).unwrap(); 191 assert_eq!(state, ProcessState::Free); 192} 193 194#[test] 195fn zombie_lifecycle_from_blocked() { 196 let mut state = ProcessState::Free; 197 state.transition(ProcessState::Created).unwrap(); 198 state.transition(ProcessState::Ready).unwrap(); 199 state.transition(ProcessState::Running).unwrap(); 200 state.transition(ProcessState::Blocked).unwrap(); 201 state.transition(ProcessState::Zombie).unwrap(); 202 state.transition(ProcessState::Free).unwrap(); 203 assert_eq!(state, ProcessState::Free); 204} 205 206#[test] 207fn free_and_dead_cannot_zombify() { 208 [ProcessState::Free, ProcessState::Dead] 209 .iter() 210 .for_each(|&from| { 211 assert!( 212 !ProcessState::is_valid_transition(from, ProcessState::Zombie), 213 "{:?} -> Zombie should be invalid", 214 from 215 ); 216 }); 217} 218 219#[test] 220fn zombie_is_not_a_self_transition() { 221 assert!( 222 !ProcessState::is_valid_transition(ProcessState::Zombie, ProcessState::Zombie), 223 "Zombie -> Zombie should be invalid" 224 ); 225}