1use std::collections::HashMap;
16
17use serde::{Deserialize, Serialize};
18
19#[derive(Clone, Debug, Default, Serialize, Deserialize)]
20pub struct NodeCommon {
21 pub addr: String,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub error: Option<String>,
24}
25
26#[derive(Debug, Default, Serialize, Deserialize)]
27pub struct Cpu {
28 pub vendor_id: String,
29 pub family: String,
30 pub model: String,
31 pub stepping: i32,
32 pub physical_id: String,
33 pub model_name: String,
34 pub mhz: f64,
35 pub cache_size: i32,
36 pub flags: Vec<String>,
37 pub microcode: String,
38 pub cores: u64,
39}
40
41#[derive(Debug, Default, Serialize, Deserialize)]
42pub struct CpuFreqStats {
43 name: String,
44 cpuinfo_current_frequency: Option<u64>,
45 cpuinfo_minimum_frequency: Option<u64>,
46 cpuinfo_maximum_frequency: Option<u64>,
47 cpuinfo_transition_latency: Option<u64>,
48 scaling_current_frequency: Option<u64>,
49 scaling_minimum_frequency: Option<u64>,
50 scaling_maximum_frequency: Option<u64>,
51 available_governors: String,
52 driver: String,
53 governor: String,
54 related_cpus: String,
55 set_speed: String,
56}
57
58#[derive(Debug, Default, Serialize, Deserialize)]
59pub struct Cpus {
60 node_common: NodeCommon,
61 cpus: Vec<Cpu>,
62 cpu_freq_stats: Vec<CpuFreqStats>,
63}
64
65pub fn get_cpus() -> Cpus {
66 Cpus::default()
68}
69
70#[derive(Debug, Default, Serialize, Deserialize)]
71pub struct Partition {
72 pub error: String,
73 device: String,
74 model: String,
75 revision: String,
76 mountpoint: String,
77 fs_type: String,
78 mount_options: String,
79 space_total: u64,
80 space_free: u64,
81 inode_total: u64,
82 inode_free: u64,
83}
84
85#[derive(Debug, Default, Serialize, Deserialize)]
86pub struct Partitions {
87 node_common: NodeCommon,
88 partitions: Vec<Partition>,
89}
90
91pub fn get_partitions() -> Partitions {
92 Partitions::default()
93}
94
95#[derive(Debug, Default, Serialize, Deserialize)]
96pub struct OsInfo {
97 node_common: NodeCommon,
98}
99
100pub fn get_os_info() -> OsInfo {
101 OsInfo::default()
102}
103
104#[derive(Debug, Default, Serialize, Deserialize)]
105pub struct ProcInfo {
106 node_common: NodeCommon,
107 pid: i32,
108 is_background: bool,
109 cpu_percent: f64,
110 children_pids: Vec<i32>,
111 cmd_line: String,
112 num_connections: usize,
113 create_time: u64,
114 cwd: String,
115 exec_path: String,
116 gids: Vec<i32>,
117 is_running: bool,
119 mem_percent: f32,
122 name: String,
123 nice: i32,
124 num_fds: i32,
126 num_threads: i32,
127 ppid: i32,
129 status: String,
130 tgid: i32,
131 uids: Vec<i32>,
132 username: String,
133}
134
135pub fn get_proc_info(_addr: &str) -> ProcInfo {
136 ProcInfo::default()
137}
138
139#[derive(Debug, Default, Serialize, Deserialize)]
140pub struct SysService {
141 name: String,
142 status: String,
143}
144
145#[derive(Debug, Default, Serialize, Deserialize)]
146pub struct SysServices {
147 node_common: NodeCommon,
148 services: Vec<SysService>,
149}
150
151pub fn get_sys_services(_add: &str) -> SysServices {
152 SysServices::default()
153}
154
155#[derive(Debug, Default, Serialize, Deserialize)]
156pub struct SysConfig {
157 node_common: NodeCommon,
158 config: HashMap<String, String>,
159}
160
161pub fn get_sys_config(_addr: &str) -> SysConfig {
162 SysConfig::default()
163}
164
165#[derive(Debug, Default, Serialize, Deserialize)]
166pub struct SysErrors {
167 node_common: NodeCommon,
168 errors: Vec<String>,
169}
170
171pub fn get_sys_errors(_add: &str) -> SysErrors {
172 SysErrors::default()
173}
174
175#[derive(Clone, Debug, Default, Serialize, Deserialize)]
176pub struct MemInfo {
177 node_common: NodeCommon,
178 #[serde(skip_serializing_if = "Option::is_none")]
179 total: Option<u64>,
180 #[serde(skip_serializing_if = "Option::is_none")]
181 used: Option<u64>,
182 #[serde(skip_serializing_if = "Option::is_none")]
183 free: Option<u64>,
184 #[serde(skip_serializing_if = "Option::is_none")]
185 available: Option<u64>,
186 #[serde(skip_serializing_if = "Option::is_none")]
187 shared: Option<u64>,
188 #[serde(skip_serializing_if = "Option::is_none")]
189 cache: Option<u64>,
190 #[serde(skip_serializing_if = "Option::is_none")]
191 buffers: Option<u64>,
192 #[serde(rename = "swap_space_total", skip_serializing_if = "Option::is_none")]
193 swap_space_total: Option<u64>,
194 #[serde(rename = "swap_space_free", skip_serializing_if = "Option::is_none")]
195 swap_space_free: Option<u64>,
196 #[serde(skip_serializing_if = "Option::is_none")]
197 limit: Option<u64>,
198}
199
200pub fn get_mem_info(_addr: &str) -> MemInfo {
201 MemInfo::default()
202}
203
204#[cfg(test)]
205mod tests {
206 use super::*;
207 use serde_json;
208
209 #[test]
210 fn test_node_common_creation() {
211 let node = NodeCommon::default();
212 assert!(node.addr.is_empty(), "Default addr should be empty");
213 assert!(node.error.is_none(), "Default error should be None");
214 }
215
216 #[test]
217 fn test_node_common_with_values() {
218 let node = NodeCommon {
219 addr: "127.0.0.1:9000".to_string(),
220 error: Some("Connection failed".to_string()),
221 };
222 assert_eq!(node.addr, "127.0.0.1:9000");
223 assert_eq!(node.error.unwrap(), "Connection failed");
224 }
225
226 #[test]
227 fn test_node_common_serialization() {
228 let node = NodeCommon {
229 addr: "localhost:8080".to_string(),
230 error: None,
231 };
232
233 let json = serde_json::to_string(&node).unwrap();
234 assert!(json.contains("localhost:8080"));
235 assert!(!json.contains("error"), "None error should be skipped in serialization");
236 }
237
238 #[test]
239 fn test_node_common_deserialization() {
240 let json = r#"{"addr":"test.example.com:9000","error":"Test error"}"#;
241 let node: NodeCommon = serde_json::from_str(json).unwrap();
242
243 assert_eq!(node.addr, "test.example.com:9000");
244 assert_eq!(node.error.unwrap(), "Test error");
245 }
246
247 #[test]
248 fn test_cpu_default() {
249 let cpu = Cpu::default();
250 assert!(cpu.vendor_id.is_empty());
251 assert!(cpu.family.is_empty());
252 assert!(cpu.model.is_empty());
253 assert_eq!(cpu.stepping, 0);
254 assert_eq!(cpu.mhz, 0.0);
255 assert_eq!(cpu.cache_size, 0);
256 assert!(cpu.flags.is_empty());
257 assert_eq!(cpu.cores, 0);
258 }
259
260 #[test]
261 fn test_cpu_with_values() {
262 let cpu = Cpu {
263 vendor_id: "GenuineIntel".to_string(),
264 family: "6".to_string(),
265 model: "142".to_string(),
266 stepping: 12,
267 physical_id: "0".to_string(),
268 model_name: "Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz".to_string(),
269 mhz: 1800.0,
270 cache_size: 8192,
271 flags: vec!["fpu".to_string(), "vme".to_string(), "de".to_string()],
272 microcode: "0xf0".to_string(),
273 cores: 4,
274 };
275
276 assert_eq!(cpu.vendor_id, "GenuineIntel");
277 assert_eq!(cpu.cores, 4);
278 assert_eq!(cpu.flags.len(), 3);
279 assert!(cpu.flags.contains(&"fpu".to_string()));
280 }
281
282 #[test]
283 fn test_cpu_serialization() {
284 let cpu = Cpu {
285 vendor_id: "AMD".to_string(),
286 model_name: "AMD Ryzen 7".to_string(),
287 cores: 8,
288 ..Default::default()
289 };
290
291 let json = serde_json::to_string(&cpu).unwrap();
292 assert!(json.contains("AMD"));
293 assert!(json.contains("AMD Ryzen 7"));
294 assert!(json.contains("8"));
295 }
296
297 #[test]
298 fn test_cpu_freq_stats_default() {
299 let stats = CpuFreqStats::default();
300 assert!(stats.name.is_empty());
301 assert!(stats.cpuinfo_current_frequency.is_none());
302 assert!(stats.available_governors.is_empty());
303 assert!(stats.driver.is_empty());
304 }
305
306 #[test]
307 fn test_cpus_structure() {
308 let cpus = Cpus {
309 node_common: NodeCommon {
310 addr: "node1".to_string(),
311 error: None,
312 },
313 cpus: vec![Cpu {
314 vendor_id: "Intel".to_string(),
315 cores: 4,
316 ..Default::default()
317 }],
318 cpu_freq_stats: vec![CpuFreqStats {
319 name: "cpu0".to_string(),
320 cpuinfo_current_frequency: Some(2400),
321 ..Default::default()
322 }],
323 };
324
325 assert_eq!(cpus.node_common.addr, "node1");
326 assert_eq!(cpus.cpus.len(), 1);
327 assert_eq!(cpus.cpu_freq_stats.len(), 1);
328 assert_eq!(cpus.cpus[0].cores, 4);
329 }
330
331 #[test]
332 fn test_get_cpus_function() {
333 let cpus = get_cpus();
334 assert!(cpus.node_common.addr.is_empty());
335 assert!(cpus.cpus.is_empty());
336 assert!(cpus.cpu_freq_stats.is_empty());
337 }
338
339 #[test]
340 fn test_partition_default() {
341 let partition = Partition::default();
342 assert!(partition.error.is_empty());
343 assert!(partition.device.is_empty());
344 assert_eq!(partition.space_total, 0);
345 assert_eq!(partition.space_free, 0);
346 assert_eq!(partition.inode_total, 0);
347 assert_eq!(partition.inode_free, 0);
348 }
349
350 #[test]
351 fn test_partition_with_values() {
352 let partition = Partition {
353 error: "".to_string(),
354 device: "/dev/sda1".to_string(),
355 model: "Samsung SSD".to_string(),
356 revision: "1.0".to_string(),
357 mountpoint: "/".to_string(),
358 fs_type: "ext4".to_string(),
359 mount_options: "rw,relatime".to_string(),
360 space_total: 1000000000,
361 space_free: 500000000,
362 inode_total: 1000000,
363 inode_free: 800000,
364 };
365
366 assert_eq!(partition.device, "/dev/sda1");
367 assert_eq!(partition.fs_type, "ext4");
368 assert_eq!(partition.space_total, 1000000000);
369 assert_eq!(partition.space_free, 500000000);
370 }
371
372 #[test]
373 fn test_partitions_structure() {
374 let partitions = Partitions {
375 node_common: NodeCommon {
376 addr: "storage-node".to_string(),
377 error: None,
378 },
379 partitions: vec![
380 Partition {
381 device: "/dev/sda1".to_string(),
382 mountpoint: "/".to_string(),
383 space_total: 1000000,
384 space_free: 500000,
385 ..Default::default()
386 },
387 Partition {
388 device: "/dev/sdb1".to_string(),
389 mountpoint: "/data".to_string(),
390 space_total: 2000000,
391 space_free: 1500000,
392 ..Default::default()
393 },
394 ],
395 };
396
397 assert_eq!(partitions.partitions.len(), 2);
398 assert_eq!(partitions.partitions[0].device, "/dev/sda1");
399 assert_eq!(partitions.partitions[1].mountpoint, "/data");
400 }
401
402 #[test]
403 fn test_get_partitions_function() {
404 let partitions = get_partitions();
405 assert!(partitions.node_common.addr.is_empty());
406 assert!(partitions.partitions.is_empty());
407 }
408
409 #[test]
410 fn test_os_info_default() {
411 let os_info = OsInfo::default();
412 assert!(os_info.node_common.addr.is_empty());
413 assert!(os_info.node_common.error.is_none());
414 }
415
416 #[test]
417 fn test_get_os_info_function() {
418 let os_info = get_os_info();
419 assert!(os_info.node_common.addr.is_empty());
420 }
421
422 #[test]
423 fn test_proc_info_default() {
424 let proc_info = ProcInfo::default();
425 assert_eq!(proc_info.pid, 0);
426 assert!(!proc_info.is_background);
427 assert_eq!(proc_info.cpu_percent, 0.0);
428 assert!(proc_info.children_pids.is_empty());
429 assert!(proc_info.cmd_line.is_empty());
430 assert_eq!(proc_info.num_connections, 0);
431 assert!(!proc_info.is_running);
432 assert_eq!(proc_info.mem_percent, 0.0);
433 assert!(proc_info.name.is_empty());
434 assert_eq!(proc_info.nice, 0);
435 assert_eq!(proc_info.num_fds, 0);
436 assert_eq!(proc_info.num_threads, 0);
437 assert_eq!(proc_info.ppid, 0);
438 assert!(proc_info.status.is_empty());
439 assert_eq!(proc_info.tgid, 0);
440 assert!(proc_info.uids.is_empty());
441 assert!(proc_info.username.is_empty());
442 }
443
444 #[test]
445 fn test_proc_info_with_values() {
446 let proc_info = ProcInfo {
447 node_common: NodeCommon {
448 addr: "worker-node".to_string(),
449 error: None,
450 },
451 pid: 1234,
452 is_background: true,
453 cpu_percent: 15.5,
454 children_pids: vec![1235, 1236],
455 cmd_line: "rustfs --config /etc/rustfs.conf".to_string(),
456 num_connections: 10,
457 create_time: 1640995200,
458 cwd: "/opt/rustfs".to_string(),
459 exec_path: "/usr/bin/rustfs".to_string(),
460 gids: vec![1000, 1001],
461 is_running: true,
462 mem_percent: 8.2,
463 name: "rustfs".to_string(),
464 nice: 0,
465 num_fds: 25,
466 num_threads: 4,
467 ppid: 1,
468 status: "running".to_string(),
469 tgid: 1234,
470 uids: vec![1000],
471 username: "rustfs".to_string(),
472 };
473
474 assert_eq!(proc_info.pid, 1234);
475 assert!(proc_info.is_background);
476 assert_eq!(proc_info.cpu_percent, 15.5);
477 assert_eq!(proc_info.children_pids.len(), 2);
478 assert_eq!(proc_info.name, "rustfs");
479 assert!(proc_info.is_running);
480 }
481
482 #[test]
483 fn test_get_proc_info_function() {
484 let proc_info = get_proc_info("127.0.0.1:9000");
485 assert_eq!(proc_info.pid, 0);
486 assert!(!proc_info.is_running);
487 }
488
489 #[test]
490 fn test_sys_service_default() {
491 let service = SysService::default();
492 assert!(service.name.is_empty());
493 assert!(service.status.is_empty());
494 }
495
496 #[test]
497 fn test_sys_service_with_values() {
498 let service = SysService {
499 name: "rustfs".to_string(),
500 status: "active".to_string(),
501 };
502
503 assert_eq!(service.name, "rustfs");
504 assert_eq!(service.status, "active");
505 }
506
507 #[test]
508 fn test_sys_services_structure() {
509 let services = SysServices {
510 node_common: NodeCommon {
511 addr: "service-node".to_string(),
512 error: None,
513 },
514 services: vec![
515 SysService {
516 name: "rustfs".to_string(),
517 status: "active".to_string(),
518 },
519 SysService {
520 name: "nginx".to_string(),
521 status: "inactive".to_string(),
522 },
523 ],
524 };
525
526 assert_eq!(services.services.len(), 2);
527 assert_eq!(services.services[0].name, "rustfs");
528 assert_eq!(services.services[1].status, "inactive");
529 }
530
531 #[test]
532 fn test_get_sys_services_function() {
533 let services = get_sys_services("localhost");
534 assert!(services.node_common.addr.is_empty());
535 assert!(services.services.is_empty());
536 }
537
538 #[test]
539 fn test_sys_config_default() {
540 let config = SysConfig::default();
541 assert!(config.node_common.addr.is_empty());
542 assert!(config.config.is_empty());
543 }
544
545 #[test]
546 fn test_sys_config_with_values() {
547 let mut config_map = HashMap::new();
548 config_map.insert("max_connections".to_string(), "1000".to_string());
549 config_map.insert("timeout".to_string(), "30".to_string());
550
551 let config = SysConfig {
552 node_common: NodeCommon {
553 addr: "config-node".to_string(),
554 error: None,
555 },
556 config: config_map,
557 };
558
559 assert_eq!(config.config.len(), 2);
560 assert_eq!(config.config.get("max_connections").unwrap(), "1000");
561 assert_eq!(config.config.get("timeout").unwrap(), "30");
562 }
563
564 #[test]
565 fn test_get_sys_config_function() {
566 let config = get_sys_config("192.168.1.100");
567 assert!(config.node_common.addr.is_empty());
568 assert!(config.config.is_empty());
569 }
570
571 #[test]
572 fn test_sys_errors_default() {
573 let errors = SysErrors::default();
574 assert!(errors.node_common.addr.is_empty());
575 assert!(errors.errors.is_empty());
576 }
577
578 #[test]
579 fn test_sys_errors_with_values() {
580 let errors = SysErrors {
581 node_common: NodeCommon {
582 addr: "error-node".to_string(),
583 error: None,
584 },
585 errors: vec![
586 "Connection timeout".to_string(),
587 "Memory allocation failed".to_string(),
588 "Disk full".to_string(),
589 ],
590 };
591
592 assert_eq!(errors.errors.len(), 3);
593 assert!(errors.errors.contains(&"Connection timeout".to_string()));
594 assert!(errors.errors.contains(&"Disk full".to_string()));
595 }
596
597 #[test]
598 fn test_get_sys_errors_function() {
599 let errors = get_sys_errors("test-node");
600 assert!(errors.node_common.addr.is_empty());
601 assert!(errors.errors.is_empty());
602 }
603
604 #[test]
605 fn test_mem_info_default() {
606 let mem_info = MemInfo::default();
607 assert!(mem_info.node_common.addr.is_empty());
608 assert!(mem_info.total.is_none());
609 assert!(mem_info.used.is_none());
610 assert!(mem_info.free.is_none());
611 assert!(mem_info.available.is_none());
612 assert!(mem_info.shared.is_none());
613 assert!(mem_info.cache.is_none());
614 assert!(mem_info.buffers.is_none());
615 assert!(mem_info.swap_space_total.is_none());
616 assert!(mem_info.swap_space_free.is_none());
617 assert!(mem_info.limit.is_none());
618 }
619
620 #[test]
621 fn test_mem_info_with_values() {
622 let mem_info = MemInfo {
623 node_common: NodeCommon {
624 addr: "memory-node".to_string(),
625 error: None,
626 },
627 total: Some(16777216000),
628 used: Some(8388608000),
629 free: Some(4194304000),
630 available: Some(12582912000),
631 shared: Some(1048576000),
632 cache: Some(2097152000),
633 buffers: Some(524288000),
634 swap_space_total: Some(4294967296),
635 swap_space_free: Some(2147483648),
636 limit: Some(16777216000),
637 };
638
639 assert_eq!(mem_info.total.unwrap(), 16777216000);
640 assert_eq!(mem_info.used.unwrap(), 8388608000);
641 assert_eq!(mem_info.free.unwrap(), 4194304000);
642 assert_eq!(mem_info.swap_space_total.unwrap(), 4294967296);
643 }
644
645 #[test]
646 fn test_mem_info_serialization() {
647 let mem_info = MemInfo {
648 node_common: NodeCommon {
649 addr: "test-node".to_string(),
650 error: None,
651 },
652 total: Some(8000000000),
653 used: Some(4000000000),
654 free: None,
655 available: Some(6000000000),
656 ..Default::default()
657 };
658
659 let json = serde_json::to_string(&mem_info).unwrap();
660 assert!(json.contains("8000000000"));
661 assert!(json.contains("4000000000"));
662 assert!(json.contains("6000000000"));
663 assert!(!json.contains("free"), "None values should be skipped");
664 }
665
666 #[test]
667 fn test_get_mem_info_function() {
668 let mem_info = get_mem_info("memory-server");
669 assert!(mem_info.node_common.addr.is_empty());
670 assert!(mem_info.total.is_none());
671 assert!(mem_info.used.is_none());
672 }
673
674 #[test]
675 fn test_all_structures_debug_format() {
676 let node = NodeCommon::default();
677 let cpu = Cpu::default();
678 let partition = Partition::default();
679 let proc_info = ProcInfo::default();
680 let service = SysService::default();
681 let mem_info = MemInfo::default();
682
683 assert!(!format!("{node:?}").is_empty());
685 assert!(!format!("{cpu:?}").is_empty());
686 assert!(!format!("{partition:?}").is_empty());
687 assert!(!format!("{proc_info:?}").is_empty());
688 assert!(!format!("{service:?}").is_empty());
689 assert!(!format!("{mem_info:?}").is_empty());
690 }
691
692 #[test]
693 fn test_memory_efficiency() {
694 assert!(std::mem::size_of::<NodeCommon>() < 1000);
696 assert!(std::mem::size_of::<Cpu>() < 2000);
697 assert!(std::mem::size_of::<Partition>() < 2000);
698 assert!(std::mem::size_of::<MemInfo>() < 1000);
699 }
700}