use boomerang::{ builder::*, runtime::{self}, Reaction, Reactor, }; use boomerang_util::timeout; trait CountData: Copy + runtime::PortData + std::ops::AddAssign + std::cmp::PartialEq { } impl CountData for i32 {} #[derive(Reactor)] #[reactor(state = "T", reaction = "ReactionT", reaction = "ReactionShutdown")] struct Count { #[reactor(timer(period = "1 msec"))] t: TimerActionKey, c: TypedPortKey, #[reactor(child = runtime::Duration::from_secs(1))] _timeout: timeout::Timeout, } #[derive(Reaction)] #[reaction(reactor = "Count::", triggers(action = "t"))] struct ReactionT<'a, T: CountData> { #[reaction(path = "c")] xyc: runtime::OutputRef<'a, T>, } impl Trigger> for ReactionT<'_, T> { fn trigger(mut self, _ctx: &mut runtime::Context, state: &mut as Reactor>::State) { *state += 1; assert!(self.xyc.is_none()); *self.xyc = Some(*state); } } #[derive(Reaction)] #[reaction(reactor = "Count::", bound = "T: CountData", triggers(shutdown))] struct ReactionShutdown; impl Trigger> for ReactionShutdown { fn trigger(self, _ctx: &mut runtime::Context, state: &mut as Reactor>::State) { assert_eq!(*state, 1e3 as i32, "expected 1e3, got {state:?}"); println!("ok"); } } #[test] fn count() { tracing_subscriber::fmt::init(); let (_, sched) = boomerang_util::runner::build_and_test_reactor::>("count", 0, true, false) .unwrap(); let env = sched.into_env(); let count = env .find_reactor_by_name("count") .and_then(|r| r.get_state::()) .unwrap(); assert_eq!(*count, 1e3 as i32); }