shell_tunnel/session/
state.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
5pub enum SessionState {
6 #[default]
8 Created,
9 Active,
11 Idle,
13 Terminated,
15}
16
17impl SessionState {
18 pub fn can_transition_to(&self, target: SessionState) -> bool {
34 use SessionState::*;
35 matches!(
36 (*self, target),
37 (Created, Active)
38 | (Created, Idle)
39 | (Active, Idle)
40 | (Active, Terminated)
41 | (Idle, Active)
42 | (Idle, Terminated)
43 )
44 }
45
46 pub fn transition_to(&mut self, target: SessionState) -> crate::Result<()> {
50 if self.can_transition_to(target) {
51 *self = target;
52 Ok(())
53 } else {
54 Err(crate::error::ShellTunnelError::InvalidStateTransition {
55 from: *self,
56 to: target,
57 })
58 }
59 }
60
61 pub fn is_terminal(&self) -> bool {
63 matches!(self, SessionState::Terminated)
64 }
65
66 pub fn can_execute(&self) -> bool {
68 matches!(self, SessionState::Active | SessionState::Idle)
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn test_valid_transitions() {
78 let mut state = SessionState::Created;
80 assert!(state.transition_to(SessionState::Active).is_ok());
81 assert_eq!(state, SessionState::Active);
82
83 assert!(state.transition_to(SessionState::Idle).is_ok());
85 assert_eq!(state, SessionState::Idle);
86
87 assert!(state.transition_to(SessionState::Active).is_ok());
89 assert_eq!(state, SessionState::Active);
90
91 assert!(state.transition_to(SessionState::Terminated).is_ok());
93 assert_eq!(state, SessionState::Terminated);
94 }
95
96 #[test]
97 fn test_created_to_idle_is_valid() {
98 let mut state = SessionState::Created;
100 assert!(state.transition_to(SessionState::Idle).is_ok());
101 assert_eq!(state, SessionState::Idle);
102 }
103
104 #[test]
105 fn test_invalid_idle_to_created() {
106 let mut state = SessionState::Idle;
108 assert!(state.transition_to(SessionState::Created).is_err());
109 assert_eq!(state, SessionState::Idle);
111 }
112
113 #[test]
114 fn test_invalid_from_terminated() {
115 let mut state = SessionState::Terminated;
116 assert!(state.transition_to(SessionState::Active).is_err());
117 assert!(state.transition_to(SessionState::Idle).is_err());
118 assert!(state.transition_to(SessionState::Created).is_err());
119 }
120
121 #[test]
122 fn test_is_terminal() {
123 assert!(!SessionState::Created.is_terminal());
124 assert!(!SessionState::Active.is_terminal());
125 assert!(!SessionState::Idle.is_terminal());
126 assert!(SessionState::Terminated.is_terminal());
127 }
128
129 #[test]
130 fn test_can_execute() {
131 assert!(!SessionState::Created.can_execute());
132 assert!(SessionState::Active.can_execute());
133 assert!(SessionState::Idle.can_execute());
134 assert!(!SessionState::Terminated.can_execute());
135 }
136
137 #[test]
138 fn test_default() {
139 let state = SessionState::default();
140 assert_eq!(state, SessionState::Created);
141 }
142}