#![allow(dead_code)]
use calloop::{EventLoop, EventSource};
use std::thread::JoinHandle;
use test_binary::build_mock_binary_once;
build_mock_binary_once!(test_status);
build_mock_binary_once!(test_output);
build_mock_binary_once!(test_output_asap);
pub fn test_status_cmd(status: i32) -> calloop_subproc::Command {
calloop_subproc::Command::new(test_status_path()).with_args([format!("{}", status)])
}
pub fn test_output_cmd() -> calloop_subproc::Command {
calloop_subproc::Command::new(test_output_path())
}
pub fn test_output_asap_cmd() -> calloop_subproc::Command {
calloop_subproc::Command::new(test_output_asap_path())
}
static INTEGRATION_TEST_LOGGING_INIT: std::sync::Once = std::sync::Once::new();
pub fn init_logging() {
INTEGRATION_TEST_LOGGING_INIT.call_once(|| {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace"))
.is_test(true)
.try_init()
.expect("Could not initialise test logging");
});
}
pub struct SpawnedCalloop<T, U> {
runner: Option<std::thread::JoinHandle<()>>,
stopper: calloop::ping::Ping,
receiver: std::sync::mpsc::Receiver<T>,
replier: Option<std::sync::mpsc::Sender<U>>,
}
impl<T: Send + 'static, U: Send + 'static> SpawnedCalloop<T, U> {
pub fn new<F, X>(creator: F) -> Self
where
F: FnOnce() -> X + Send + 'static,
X: EventSource<Event = T, Ret = U>,
{
let (stopper, stop_src) = calloop::ping::make_ping().expect("Could not create ping");
let (sender, receiver) = std::sync::mpsc::channel();
let (replier, returner) = std::sync::mpsc::channel();
let runner = std::thread::spawn(move || {
let dut_source = creator();
let mut event_loop: EventLoop<calloop::LoopSignal> =
EventLoop::try_new().expect("Could not initialise event loop");
let handle = event_loop.handle();
handle
.insert_source(stop_src, |_, _, signaller| {
log::trace!("Received stop signal");
signaller.stop();
})
.expect("Could not insert ping source");
handle
.insert_source(dut_source, |msg, _, _| {
sender.send(msg).expect("Could not send event source data");
returner
.recv()
.expect("Could not receive event source return value")
})
.expect("Could not insert event source under test");
event_loop
.run(None, &mut event_loop.get_signal(), |_| {})
.expect("Could not run event loop");
});
Self {
runner: Some(runner),
stopper,
receiver,
replier: Some(replier),
}
}
}
impl<T, U> SpawnedCalloop<T, U> {
pub fn send(&self, val: U) {
self.replier
.as_ref()
.expect("Reply side of channel should still exist")
.send(val)
.expect("Could not send reply value to test loop");
}
}
impl<T, U> Iterator for SpawnedCalloop<T, U> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.receiver.recv().ok()
}
}
impl<T, U> Drop for SpawnedCalloop<T, U> {
fn drop(&mut self) {
self.stopper.ping();
self.replier.take();
self.runner.take().map(JoinHandle::join);
}
}