1// Take a look at the license at the top of the repository in the LICENSE file.
2
3// Once https://github.com/rust-lang/rfcs/blob/master/text/1422-pub-restricted.md
4// feature gets stabilized, we can move common parts in here.
5
6#[cfg(test)]
7mod tests {
8 use crate::{ProcessExt, System, SystemExt};
9
10 #[test]
11 fn test_refresh_system() {
12 let mut sys = System::new();
13 sys.refresh_system();
14 // We don't want to test on unsupported systems.
15 if System::IS_SUPPORTED {
16 assert!(sys.total_memory() != 0);
17 assert!(sys.free_memory() != 0);
18 }
19 assert!(sys.total_memory() >= sys.free_memory());
20 assert!(sys.total_swap() >= sys.free_swap());
21 }
22
23 #[test]
24 fn test_refresh_process() {
25 let mut sys = System::new();
26 assert!(sys.processes().is_empty(), "no process should be listed!");
27 // We don't want to test on unsupported systems.
28
29 #[cfg(not(feature = "apple-sandbox"))]
30 if System::IS_SUPPORTED {
31 assert!(
32 sys.refresh_process(crate::get_current_pid().expect("failed to get current pid")),
33 "process not listed",
34 );
35 // Ensure that the process was really added to the list!
36 assert!(sys
37 .process(crate::get_current_pid().expect("failed to get current pid"))
38 .is_some());
39 }
40 }
41
42 #[test]
43 fn test_get_process() {
44 let mut sys = System::new();
45 sys.refresh_processes();
46 let current_pid = match crate::get_current_pid() {
47 Ok(pid) => pid,
48 _ => {
49 if !System::IS_SUPPORTED {
50 return;
51 }
52 panic!("get_current_pid should work!");
53 }
54 };
55 if let Some(p) = sys.process(current_pid) {
56 assert!(p.memory() > 0);
57 } else {
58 #[cfg(not(feature = "apple-sandbox"))]
59 assert!(!System::IS_SUPPORTED);
60 }
61 }
62
63 #[test]
64 fn check_if_send_and_sync() {
65 trait Foo {
66 fn foo(&self) {}
67 }
68 impl<T> Foo for T where T: Send {}
69
70 trait Bar {
71 fn bar(&self) {}
72 }
73
74 impl<T> Bar for T where T: Sync {}
75
76 let mut sys = System::new();
77 sys.refresh_processes();
78 let current_pid = match crate::get_current_pid() {
79 Ok(pid) => pid,
80 _ => {
81 if !System::IS_SUPPORTED {
82 return;
83 }
84 panic!("get_current_pid should work!");
85 }
86 };
87 if let Some(p) = sys.process(current_pid) {
88 p.foo(); // If this doesn't compile, it'll simply mean that the Process type
89 // doesn't implement the Send trait.
90 p.bar(); // If this doesn't compile, it'll simply mean that the Process type
91 // doesn't implement the Sync trait.
92 } else {
93 #[cfg(not(feature = "apple-sandbox"))]
94 assert!(!System::IS_SUPPORTED);
95 }
96 }
97
98 #[test]
99 fn check_hostname_has_no_nuls() {
100 let sys = System::new();
101
102 if let Some(hostname) = sys.host_name() {
103 assert!(!hostname.contains('\u{0}'))
104 }
105 }
106
107 #[test]
108 fn check_uptime() {
109 let sys = System::new();
110 let uptime = sys.uptime();
111 if System::IS_SUPPORTED {
112 std::thread::sleep(std::time::Duration::from_millis(1000));
113 let new_uptime = sys.uptime();
114 assert!(uptime < new_uptime);
115 }
116 }
117
118 // This test is used to ensure that the CPU usage computation isn't completely going off
119 // when refreshing it too frequently (ie, multiple times in a row in a very small interval).
120 #[test]
121 #[ignore] // This test MUST be run on its own to prevent wrong CPU usage measurements.
122 fn test_consecutive_cpu_usage_update() {
123 use crate::{PidExt, ProcessExt, ProcessRefreshKind, System, SystemExt};
124 use std::sync::atomic::{AtomicBool, Ordering};
125 use std::sync::Arc;
126 use std::time::Duration;
127
128 if !System::IS_SUPPORTED {
129 return;
130 }
131
132 let mut sys = System::new_all();
133 assert!(!sys.cpus().is_empty());
134 sys.refresh_processes_specifics(ProcessRefreshKind::new().with_cpu());
135
136 let stop = Arc::new(AtomicBool::new(false));
137 // Spawning a few threads to ensure that it will actually have an impact on the CPU usage.
138 for it in 0..sys.cpus().len() / 2 + 1 {
139 let stop_c = Arc::clone(&stop);
140 std::thread::spawn(move || {
141 while !stop_c.load(Ordering::Relaxed) {
142 if it != 0 {
143 // The first thread runs at 100% to be sure it'll be noticeable.
144 std::thread::sleep(Duration::from_millis(1));
145 }
146 }
147 });
148 }
149
150 let mut pids = sys
151 .processes()
152 .iter()
153 .map(|(pid, _)| *pid)
154 .take(2)
155 .collect::<Vec<_>>();
156 let pid = std::process::id();
157 pids.push(PidExt::from_u32(pid));
158 assert_eq!(pids.len(), 3);
159
160 for it in 0..3 {
161 std::thread::sleep(
162 crate::System::MINIMUM_CPU_UPDATE_INTERVAL + Duration::from_millis(1),
163 );
164 for pid in &pids {
165 sys.refresh_process_specifics(*pid, ProcessRefreshKind::new().with_cpu());
166 }
167 // To ensure that Linux doesn't give too high numbers.
168 assert!(
169 sys.process(pids[2]).unwrap().cpu_usage() < sys.cpus().len() as f32 * 100.,
170 "using ALL CPU: failed at iteration {}",
171 it
172 );
173 // To ensure it's not 0 either.
174 assert!(
175 sys.process(pids[2]).unwrap().cpu_usage() > 0.,
176 "using NO CPU: failed at iteration {}",
177 it
178 );
179 }
180 stop.store(false, Ordering::Relaxed);
181 }
182}
183