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)] |
7 | mod 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 | |