use anyhow::anyhow;
use serde::Deserialize;
use serde::Serialize;
use snapshot::AnySnapshot;
#[derive(Copy, Clone, Serialize, Deserialize)]
pub enum DeviceState {
Awake,
Sleep,
}
pub trait Suspendable {
fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> {
Err(anyhow!(
"Suspendable::snapshot not implemented for {}",
std::any::type_name::<Self>()
))
}
fn restore(&mut self, _data: AnySnapshot) -> anyhow::Result<()> {
Err(anyhow!(
"Suspendable::restore not implemented for {}",
std::any::type_name::<Self>()
))
}
fn sleep(&mut self) -> anyhow::Result<()> {
Err(anyhow!(
"Suspendable::sleep not implemented for {}",
std::any::type_name::<Self>()
))
}
fn wake(&mut self) -> anyhow::Result<()> {
Err(anyhow!(
"Suspendable::wake not implemented for {}",
std::any::type_name::<Self>()
))
}
}
#[macro_export]
macro_rules! suspendable_tests {
($name:ident, $dev:expr, $modfun:path) => {
mod $name {
use super::*;
#[test]
fn test_sleep_idempotent() {
let unit = &mut $dev;
let res = unit.sleep();
let res2 = unit.sleep();
match res {
Ok(()) => (),
Err(e) => println!("{}", e),
}
match res2 {
Ok(()) => (),
Err(e) => println!("idempotent: {}", e),
}
}
#[test]
fn test_snapshot_restore() {
let unit = &mut $dev;
let snap = unit.snapshot();
match snap {
Ok(snap_res) => {
let res = unit.restore(snap_res);
match res {
Ok(()) => (),
Err(e) => println!("{}", e),
}
}
Err(e) => println!("{}", e),
}
}
#[test]
fn test_sleep_snapshot() {
let unit = &mut $dev;
let sleep_result = unit.sleep();
let snap_result = unit.snapshot();
match sleep_result {
Ok(()) => (),
Err(e) => println!("{}", e),
}
match snap_result {
Ok(_res) => (),
Err(e) => println!("{}", e),
}
}
#[test]
fn test_sleep_snapshot_restore_wake() {
let unit = &mut $dev;
let sleep_result = unit.sleep();
let snap_result = unit.snapshot();
match sleep_result {
Ok(()) => (),
Err(e) => println!("{}", e),
}
match snap_result {
Ok(snap_res) => {
let res = unit.restore(snap_res);
match res {
Ok(()) => (),
Err(e) => println!("{}", e),
}
}
Err(e) => println!("{}", e),
}
let wake_res = unit.wake();
match wake_res {
Ok(()) => (),
Err(e) => println!("{}", e),
}
}
#[test]
fn test_sleep_snapshot_wake() {
let unit = &mut $dev;
let sleep_result = unit.sleep();
let snap_result = unit.snapshot();
match sleep_result {
Ok(()) => (),
Err(e) => println!("{}", e),
}
match snap_result {
Ok(_snap_res) => (),
Err(e) => println!("{}", e),
}
let wake_res = unit.wake();
match wake_res {
Ok(()) => (),
Err(e) => println!("{}", e),
}
}
#[test]
fn test_snapshot() {
let unit = &mut $dev;
let snap_result = unit.snapshot();
match snap_result {
Ok(_snap_res) => (),
Err(e) => println!("{}", e),
}
}
#[test]
fn test_suspend_mod_restore() {
let unit = &mut $dev;
let snap_result = unit.snapshot().expect("failed to take initial snapshot");
$modfun(unit);
unit.restore(snap_result.clone())
.expect("failed to restore snapshot");
let snap2_result = unit
.snapshot()
.expect("failed to take snapshot after modification");
assert_eq!(snap_result, snap2_result);
}
#[test]
fn test_suspend_mod() {
let unit = &mut $dev;
let snap_result = unit.snapshot().expect("failed to take initial snapshot");
$modfun(unit);
let snap2_result = unit
.snapshot()
.expect("failed to take snapshot after modification");
assert_ne!(snap_result, snap2_result)
}
}
};
}