elara_loadtest/
test_node.rs1use elara_runtime::{Node, NodeConfig};
8use elara_core::{NodeId, SessionId, Event, EventType, StateId, MutationOp};
9use std::time::Instant;
10use std::collections::HashMap;
11
12pub struct TestNode {
14 node: Node,
16 node_id: NodeId,
18 pub(crate) peers: HashMap<NodeId, usize>,
20 messages_sent: u64,
22 messages_received: u64,
24}
25
26impl TestNode {
27 pub fn spawn(config: NodeConfig) -> Result<Self, String> {
29 let node = Node::with_config(config);
30 let node_id = node.node_id();
31
32 Ok(Self {
33 node,
34 node_id,
35 peers: HashMap::new(),
36 messages_sent: 0,
37 messages_received: 0,
38 })
39 }
40
41 pub fn spawn_default() -> Result<Self, String> {
43 Self::spawn(NodeConfig::default())
44 }
45
46 pub fn node_id(&self) -> NodeId {
48 self.node_id
49 }
50
51 pub fn join_session(&mut self, session_id: SessionId, session_key: [u8; 32]) {
53 self.node.join_session(session_id, session_key);
54 }
55
56 pub fn join_session_unsecured(&mut self, session_id: SessionId) {
58 self.node.join_session_unsecured(session_id);
59 }
60
61 pub fn connect_to(&mut self, peer: &TestNode) -> Result<(), String> {
63 let peer_id = peer.node_id();
64 let peer_index = self.peers.len();
65 self.peers.insert(peer_id, peer_index);
66 Ok(())
67 }
68
69 pub fn send_message(&mut self, payload: Vec<u8>) -> Result<Instant, String> {
73 let start = Instant::now();
74
75 let seq = self.node.next_event_seq();
76
77 let event = Event::new(
79 self.node_id,
80 seq,
81 EventType::TextAppend,
82 StateId::new(0),
83 MutationOp::Append(payload),
84 );
85
86 self.node.queue_local_event(event);
88
89 self.node.tick();
91
92 self.messages_sent += 1;
93
94 Ok(start)
95 }
96
97 pub fn receive_from(&mut self, peer: &mut TestNode) -> usize {
99 let mut received_count = 0;
100
101 while let Some(frame) = peer.node.pop_outgoing() {
103 self.node.queue_incoming(frame);
105 received_count += 1;
106 }
107
108 if received_count > 0 {
110 self.node.tick();
111 self.messages_received += received_count as u64;
112 }
113
114 received_count
115 }
116
117 pub fn tick(&mut self) {
119 self.node.tick();
120 }
121
122 pub fn messages_sent(&self) -> u64 {
124 self.messages_sent
125 }
126
127 pub fn messages_received(&self) -> u64 {
129 self.messages_received
130 }
131
132 pub fn node(&self) -> &Node {
134 &self.node
135 }
136
137 pub fn node_mut(&mut self) -> &mut Node {
139 &mut self.node
140 }
141
142 pub fn shutdown(self) {
144 drop(self);
146 }
147}
148
149pub fn generate_test_message(size: usize) -> Vec<u8> {
151 vec![0u8; size]
152}
153
154#[allow(dead_code)]
156pub fn generate_random_message(size: usize) -> Vec<u8> {
157 use std::collections::hash_map::RandomState;
158 use std::hash::{BuildHasher, Hash, Hasher};
159
160 let mut data = Vec::with_capacity(size);
161 let hasher_builder = RandomState::new();
162
163 for i in 0..size {
164 let mut hasher = hasher_builder.build_hasher();
165 i.hash(&mut hasher);
166 data.push((hasher.finish() & 0xFF) as u8);
167 }
168
169 data
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175
176 #[test]
177 fn test_node_spawn() {
178 let node = TestNode::spawn_default();
179 assert!(node.is_ok());
180 }
181
182 #[test]
183 fn test_node_connection() {
184 let mut node1 = TestNode::spawn_default().unwrap();
185 let node2 = TestNode::spawn_default().unwrap();
186
187 let result = node1.connect_to(&node2);
188 assert!(result.is_ok());
189 assert_eq!(node1.peers.len(), 1);
190 }
191
192 #[test]
193 fn test_message_generation() {
194 let msg = generate_test_message(100);
195 assert_eq!(msg.len(), 100);
196
197 let random_msg = generate_random_message(100);
198 assert_eq!(random_msg.len(), 100);
199 }
200
201 #[test]
202 fn test_send_message() {
203 let mut node = TestNode::spawn_default().unwrap();
204 let session_id = SessionId::new(1);
205 node.join_session_unsecured(session_id);
206
207 let payload = generate_test_message(64);
208 let result = node.send_message(payload);
209
210 assert!(result.is_ok());
211 assert_eq!(node.messages_sent(), 1);
212 }
213
214 #[test]
215 fn test_message_exchange() {
216 let mut node1 = TestNode::spawn_default().unwrap();
217 let mut node2 = TestNode::spawn_default().unwrap();
218
219 let session_id = SessionId::new(1);
220 node1.join_session_unsecured(session_id);
221 node2.join_session_unsecured(session_id);
222
223 node1.connect_to(&node2).unwrap();
224
225 let payload = generate_test_message(64);
227 node1.send_message(payload).unwrap();
228
229 let _received = node2.receive_from(&mut node1);
231
232 assert_eq!(node1.messages_sent(), 1);
233 }
235}