zoe_client/system_check/
synchronization.rs1use super::{SystemCheckConfig, TestInfo, TestResult};
9use crate::Client;
10use crate::services::MessagesManagerTrait;
11use std::time::{Duration, SystemTime, UNIX_EPOCH};
12use tokio::time::sleep;
13use tracing::{debug, info, warn};
14use zoe_wire_protocol::{
15 Content, KeyPair, Kind, Message, MessageFull, MessageV0, MessageV0Header, Tag,
16};
17
18#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
20pub struct SyncTestMessage {
21 pub sync_id: String,
22 pub message_type: String,
23 pub created_offline: bool,
24 pub data: Vec<u8>,
25 pub checksum: u32,
26 pub timestamp: u64,
27}
28
29impl SyncTestMessage {
30 pub fn new_offline(sync_id: String, data_size: usize) -> Self {
31 use rand::{RngCore, SeedableRng};
32 let mut rng = rand::rngs::StdRng::from_entropy();
33 let data: Vec<u8> = (0..data_size).map(|_| rng.next_u32() as u8).collect();
34 let checksum = crc32fast::hash(&data);
35 let timestamp = SystemTime::now()
36 .duration_since(UNIX_EPOCH)
37 .unwrap()
38 .as_secs();
39
40 Self {
41 sync_id,
42 message_type: "sync_test".to_string(),
43 created_offline: true,
44 data,
45 checksum,
46 timestamp,
47 }
48 }
49
50 pub fn verify_integrity(&self) -> bool {
51 crc32fast::hash(&self.data) == self.checksum
52 }
53}
54
55pub async fn run_tests(client: &Client, config: &SystemCheckConfig) -> Vec<TestInfo> {
57 let mut tests = Vec::new();
58
59 info!("🔄 Running synchronization verification tests");
60
61 tests.push(test_message_sync_verification(client, config).await);
63
64 tests.push(test_sync_connection_stability(client, config).await);
66
67 tests
68}
69
70async fn test_message_sync_verification(client: &Client, _config: &SystemCheckConfig) -> TestInfo {
72 let mut test = TestInfo::new("Message Sync Verification");
73
74 debug!("Testing message synchronization after connection establishment...");
75
76 if !client.has_connected_relays().await {
78 let error = "No relay connections available for sync verification".to_string();
79 return test.with_result(TestResult::Failed { error });
80 }
81
82 test.add_detail("✓ Relay connection confirmed for sync testing");
83
84 let sync_message = SyncTestMessage::new_offline(
86 "sync_verification_test".to_string(),
87 512, );
89
90 let serialized_content = match postcard::to_stdvec(&sync_message) {
91 Ok(data) => data,
92 Err(e) => {
93 let error = format!("Failed to serialize sync test message: {e}");
94 return test.with_result(TestResult::Failed { error });
95 }
96 };
97
98 use rand::SeedableRng;
99 let mut rng = rand::rngs::StdRng::from_entropy();
100 let temp_keypair = KeyPair::generate_ed25519(&mut rng);
101
102 let message = Message::MessageV0(MessageV0 {
103 header: MessageV0Header {
104 sender: temp_keypair.public_key(),
105 when: SystemTime::now()
106 .duration_since(UNIX_EPOCH)
107 .unwrap()
108 .as_secs(),
109 kind: Kind::Ephemeral(3600), tags: vec![Tag::Protected],
111 },
112 content: Content::Raw(serialized_content),
113 });
114
115 let message_full = match MessageFull::new(message, &temp_keypair) {
116 Ok(msg) => msg,
117 Err(e) => {
118 let error = format!("Failed to create sync test MessageFull: {e}");
119 return test.with_result(TestResult::Failed { error });
120 }
121 };
122
123 let message_manager = client.message_manager();
125 match message_manager.publish(message_full).await {
126 Ok(_) => {
127 test.add_detail("✓ Published message for sync verification");
128 }
129 Err(e) => {
130 let error = format!("Failed to publish sync test message: {e}");
131 return test.with_result(TestResult::Failed { error });
132 }
133 }
134
135 sleep(Duration::from_millis(500)).await;
137
138 if sync_message.verify_integrity() {
140 test.add_detail("✓ Message data integrity maintained during sync");
141 } else {
142 let error = "Message integrity check failed after sync".to_string();
143 return test.with_result(TestResult::Failed { error });
144 }
145
146 let _storage = client.storage();
148 test.add_detail("✓ Local storage accessible after sync operation");
149
150 info!("Message sync verification completed successfully");
151 test.with_result(TestResult::Passed)
152}
153
154async fn test_sync_connection_stability(client: &Client, _config: &SystemCheckConfig) -> TestInfo {
156 let mut test = TestInfo::new("Sync Connection Stability");
157
158 debug!("Testing connection stability during sync operations...");
159
160 if !client.has_connected_relays().await {
162 let error = "No relay connections available for stability testing".to_string();
163 return test.with_result(TestResult::Failed { error });
164 }
165
166 let initial_status = match client.get_relay_status().await {
167 Ok(status) => status,
168 Err(e) => {
169 let error = format!("Failed to get initial relay status: {e}");
170 return test.with_result(TestResult::Failed { error });
171 }
172 };
173
174 let connected_count = initial_status
175 .iter()
176 .filter(|s| matches!(s.status, crate::RelayConnectionStatus::Connected { .. }))
177 .count();
178
179 test.add_detail(format!(
180 "✓ Initial connection state: {connected_count} relays connected"
181 ));
182
183 for i in 0..3 {
185 let test_message = SyncTestMessage::new_offline(format!("stability_test_{i}"), 128);
187
188 let serialized_content = match postcard::to_stdvec(&test_message) {
189 Ok(data) => data,
190 Err(e) => {
191 warn!("Failed to serialize stability test message {}: {}", i, e);
192 continue;
193 }
194 };
195
196 use rand::SeedableRng;
197 let mut rng = rand::rngs::StdRng::from_entropy();
198 let temp_keypair = KeyPair::generate_ed25519(&mut rng);
199
200 let message = Message::MessageV0(MessageV0 {
201 header: MessageV0Header {
202 sender: temp_keypair.public_key(),
203 when: SystemTime::now()
204 .duration_since(UNIX_EPOCH)
205 .unwrap()
206 .as_secs(),
207 kind: Kind::Ephemeral(300), tags: vec![Tag::Protected],
209 },
210 content: Content::Raw(serialized_content),
211 });
212
213 let message_full = match MessageFull::new(message, &temp_keypair) {
214 Ok(msg) => msg,
215 Err(e) => {
216 warn!("Failed to create stability test MessageFull {}: {}", i, e);
217 continue;
218 }
219 };
220
221 let message_manager = client.message_manager();
223 match message_manager.publish(message_full).await {
224 Ok(_) => {
225 test.add_detail(format!("✓ Stability test {i} completed"));
226 }
227 Err(e) => {
228 warn!("Stability test {} failed: {}", i, e);
229 }
231 }
232
233 sleep(Duration::from_millis(100)).await;
235 }
236
237 if client.has_connected_relays().await {
239 test.add_detail("✓ Connection remained stable during sync operations");
240
241 match client.get_relay_status().await {
243 Ok(final_status) => {
244 let final_connected = final_status
245 .iter()
246 .filter(|s| matches!(s.status, crate::RelayConnectionStatus::Connected { .. }))
247 .count();
248
249 test.add_detail(format!(
250 "✓ Final connection state: {final_connected} relays connected"
251 ));
252
253 if final_connected >= connected_count {
254 test.add_detail("✓ Connection stability maintained");
255 } else {
256 test.add_detail("âš Some connections were lost during testing");
257 }
258 }
259 Err(e) => {
260 warn!("Failed to get final relay status: {}", e);
261 }
262 }
263 } else {
264 let error = "Connection lost during sync stability testing".to_string();
265 return test.with_result(TestResult::Failed { error });
266 }
267
268 info!("Sync connection stability test completed successfully");
269 test.with_result(TestResult::Passed)
270}