Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_sys/tests/parse.rs

5.4 KiB, 2 runs

created by r1870400018:10598, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1//! Integration tests for the `/proc` parsers. Each test uses a
2//! fixed sample body copied from a real machine so the parsers
3//! are exercised deterministically, regardless of the host the
4//! test happens to run on.
5
6use oxedyne_fe2o3_core::prelude::*;
7use oxedyne_fe2o3_sys::{
8 cpu::CpuTimes,
9 disk::DiskStats,
10 load::LoadAvg,
11 mem::MemInfo,
12 net::NetStats,
13 proc_self::ProcSelf,
14 uptime::Uptime,
15};
16
17#[test]
18fn cpu_aggregate_line() -> Outcome<()> {
19 let sample =
20 "cpu 100 20 40 500 10 0 5 0 0 0\n\
21 cpu0 50 10 20 250 5 0 2 0 0 0\n\
22 cpu1 50 10 20 250 5 0 3 0 0 0\n\
23 intr 123\n";
24 let c = res!(CpuTimes::from_stat(sample));
25 assert_eq!(c.user, 100);
26 assert_eq!(c.nice, 20);
27 assert_eq!(c.system, 40);
28 assert_eq!(c.idle, 500);
29 assert_eq!(c.iowait, 10);
30 assert_eq!(c.irq, 0);
31 assert_eq!(c.softirq, 5);
32 assert_eq!(c.total(), 675);
33 assert_eq!(c.idle_total(), 510);
34 Ok(())
35}
36
37#[test]
38fn cpu_busy_fraction() -> Outcome<()> {
39 let prev = res!(CpuTimes::from_line("cpu 100 0 50 850 0 0 0 0 0 0"));
40 let now = res!(CpuTimes::from_line("cpu 150 0 100 900 0 0 0 0 0 0"));
41 // total prev = 1000, now = 1150 → delta 150
42 // idle prev = 850, now = 900 → delta 50
43 // busy / total = 100 / 150 ≈ 0.6667
44 let frac = now.busy_fraction(&prev);
45 assert!((frac - (100.0 / 150.0)).abs() < 1e-9);
46 Ok(())
47}
48
49#[test]
50fn meminfo_parses_total_and_available() -> Outcome<()> {
51 let sample =
52 "MemTotal: 8000000 kB\n\
53 MemFree: 500000 kB\n\
54 MemAvailable: 2000000 kB\n\
55 Buffers: 100000 kB\n\
56 Cached: 1500000 kB\n\
57 SwapTotal: 1000000 kB\n\
58 SwapFree: 900000 kB\n";
59 let m = res!(MemInfo::from_meminfo(sample));
60 assert_eq!(m.total, 8_000_000 * 1024);
61 assert_eq!(m.available, 2_000_000 * 1024);
62 assert_eq!(m.swap_total,1_000_000 * 1024);
63 assert_eq!(m.swap_free, 900_000 * 1024);
64 assert_eq!(m.swap_used(), 100_000 * 1024);
65 // used = total - available = 6M kB.
66 assert_eq!(m.used(), 6_000_000 * 1024);
67 Ok(())
68}
69
70#[test]
71fn loadavg_parses() -> Outcome<()> {
72 let l = res!(LoadAvg::from_line("0.42 0.51 0.63 3/612 12345"));
73 assert!((l.one - 0.42).abs() < 1e-9);
74 assert!((l.five - 0.51).abs() < 1e-9);
75 assert!((l.fifteen - 0.63).abs() < 1e-9);
76 assert_eq!(l.runnable, 3);
77 assert_eq!(l.total, 612);
78 Ok(())
79}
80
81#[test]
82fn uptime_parses() -> Outcome<()> {
83 let u = res!(Uptime::from_line("12345.67 98765.43"));
84 assert!((u.seconds - 12345.67).abs() < 1e-3);
85 assert!((u.idle_total - 98765.43).abs() < 1e-3);
86 Ok(())
87}
88
89#[test]
90fn diskstats_parses_minimum_column_count() -> Outcome<()> {
91 // 14-column diskstats line (kernel 4.18+).
92 let sample =
93 " 8 0 sda 100 0 2000 50 200 0 4000 80 0 120 130\n\
94 254 0 dm-0 10 0 200 5 20 0 400 8 0 12 13\n";
95 let d = res!(DiskStats::from_diskstats(sample));
96 assert_eq!(d.devices.len(), 2);
97 assert_eq!(d.devices[0].name, "sda");
98 assert_eq!(d.devices[0].reads, 100);
99 assert_eq!(d.devices[0].read_sectors, 2000);
100 assert_eq!(d.devices[0].writes, 200);
101 assert_eq!(d.devices[0].write_sectors, 4000);
102 assert_eq!(d.devices[1].name, "dm-0");
103 Ok(())
104}
105
106#[test]
107fn net_dev_parses() -> Outcome<()> {
108 let sample =
109 "Inter-| Receive | Transmit\n\
110 face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n\
111 lo: 1000 10 0 0 0 0 0 0 1000 10 0 0 0 0 0 0\n\
112 eth0: 5000 50 1 2 0 0 0 0 6000 60 0 0 0 0 0 0\n";
113 let n = res!(NetStats::from_net_dev(sample));
114 assert_eq!(n.interfaces.len(), 2);
115 assert_eq!(n.interfaces[0].name, "lo");
116 assert_eq!(n.interfaces[0].rx_bytes, 1000);
117 assert_eq!(n.interfaces[0].tx_bytes, 1000);
118 assert_eq!(n.interfaces[1].name, "eth0");
119 assert_eq!(n.interfaces[1].rx_errors, 1);
120 assert_eq!(n.interfaces[1].rx_drops, 2);
121 assert_eq!(n.interfaces[1].tx_bytes, 6000);
122 Ok(())
123}
124
125#[test]
126fn proc_self_status_parses() -> Outcome<()> {
127 let sample =
128 "Name:\tsteel\n\
129 State:\tR (running)\n\
130 VmPeak:\t 12345 kB\n\
131 VmSize:\t 10000 kB\n\
132 VmRSS:\t 4000 kB\n\
133 Threads:\t8\n\
134 voluntary_ctxt_switches:\t1234\n\
135 nonvoluntary_ctxt_switches:\t56\n";
136 let p = res!(ProcSelf::from_status(sample));
137 assert_eq!(p.rss_bytes, 4_000 * 1024);
138 assert_eq!(p.vsize_bytes, 10_000 * 1024);
139 assert_eq!(p.peak_rss, 12_345 * 1024);
140 assert_eq!(p.threads, 8);
141 assert_eq!(p.voluntary_ctxt, 1234);
142 assert_eq!(p.involuntary_ctxt, 56);
143 Ok(())
144}
145
146#[test]
147fn proc_self_stat_cpu_ticks_parses() -> Outcome<()> {
148 // A synthetic /proc/self/stat line whose comm field deliberately
149 // contains spaces and brackets to exercise the "parse after the
150 // final ')'" logic. utime is field 14 (value 30) and stime is
151 // field 15 (value 12), so the sum is 42.
152 let sample = "1234 (odd )name) ) R 1 1234 1234 0 -1 4194560 100 0 0 0 30 12 0 0 20 0 8 0 999";
153 let ticks = res!(ProcSelf::cpu_ticks_from_stat(sample));
154 assert_eq!(ticks, 42);
155 Ok(())
156}