1use std::path::PathBuf;
22
23#[derive(Debug, Clone)]
25pub struct MockPeerBuilder {
26 peer_id: String,
27 reputation_score: f64,
28 latency_ms: f64,
29 bandwidth_bps: u64,
30 is_online: bool,
31}
32
33impl MockPeerBuilder {
34 #[inline]
36 pub fn new(peer_id: impl Into<String>) -> Self {
37 Self {
38 peer_id: peer_id.into(),
39 reputation_score: 0.5,
40 latency_ms: 50.0,
41 bandwidth_bps: 10 * 1024 * 1024, is_online: true,
43 }
44 }
45
46 #[inline]
48 pub fn with_reputation(mut self, score: f64) -> Self {
49 self.reputation_score = score.clamp(0.0, 1.0);
50 self
51 }
52
53 #[inline]
55 pub fn with_latency(mut self, latency_ms: f64) -> Self {
56 self.latency_ms = latency_ms;
57 self
58 }
59
60 #[inline]
62 pub fn with_bandwidth(mut self, bandwidth_bps: u64) -> Self {
63 self.bandwidth_bps = bandwidth_bps;
64 self
65 }
66
67 #[inline]
69 pub fn online(mut self, is_online: bool) -> Self {
70 self.is_online = is_online;
71 self
72 }
73
74 #[inline]
76 pub fn build(self) -> MockPeer {
77 MockPeer {
78 peer_id: self.peer_id,
79 reputation_score: self.reputation_score,
80 latency_ms: self.latency_ms,
81 bandwidth_bps: self.bandwidth_bps,
82 is_online: self.is_online,
83 }
84 }
85}
86
87#[derive(Debug, Clone)]
89pub struct MockPeer {
90 pub peer_id: String,
92 pub reputation_score: f64,
94 pub latency_ms: f64,
96 pub bandwidth_bps: u64,
98 pub is_online: bool,
100}
101
102pub struct TempDir {
104 path: PathBuf,
105}
106
107impl TempDir {
108 pub fn new(prefix: &str) -> std::io::Result<Self> {
110 let path =
111 std::env::temp_dir().join(format!("chie-test-{}-{}", prefix, rand::random::<u64>()));
112 std::fs::create_dir_all(&path)?;
113 Ok(Self { path })
114 }
115
116 #[inline]
118 pub fn path(&self) -> &PathBuf {
119 &self.path
120 }
121
122 #[inline]
124 pub fn path_str(&self) -> &str {
125 self.path.to_str().unwrap()
126 }
127}
128
129impl Drop for TempDir {
130 fn drop(&mut self) {
131 let _ = std::fs::remove_dir_all(&self.path);
132 }
133}
134
135#[inline]
137pub fn random_cid() -> String {
138 format!("Qm{:x}", rand::random::<u128>())
139}
140
141#[inline]
143pub fn random_peer_id() -> String {
144 format!("peer-{:x}", rand::random::<u64>())
145}
146
147pub fn random_bytes(size: usize) -> Vec<u8> {
149 (0..size).map(|_| rand::random::<u8>()).collect()
150}
151
152#[inline]
154pub fn assert_approx_eq(a: f64, b: f64, epsilon: f64) {
155 assert!(
156 (a - b).abs() < epsilon,
157 "Expected {} ≈ {}, diff: {}",
158 a,
159 b,
160 (a - b).abs()
161 );
162}
163
164pub struct MockConfig;
166
167impl MockConfig {
168 #[inline]
170 pub fn storage() -> crate::config::StorageSettings {
171 crate::config::StorageSettings::new(
172 PathBuf::from("/tmp/chie-test"),
173 10 * 1024 * 1024 * 1024, )
175 }
176
177 #[inline]
179 pub fn network() -> crate::config::NetworkSettings {
180 crate::config::NetworkSettings::new(100 * 1024 * 1024 / 8) }
182
183 #[inline]
185 pub fn coordinator() -> crate::config::CoordinatorSettings {
186 crate::config::CoordinatorSettings::new("http://localhost:8080".to_string())
187 }
188
189 #[inline]
191 pub fn node_settings() -> crate::config::NodeSettings {
192 crate::config::NodeSettings {
193 storage: Self::storage(),
194 network: Self::network(),
195 coordinator: Self::coordinator(),
196 performance: crate::config::PerformanceSettings::default(),
197 }
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204
205 #[test]
206 fn test_mock_peer_builder() {
207 let peer = MockPeerBuilder::new("peer1")
208 .with_reputation(0.8)
209 .with_latency(100.0)
210 .build();
211
212 assert_eq!(peer.peer_id, "peer1");
213 assert_eq!(peer.reputation_score, 0.8);
214 assert_eq!(peer.latency_ms, 100.0);
215 }
216
217 #[test]
218 fn test_mock_peer_reputation_clamping() {
219 let peer = MockPeerBuilder::new("peer1").with_reputation(1.5).build();
220 assert_eq!(peer.reputation_score, 1.0);
221
222 let peer = MockPeerBuilder::new("peer2").with_reputation(-0.5).build();
223 assert_eq!(peer.reputation_score, 0.0);
224 }
225
226 #[test]
227 fn test_temp_dir_creation() {
228 let temp = TempDir::new("test").unwrap();
229 assert!(temp.path().exists());
230 assert!(temp.path().is_dir());
231 }
232
233 #[test]
234 fn test_temp_dir_cleanup() {
235 let path = {
236 let temp = TempDir::new("cleanup").unwrap();
237 temp.path().clone()
238 };
239 assert!(!path.exists());
241 }
242
243 #[test]
244 fn test_random_cid() {
245 let cid1 = random_cid();
246 let cid2 = random_cid();
247
248 assert!(cid1.starts_with("Qm"));
249 assert_ne!(cid1, cid2); }
251
252 #[test]
253 fn test_random_peer_id() {
254 let peer1 = random_peer_id();
255 let peer2 = random_peer_id();
256
257 assert!(peer1.starts_with("peer-"));
258 assert_ne!(peer1, peer2);
259 }
260
261 #[test]
262 fn test_random_bytes() {
263 let bytes = random_bytes(100);
264 assert_eq!(bytes.len(), 100);
265 }
266
267 #[test]
268 fn test_assert_approx_eq() {
269 assert_approx_eq(1.0, 1.0001, 0.001);
270 assert_approx_eq(0.5, 0.499, 0.01);
271 }
272
273 #[test]
274 #[should_panic]
275 fn test_assert_approx_eq_fails() {
276 assert_approx_eq(1.0, 2.0, 0.001);
277 }
278
279 #[test]
280 fn test_mock_config_storage() {
281 let storage = MockConfig::storage();
282 assert_eq!(storage.max_bytes, 10 * 1024 * 1024 * 1024);
283 }
284
285 #[test]
286 fn test_mock_config_node_settings() {
287 let settings = MockConfig::node_settings();
288 assert!(settings.validate().is_ok());
289 }
290
291 #[test]
292 fn test_mock_peer_online_status() {
293 let peer = MockPeerBuilder::new("peer1").online(false).build();
294 assert!(!peer.is_online);
295
296 let peer = MockPeerBuilder::new("peer2").online(true).build();
297 assert!(peer.is_online);
298 }
299}