near_async/test_loop/
data.rs1use std::any::{Any, type_name};
2use std::marker::PhantomData;
3use std::sync::Arc;
4use std::sync::atomic::AtomicBool;
5
6use crate::messaging::{Actor, LateBoundSender};
7
8use super::pending_events_sender::RawPendingEventsSender;
9use super::sender::TestLoopSender;
10
11pub struct TestLoopData {
41 data: Vec<Box<dyn Any>>,
43 raw_pending_events_sender: RawPendingEventsSender,
45 shutting_down: Arc<AtomicBool>,
47}
48
49impl TestLoopData {
50 pub(crate) fn new(
51 raw_pending_events_sender: RawPendingEventsSender,
52 shutting_down: Arc<AtomicBool>,
53 ) -> Self {
54 Self { data: Vec::new(), raw_pending_events_sender, shutting_down }
55 }
56
57 pub fn register_data<T>(&mut self, data: T) -> TestLoopDataHandle<T> {
60 let id = self.data.len();
61 self.data.push(Box::new(data));
62 TestLoopDataHandle::new(id)
63 }
64
65 pub fn register_actor<A>(
71 &mut self,
72 identifier: &str,
73 actor: A,
74 adapter: Option<Arc<LateBoundSender<TestLoopSender<A>>>>,
75 ) -> TestLoopSender<A>
76 where
77 A: Actor + 'static,
78 {
79 let actor_handle = self.register_data(actor);
80 let sender = TestLoopSender::new(
81 actor_handle,
82 self.raw_pending_events_sender.for_identifier(identifier),
83 self.shutting_down.clone(),
84 );
85 self.queue_start_actor_event(identifier, sender.clone());
86 if let Some(adapter) = adapter {
87 adapter.bind(sender.clone());
88 }
89 sender
90 }
91
92 fn queue_start_actor_event<A>(&self, identifier: &str, mut sender: TestLoopSender<A>)
94 where
95 A: Actor + 'static,
96 {
97 let callback = move |data: &mut TestLoopData| {
98 let actor = data.get_mut(&sender.actor_handle());
99 actor.start_actor(&mut sender);
100 };
101 self.raw_pending_events_sender
102 .for_identifier(identifier)
103 .send(format!("StartActor({:?})", type_name::<A>()), Box::new(callback));
104 }
105
106 pub fn get<T>(&self, handle: &TestLoopDataHandle<T>) -> &T {
108 self.data
109 .get(handle.id)
110 .expect("Handle id out of bounds. Does handle belong to this TestLoopData?")
111 .downcast_ref()
112 .expect("Handle type mismatched. Does handle belong to this TestLoopData?")
113 }
114
115 pub fn get_mut<T>(&mut self, handle: &TestLoopDataHandle<T>) -> &mut T {
117 self.data
118 .get_mut(handle.id)
119 .expect("Handle id out of bounds. Does handle belong to this TestLoopData?")
120 .downcast_mut()
121 .expect("Handle type mismatched. Does handle belong to this TestLoopData?")
122 }
123}
124
125pub struct TestLoopDataHandle<T>
129where
130 T: 'static,
131{
132 id: usize,
134 _phantom: PhantomData<fn(T)>,
136}
137
138impl<T> Clone for TestLoopDataHandle<T> {
139 fn clone(&self) -> Self {
140 Self { id: self.id, _phantom: PhantomData }
141 }
142}
143
144impl<T> TestLoopDataHandle<T> {
145 fn new(id: usize) -> Self {
146 Self { id, _phantom: PhantomData }
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use std::sync::Arc;
153 use std::sync::atomic::AtomicBool;
154
155 use crate::test_loop::data::TestLoopData;
156 use crate::test_loop::pending_events_sender::RawPendingEventsSender;
157
158 #[derive(Debug, PartialEq)]
159 struct TestData {
160 pub value: usize,
161 }
162
163 #[test]
164 fn test_register_data() {
165 let mut data = TestLoopData::new(
166 RawPendingEventsSender::new(|_| {}),
167 Arc::new(AtomicBool::new(false)),
168 );
169 let test_data = TestData { value: 42 };
170 let handle = data.register_data(test_data);
171 assert_eq!(data.get(&handle), &TestData { value: 42 });
172
173 data.get_mut(&handle).value = 43;
174 assert_eq!(data.get(&handle), &TestData { value: 43 });
175 }
176}