use cfg_if::cfg_if; #[macro_export] macro_rules! skip { ($($reason: expr),+) => { use ::std::io::{self, Write}; let stderr = io::stderr(); let mut handle = stderr.lock(); writeln!(handle, $($reason),+).unwrap(); return; } } cfg_if! { if #[cfg(any(target_os = "android", target_os = "linux"))] { #[macro_export] macro_rules! require_capability { ($name:expr, $capname:ident) => { use ::caps::{Capability, CapSet, has_cap}; if !has_cap(None, CapSet::Effective, Capability::$capname) .unwrap() { skip!("{} requires capability {}. Skipping test.", $name, Capability::$capname); } } } } else if #[cfg(not(target_os = "redox"))] { #[macro_export] macro_rules! require_capability { ($name:expr, $capname:ident) => {} } } } /// Skip the test if we don't have the ability to mount file systems. #[cfg(target_os = "freebsd")] #[macro_export] macro_rules! require_mount { ($name:expr) => { use ::sysctl::{CtlValue, Sysctl}; use nix::unistd::Uid; let ctl = ::sysctl::Ctl::new("vfs.usermount").unwrap(); if !Uid::current().is_root() && CtlValue::Int(0) == ctl.value().unwrap() { skip!( "{} requires the ability to mount file systems. Skipping test.", $name ); } }; } #[cfg(any(target_os = "linux", target_os = "android"))] #[macro_export] macro_rules! skip_if_cirrus { ($reason:expr) => { if std::env::var_os("CIRRUS_CI").is_some() { skip!("{}", $reason); } }; } #[cfg(target_os = "freebsd")] #[macro_export] macro_rules! skip_if_jailed { ($name:expr) => { use ::sysctl::{CtlValue, Sysctl}; let ctl = ::sysctl::Ctl::new("security.jail.jailed").unwrap(); if let CtlValue::Int(1) = ctl.value().unwrap() { skip!("{} cannot run in a jail. Skipping test.", $name); } }; } #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] #[macro_export] macro_rules! skip_if_not_root { ($name:expr) => { use nix::unistd::Uid; if !Uid::current().is_root() { skip!("{} requires root privileges. Skipping test.", $name); } }; } cfg_if! { if #[cfg(any(target_os = "android", target_os = "linux"))] { #[macro_export] macro_rules! skip_if_seccomp { ($name:expr) => { if let Ok(s) = std::fs::read_to_string("/proc/self/status") { for l in s.lines() { let mut fields = l.split_whitespace(); if fields.next() == Some("Seccomp:") && fields.next() != Some("0") { skip!("{} cannot be run in Seccomp mode. Skipping test.", stringify!($name)); } } } } } } else if #[cfg(not(target_os = "redox"))] { #[macro_export] macro_rules! skip_if_seccomp { ($name:expr) => {} } } } cfg_if! { if #[cfg(target_os = "linux")] { #[macro_export] macro_rules! require_kernel_version { ($name:expr, $version_requirement:expr) => { use semver::{Version, VersionReq}; let version_requirement = VersionReq::parse($version_requirement) .expect("Bad match_version provided"); let uname = nix::sys::utsname::uname().unwrap(); println!("{}", uname.sysname().to_str().unwrap()); println!("{}", uname.nodename().to_str().unwrap()); println!("{}", uname.release().to_str().unwrap()); println!("{}", uname.version().to_str().unwrap()); println!("{}", uname.machine().to_str().unwrap()); // Fix stuff that the semver parser can't handle let fixed_release = &uname.release().to_str().unwrap().to_string() // Fedora 33 reports version as 4.18.el8_2.x86_64 or // 5.18.200-fc33.x86_64. Remove the underscore. .replace("_", "-") // Cirrus-CI reports version as 4.19.112+ . Remove the + .replace("+", ""); let mut version = Version::parse(fixed_release).unwrap(); //Keep only numeric parts version.pre = semver::Prerelease::EMPTY; version.build = semver::BuildMetadata::EMPTY; if !version_requirement.matches(&version) { skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`", stringify!($name), version, version_requirement); } } } } }