zoe_client/system_check/
offline_blob.rs1use super::{SystemCheckConfig, TestInfo, TestResult};
8use crate::Client;
9use std::collections::HashMap;
10use tracing::{debug, info};
11
12#[derive(Debug, Clone)]
14pub struct OfflineTestBlob {
15 pub blob_id: String,
16 pub data: Vec<u8>,
17 pub checksum: u32,
18 pub size: usize,
19}
20
21impl OfflineTestBlob {
22 pub fn new(blob_id: String, size: usize) -> Self {
23 use rand::{RngCore, SeedableRng};
24 let mut rng = rand::rngs::StdRng::from_entropy();
25 let data: Vec<u8> = (0..size).map(|_| rng.next_u32() as u8).collect();
26 let checksum = crc32fast::hash(&data);
27
28 Self {
29 blob_id,
30 data,
31 checksum,
32 size,
33 }
34 }
35
36 pub fn verify_integrity(&self) -> bool {
37 self.data.len() == self.size && crc32fast::hash(&self.data) == self.checksum
38 }
39}
40
41pub async fn run_tests(client: &Client, config: &SystemCheckConfig) -> Vec<TestInfo> {
43 let mut tests = Vec::new();
44
45 info!("📁 Running offline blob service tests (no relay connection required)");
46
47 tests.push(test_offline_blob_storage(client, config).await);
49
50 tests.push(test_blob_data_integrity(client, config).await);
52
53 tests
54}
55
56async fn test_offline_blob_storage(client: &Client, config: &SystemCheckConfig) -> TestInfo {
58 let mut test = TestInfo::new("Offline Blob Storage");
59
60 debug!(
61 "Testing offline blob storage with {} KB data...",
62 config.offline_blob_size / 1024
63 );
64
65 let test_blob = OfflineTestBlob::new("offline_blob_test".to_string(), config.offline_blob_size);
67
68 let _blob_service = client.blob_service();
70 test.add_detail("✓ Blob service accessible");
71
72 if test_blob.verify_integrity() {
79 test.add_detail(format!("✓ Generated test blob: {} bytes", test_blob.size));
80 test.add_detail(format!("✓ Blob checksum: {:08x}", test_blob.checksum));
81 } else {
82 let error = "Test blob data integrity check failed".to_string();
83 return test.with_result(TestResult::Failed { error });
84 }
85
86 test.add_detail("✓ Blob service initialized offline");
88
89 info!("Offline blob storage test completed successfully");
90 test.with_result(TestResult::Passed)
91}
92
93async fn test_blob_data_integrity(client: &Client, config: &SystemCheckConfig) -> TestInfo {
95 let mut test = TestInfo::new("Blob Data Integrity");
96
97 debug!("Testing blob data integrity with multiple patterns...");
98
99 let mut test_blobs = HashMap::new();
100
101 let test_patterns = vec![
103 ("zeros", vec![0u8; config.offline_blob_size / 4]),
104 ("ones", vec![0xFFu8; config.offline_blob_size / 4]),
105 (
106 "alternating",
107 (0..config.offline_blob_size / 4)
108 .map(|i| (i % 2) as u8)
109 .collect(),
110 ),
111 ("random", {
112 use rand::{RngCore, SeedableRng};
113 let mut rng = rand::rngs::StdRng::from_entropy();
114 (0..config.offline_blob_size / 4)
115 .map(|_| rng.next_u32() as u8)
116 .collect()
117 }),
118 ];
119
120 for (pattern_name, pattern_data) in &test_patterns {
121 let blob_id = format!("integrity_test_{pattern_name}");
122 let checksum = crc32fast::hash(pattern_data);
123
124 let test_blob = OfflineTestBlob {
125 blob_id: blob_id.clone(),
126 data: pattern_data.clone(),
127 checksum,
128 size: pattern_data.len(),
129 };
130
131 if test_blob.verify_integrity() {
132 test_blobs.insert(blob_id.clone(), test_blob);
133 test.add_detail(format!(
134 "✓ {} pattern: {} bytes, checksum {:08x}",
135 pattern_name,
136 pattern_data.len(),
137 checksum
138 ));
139 } else {
140 let error = format!("Integrity check failed for {pattern_name} pattern");
141 return test.with_result(TestResult::Failed { error });
142 }
143 }
144
145 let mut integrity_checks = 0;
147 for (blob_id, blob) in &test_blobs {
148 if blob.verify_integrity() {
149 integrity_checks += 1;
150 } else {
151 let error = format!("Integrity verification failed for blob: {blob_id}");
152 return test.with_result(TestResult::Failed { error });
153 }
154 }
155
156 test.add_detail(format!("✓ All {integrity_checks} integrity checks passed"));
157
158 let _blob_service = client.blob_service();
160 test.add_detail("✓ Blob service ready for online operations");
161
162 info!("Blob data integrity test completed successfully");
163 test.with_result(TestResult::Passed)
164}