1use anyhow::anyhow;
8use serde::Deserialize;
9use serde::Serialize;
10use snapshot::AnySnapshot;
11
12#[derive(Copy, Clone, Serialize, Deserialize)]
13pub enum DeviceState {
14 Awake,
15 Sleep,
16}
17
18pub trait Suspendable {
21 fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> {
23 Err(anyhow!(
24 "Suspendable::snapshot not implemented for {}",
25 std::any::type_name::<Self>()
26 ))
27 }
28 fn restore(&mut self, _data: AnySnapshot) -> anyhow::Result<()> {
30 Err(anyhow!(
31 "Suspendable::restore not implemented for {}",
32 std::any::type_name::<Self>()
33 ))
34 }
35 fn sleep(&mut self) -> anyhow::Result<()> {
38 Err(anyhow!(
39 "Suspendable::sleep not implemented for {}",
40 std::any::type_name::<Self>()
41 ))
42 }
43 fn wake(&mut self) -> anyhow::Result<()> {
46 Err(anyhow!(
47 "Suspendable::wake not implemented for {}",
48 std::any::type_name::<Self>()
49 ))
50 }
51}
52
53#[macro_export]
62macro_rules! suspendable_tests {
63 ($name:ident, $dev:expr, $modfun:ident) => {
64 mod $name {
65 use super::*;
66
67 #[test]
68 fn test_sleep_idempotent() {
69 let unit = &mut $dev;
70 let res = unit.sleep();
71 let res2 = unit.sleep();
72 match res {
73 Ok(()) => (),
74 Err(e) => println!("{}", e),
75 }
76 match res2 {
77 Ok(()) => (),
78 Err(e) => println!("idempotent: {}", e),
79 }
80 }
81
82 #[test]
83 fn test_snapshot_restore() {
84 let unit = &mut $dev;
85 let snap = unit.snapshot();
86 match snap {
87 Ok(snap_res) => {
88 let res = unit.restore(snap_res);
89 match res {
90 Ok(()) => (),
91 Err(e) => println!("{}", e),
92 }
93 }
94 Err(e) => println!("{}", e),
95 }
96 }
97
98 #[test]
99 fn test_sleep_snapshot() {
100 let unit = &mut $dev;
101 let sleep_result = unit.sleep();
102 let snap_result = unit.snapshot();
103 match sleep_result {
104 Ok(()) => (),
105 Err(e) => println!("{}", e),
106 }
107 match snap_result {
108 Ok(_res) => (),
109 Err(e) => println!("{}", e),
110 }
111 }
112
113 #[test]
114 fn test_sleep_snapshot_restore_wake() {
115 let unit = &mut $dev;
116 let sleep_result = unit.sleep();
117 let snap_result = unit.snapshot();
118 match sleep_result {
119 Ok(()) => (),
120 Err(e) => println!("{}", e),
121 }
122 match snap_result {
123 Ok(snap_res) => {
124 let res = unit.restore(snap_res);
125 match res {
126 Ok(()) => (),
127 Err(e) => println!("{}", e),
128 }
129 }
130 Err(e) => println!("{}", e),
131 }
132 let wake_res = unit.wake();
133 match wake_res {
134 Ok(()) => (),
135 Err(e) => println!("{}", e),
136 }
137 }
138
139 #[test]
140 fn test_sleep_snapshot_wake() {
141 let unit = &mut $dev;
142 let sleep_result = unit.sleep();
143 let snap_result = unit.snapshot();
144 match sleep_result {
145 Ok(()) => (),
146 Err(e) => println!("{}", e),
147 }
148 match snap_result {
149 Ok(_snap_res) => (),
150 Err(e) => println!("{}", e),
151 }
152 let wake_res = unit.wake();
153 match wake_res {
154 Ok(()) => (),
155 Err(e) => println!("{}", e),
156 }
157 }
158
159 #[test]
160 fn test_snapshot() {
161 let unit = &mut $dev;
162 let snap_result = unit.snapshot();
163 match snap_result {
164 Ok(_snap_res) => (),
165 Err(e) => println!("{}", e),
166 }
167 }
168
169 #[test]
170 fn test_suspend_mod_restore() {
171 let unit = &mut $dev;
172 let snap_result = unit.snapshot().expect("failed to take initial snapshot");
173 $modfun(unit);
174 unit.restore(snap_result.clone())
175 .expect("failed to restore snapshot");
176 let snap2_result = unit
177 .snapshot()
178 .expect("failed to take snapshot after modification");
179 assert_eq!(snap_result, snap2_result);
180 }
181
182 #[test]
183 fn test_suspend_mod() {
184 let unit = &mut $dev;
185 let snap_result = unit.snapshot().expect("failed to take initial snapshot");
186 $modfun(unit);
187 let snap2_result = unit
188 .snapshot()
189 .expect("failed to take snapshot after modification");
190 assert_ne!(snap_result, snap2_result)
191 }
192 }
193 };
194}