Adam Snaider | 644a41e | 2023-10-20 15:14:44 -0400 | [diff] [blame^] | 1 | #[cfg(test)] |
| 2 | mod tests { |
| 3 | use std::{cell::Cell, time::Duration}; |
| 4 | |
| 5 | use aos_configuration::read_config_from; |
| 6 | use aos_events_event_loop_runtime::{EventLoopRuntimeHolder, Watcher}; |
| 7 | use aos_events_simulated_event_loop::{SimulatedEventLoopFactory, SimulatedEventLoopHolder}; |
| 8 | use aos_test_init::test_init; |
| 9 | use ping_lib::PingTask; |
| 10 | use ping_rust_fbs::aos::examples as ping; |
| 11 | use pong_rust_fbs::aos::examples as pong; |
| 12 | use runfiles::Runfiles; |
| 13 | |
| 14 | // We use this trait to simplify leaking memory. For now, the event loop only allows |
| 15 | // data with a `'static` lifetime. Until that restriction is lifted, we may leak |
| 16 | // some memory in tests. |
| 17 | trait Leak: Sized { |
| 18 | fn leak(self) -> &'static mut Self { |
| 19 | Box::leak(Box::new(self)) |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | impl<T> Leak for T {} |
| 24 | |
| 25 | #[allow(unused)] |
| 26 | struct PingPongTest { |
| 27 | ping_event_loop: EventLoopRuntimeHolder<SimulatedEventLoopHolder>, |
| 28 | pong_event_loop: EventLoopRuntimeHolder<SimulatedEventLoopHolder>, |
| 29 | event_loop_factory: SimulatedEventLoopFactory<'static>, |
| 30 | } |
| 31 | |
| 32 | impl PingPongTest { |
| 33 | pub fn init() -> PingPongTest { |
| 34 | test_init(); |
| 35 | let r = Runfiles::create().unwrap(); |
| 36 | let config = |
| 37 | read_config_from(&r.rlocation("org_frc971/aos/events/pingpong_config.json")) |
| 38 | .unwrap() |
| 39 | .leak(); |
| 40 | let mut event_loop_factory = SimulatedEventLoopFactory::new(config); |
| 41 | |
| 42 | let ping_event_loop = event_loop_factory.make_runtime("ping", None, |runtime| { |
| 43 | let ping = PingTask::new(); |
| 44 | runtime.spawn(async move { ping.tasks(runtime, 10000).await }); |
| 45 | }); |
| 46 | |
| 47 | let pong_event_loop = event_loop_factory.make_runtime("pong", None, |runtime| { |
| 48 | runtime.spawn(async move { pong_lib::pong(runtime).await }) |
| 49 | }); |
| 50 | PingPongTest { |
| 51 | event_loop_factory, |
| 52 | ping_event_loop, |
| 53 | pong_event_loop, |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | pub fn event_loop(&mut self) -> &mut SimulatedEventLoopFactory<'static> { |
| 58 | &mut self.event_loop_factory |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | #[test] |
| 63 | fn starts() { |
| 64 | let mut pingpong = PingPongTest::init(); |
| 65 | pingpong.event_loop().run_for(Duration::from_secs(10)); |
| 66 | } |
| 67 | |
| 68 | #[test] |
| 69 | fn always_replies() { |
| 70 | let mut pingpong = PingPongTest::init(); |
| 71 | |
| 72 | // For now, the simulated event loop requires all references in the tasks |
| 73 | // to be `'static`, so we leak them for now until the restriction is lifted. |
| 74 | let ping_count: &Cell<i32> = Cell::new(1).leak(); |
| 75 | let pong_count: &Cell<i32> = Cell::new(1).leak(); |
| 76 | |
| 77 | let _test_runtime = pingpong.event_loop().make_runtime("test", None, |runtime| { |
| 78 | let count_pings = async move { |
| 79 | let mut ping_watcher: Watcher<ping::Ping> = runtime.make_watcher("/test").unwrap(); |
| 80 | loop { |
| 81 | let ping = ping_watcher.next().await; |
| 82 | assert_eq!(ping.message().unwrap().value(), ping_count.get()); |
| 83 | ping_count.set(ping_count.get() + 1); |
| 84 | } |
| 85 | }; |
| 86 | let count_pongs = async move { |
| 87 | let mut pong_watcher: Watcher<pong::Pong> = runtime.make_watcher("/test").unwrap(); |
| 88 | loop { |
| 89 | let pong = pong_watcher.next().await; |
| 90 | assert_eq!(pong.message().unwrap().value(), pong_count.get()); |
| 91 | pong_count.set(pong_count.get() + 1); |
| 92 | } |
| 93 | }; |
| 94 | |
| 95 | runtime.spawn(async move { |
| 96 | futures::join!(count_pings, count_pongs); |
| 97 | unreachable!(); |
| 98 | }); |
| 99 | }); |
| 100 | |
| 101 | pingpong.event_loop().run_for(Duration::from_secs(10)); |
| 102 | |
| 103 | // We run at t=0 and t=10 seconds, which means we run 1 extra time (Note that we started |
| 104 | // the count at 1, not 0). |
| 105 | assert_eq!(ping_count.get(), 1002); |
| 106 | assert_eq!(pong_count.get(), 1002); |
| 107 | } |
| 108 | } |