#![doc = include_str!("../README.md")]
#![allow(unknown_lints)]
#![deny(missing_docs)]
#![deny(rustdoc::broken_intra_doc_links)]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::non_send_fields_in_send_ty)]
#![allow(renamed_and_removed_lints)]
#![allow(clippy::assertions_on_constants)]
#![allow(unknown_lints)]
#[macro_use]
mod macros;
cfg_if::cfg_if! {
if #[cfg(feature = "unknown-ci")] {
mod unknown;
use unknown as sys;
#[cfg(test)]
pub(crate) const MIN_USERS: usize = 0;
} else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
mod apple;
use apple as sys;
mod network_helper_nix;
use network_helper_nix as network_helper;
mod network;
#[cfg(test)]
pub(crate) const MIN_USERS: usize = 1;
} else if #[cfg(windows)] {
mod windows;
use windows as sys;
mod network_helper_win;
use network_helper_win as network_helper;
mod network;
#[cfg(test)]
pub(crate) const MIN_USERS: usize = 1;
} else if #[cfg(any(target_os = "linux", target_os = "android"))] {
mod linux;
use linux as sys;
pub(crate) mod users;
mod network_helper_nix;
use network_helper_nix as network_helper;
mod network;
#[cfg(test)]
pub(crate) const MIN_USERS: usize = 1;
} else if #[cfg(target_os = "freebsd")] {
mod freebsd;
use freebsd as sys;
pub(crate) mod users;
mod network_helper_nix;
use network_helper_nix as network_helper;
mod network;
#[cfg(test)]
pub(crate) const MIN_USERS: usize = 1;
} else {
mod unknown;
use unknown as sys;
#[cfg(test)]
pub(crate) const MIN_USERS: usize = 0;
}
}
pub use common::{
get_current_pid, CpuRefreshKind, DiskType, DiskUsage, Gid, LoadAvg, MacAddr, NetworksIter, Pid,
PidExt, ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Cpu, Disk, NetworkData, Networks, Process, System};
pub use traits::{
ComponentExt, CpuExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, SystemExt, UserExt,
};
#[cfg(feature = "c-interface")]
pub use c_interface::*;
#[cfg(feature = "c-interface")]
mod c_interface;
mod common;
mod debug;
mod system;
mod traits;
mod utils;
pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
cfg_if::cfg_if! {
if #[cfg(all(not(feature = "unknown-ci"), any(target_os = "linux", target_os = "android")))]
{
if _new_limit < 0 {
_new_limit = 0;
}
let max = sys::system::get_max_nb_fds();
if _new_limit > max {
_new_limit = max;
}
unsafe {
if let Ok(ref mut x) = sys::system::REMAINING_FILES.lock() {
let diff = max.saturating_sub(**x);
**x = _new_limit.saturating_sub(diff);
true
} else {
false
}
}
} else {
false
}
}
}
#[cfg(doctest)]
mod doctest {
mod process_clone {}
mod system_clone {}
}
#[cfg(test)]
mod test {
use crate::*;
#[cfg(feature = "unknown-ci")]
#[test]
fn check_unknown_ci_feature() {
assert!(!System::IS_SUPPORTED);
}
#[test]
fn check_process_memory_usage() {
let mut s = System::new();
s.refresh_all();
if System::IS_SUPPORTED {
#[cfg(not(feature = "apple-sandbox"))]
assert!(!s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
} else {
assert!(s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
}
}
#[test]
fn check_memory_usage() {
let mut s = System::new();
assert_eq!(s.total_memory(), 0);
assert_eq!(s.free_memory(), 0);
assert_eq!(s.available_memory(), 0);
assert_eq!(s.used_memory(), 0);
assert_eq!(s.total_swap(), 0);
assert_eq!(s.free_swap(), 0);
assert_eq!(s.used_swap(), 0);
s.refresh_memory();
if System::IS_SUPPORTED {
assert!(s.total_memory() > 0);
assert!(s.used_memory() > 0);
if s.total_swap() > 0 {
assert!(s.free_swap() > 0);
}
} else {
assert_eq!(s.total_memory(), 0);
assert_eq!(s.used_memory(), 0);
assert_eq!(s.total_swap(), 0);
assert_eq!(s.free_swap(), 0);
}
}
#[cfg(target_os = "linux")]
#[test]
fn check_processes_cpu_usage() {
if !System::IS_SUPPORTED {
return;
}
let mut s = System::new();
s.refresh_processes();
assert!(s
.processes()
.iter()
.all(|(_, proc_)| proc_.cpu_usage() == 0.0));
std::thread::sleep(std::time::Duration::from_millis(100));
s.refresh_processes();
assert!(s
.processes()
.iter()
.all(|(_, proc_)| proc_.cpu_usage() >= 0.0
&& proc_.cpu_usage() <= (s.cpus().len() as f32) * 100.0));
assert!(s
.processes()
.iter()
.any(|(_, proc_)| proc_.cpu_usage() > 0.0));
}
#[test]
fn check_cpu_usage() {
if !System::IS_SUPPORTED {
return;
}
let mut s = System::new();
for _ in 0..10 {
s.refresh_cpu();
std::thread::sleep(std::time::Duration::from_millis(100));
if s.cpus().iter().any(|c| c.cpu_usage() > 0.0) {
return;
}
}
panic!("CPU usage is always zero...");
}
#[test]
fn check_users() {
let mut s = System::new();
assert!(s.users().is_empty());
s.refresh_users_list();
assert!(s.users().len() >= MIN_USERS);
let mut s = System::new();
assert!(s.users().is_empty());
s.refresh_all();
assert!(s.users().is_empty());
let s = System::new_all();
assert!(s.users().len() >= MIN_USERS);
}
#[test]
fn check_uid_gid() {
let mut s = System::new();
assert!(s.users().is_empty());
s.refresh_users_list();
let users = s.users();
assert!(users.len() >= MIN_USERS);
if System::IS_SUPPORTED {
#[cfg(not(target_os = "windows"))]
{
let user = users
.iter()
.find(|u| u.name() == "root")
.expect("no root user");
assert_eq!(**user.id(), 0);
assert_eq!(*user.group_id(), 0);
if let Some(user) = users.iter().find(|u| *u.group_id() > 0) {
assert!(**user.id() > 0);
assert!(*user.group_id() > 0);
}
assert!(users.iter().filter(|u| **u.id() > 0).count() > 0);
}
s.refresh_processes();
assert!(s
.processes()
.iter()
.filter_map(|(_, p)| p.user_id())
.any(|uid| s.get_user_by_id(uid).is_some()));
}
}
#[test]
fn check_system_info() {
let s = System::new();
if System::IS_SUPPORTED {
assert!(!s.name().expect("Failed to get system name").is_empty());
assert!(!s
.kernel_version()
.expect("Failed to get kernel version")
.is_empty());
assert!(!s.os_version().expect("Failed to get os version").is_empty());
assert!(!s
.long_os_version()
.expect("Failed to get long OS version")
.is_empty());
}
assert!(!s.distribution_id().is_empty());
}
#[test]
fn check_host_name() {
if System::IS_SUPPORTED {
let s = System::new();
assert!(s.host_name().is_some());
}
}
#[test]
fn check_refresh_process_return_value() {
if System::IS_SUPPORTED {
let _pid = get_current_pid().expect("Failed to get current PID");
#[cfg(not(feature = "apple-sandbox"))]
{
let mut s = System::new();
assert!(s.refresh_process(_pid));
assert!(s.refresh_process(_pid));
}
}
}
#[test]
fn ensure_is_supported_is_set_correctly() {
if MIN_USERS > 0 {
assert!(System::IS_SUPPORTED);
} else {
assert!(!System::IS_SUPPORTED);
}
}
#[test]
fn check_cpus_number() {
let mut s = System::new();
assert!(s.cpus().is_empty());
if System::IS_SUPPORTED {
let physical_cores_count = s
.physical_core_count()
.expect("failed to get number of physical cores");
s.refresh_cpu();
assert!(!s.cpus().is_empty());
let physical_cores_count2 = s
.physical_core_count()
.expect("failed to get number of physical cores");
assert!(physical_cores_count2 <= s.cpus().len());
assert_eq!(physical_cores_count, physical_cores_count2);
} else {
assert_eq!(s.physical_core_count(), None);
}
assert!(s.physical_core_count().unwrap_or(0) <= s.cpus().len());
}
#[test]
fn check_nb_supported_signals() {
if System::IS_SUPPORTED {
assert!(
!System::SUPPORTED_SIGNALS.is_empty(),
"SUPPORTED_SIGNALS shoudn't be empty on supported systems!"
);
} else {
assert!(
System::SUPPORTED_SIGNALS.is_empty(),
"SUPPORTED_SIGNALS should be empty on not support systems!"
);
}
}
#[test]
fn check_cpu_frequency() {
if !System::IS_SUPPORTED {
return;
}
let mut s = System::new();
s.refresh_processes();
for proc_ in s.cpus() {
assert_eq!(proc_.frequency(), 0);
}
s.refresh_cpu();
for proc_ in s.cpus() {
assert_eq!(proc_.frequency(), 0);
}
if std::env::var("APPLE_CI").is_err() && std::env::var("FREEBSD_CI").is_err() {
s.refresh_cpu_specifics(CpuRefreshKind::everything());
for proc_ in s.cpus() {
assert_ne!(proc_.frequency(), 0);
}
}
}
#[test]
fn check_refresh_process_update() {
if !System::IS_SUPPORTED {
return;
}
let mut s = System::new_all();
let total = s.processes().len() as isize;
s.refresh_processes();
let new_total = s.processes().len() as isize;
assert!(
(new_total - total).abs() <= 5,
"{} <= 5",
(new_total - total).abs()
);
}
#[test]
fn check_cmd_line() {
if !System::IS_SUPPORTED {
return;
}
let mut sys = System::new();
sys.refresh_processes_specifics(ProcessRefreshKind::new());
assert!(sys
.processes()
.iter()
.any(|(_, process)| !process.cmd().is_empty()));
}
}