#![doc = include_str!("../README.md")]
#![doc = include_str!("../tests/data/qemu-config.json")]
#![doc = include_str!("../tests/data/container-config.json")]
use std::io::{Read, Write};
use std::time::SystemTime;
#[derive(Debug, PartialEq)]
pub enum Key {
Enter,
}
#[derive(Debug, PartialEq)]
pub enum Status {
Running,
Paused,
Suspended,
Shutdown,
}
#[derive(Debug, PartialEq)]
pub enum EventKind {
Shutdown,
Resume,
Pause,
Suspend,
}
pub struct Event {
pub kind: EventKind,
pub timestamp: SystemTime,
}
pub trait EventSubscriber: Send + Sync + 'static {
fn on_event(&mut self, event: &Event);
}
pub trait SystemHarness {
type Terminal: SystemTerminal;
fn terminal(&self) -> Result<Self::Terminal, Error>;
fn pause(&mut self) -> Result<(), Error>;
fn resume(&mut self) -> Result<(), Error>;
fn shutdown(&mut self) -> Result<(), Error>;
fn status(&mut self) -> Result<Status, Error>;
fn running(&mut self) -> Result<bool, Error>;
}
pub trait SystemTerminal: Write + Read {
fn send_key(&mut self, key: Key) -> Result<(), Error>;
fn send_command(&mut self, command: &str) -> Result<(), Error> {
self.write(command.as_bytes())?;
self.flush()?;
self.send_key(Key::Enter)
}
}
pub trait EventPublisher {
fn subscribe(&mut self, subscriber: impl EventSubscriber) -> Result<(), Error>;
}
impl<F> EventSubscriber for F
where
F: FnMut(&Event) + Send + Sync + 'static,
{
fn on_event(&mut self, event: &Event) {
(self)(event)
}
}
mod error;
pub use error::Error;
pub use error::ErrorKind;
#[cfg(all(target_family = "unix", feature = "container"))]
mod container;
#[cfg(all(target_family = "unix", feature = "container"))]
pub use container::*;
#[cfg(all(target_family = "unix", feature = "qemu"))]
mod qemu;
#[cfg(all(target_family = "unix", feature = "qemu"))]
pub use qemu::*;
#[cfg(test)]
mod tests {
use super::*;
struct FakeEventPublisher(Vec<Box<dyn EventSubscriber>>);
impl FakeEventPublisher {
pub fn publish(&mut self) {
let event = Event {
kind: EventKind::Shutdown,
timestamp: SystemTime::now(),
};
for subscriber in &mut self.0 {
subscriber.on_event(&event);
}
}
}
impl EventPublisher for FakeEventPublisher {
fn subscribe(&mut self, subscriber: impl EventSubscriber) -> Result<(), Error> {
self.0.push(Box::new(subscriber));
Ok(())
}
}
#[test]
fn fn_subscribe() {
let mut publisher = FakeEventPublisher(Vec::new());
publisher.subscribe(|_event: &Event| {}).unwrap();
publisher.publish();
}
}