1 use cfg_if::cfg_if; 2 3 #[macro_export] macro_rules! skip { 4 ($($reason: expr),+) => { 5 use ::std::io::{self, Write}; 6 7 let stderr = io::stderr(); 8 let mut handle = stderr.lock(); 9 writeln!(handle, $($reason),+).unwrap(); 10 return; 11 } 12 } 13 14 cfg_if! { 15 if #[cfg(any(target_os = "android", target_os = "linux"))] { 16 #[macro_export] macro_rules! require_capability { 17 ($capname:ident) => { 18 use ::caps::{Capability, CapSet, has_cap}; 19 20 if !has_cap(None, CapSet::Effective, Capability::$capname) 21 .unwrap() 22 { 23 skip!("Insufficient capabilities. Skipping test."); 24 } 25 } 26 } 27 } else if #[cfg(not(target_os = "redox"))] { 28 #[macro_export] macro_rules! require_capability { 29 ($capname:ident) => {} 30 } 31 } 32 } 33 34 /// Skip the test if we don't have the ability to mount file systems. 35 #[cfg(target_os = "freebsd")] 36 #[macro_export] macro_rules! require_mount { 37 ($name:expr) => { 38 use ::sysctl::CtlValue; 39 use nix::unistd::Uid; 40 41 if !Uid::current().is_root() && CtlValue::Int(0) == ::sysctl::value("vfs.usermount").unwrap() 42 { 43 skip!("{} requires the ability to mount file systems. Skipping test.", $name); 44 } 45 } 46 } 47 48 #[cfg(any(target_os = "linux", target_os= "android"))] 49 #[macro_export] macro_rules! skip_if_cirrus { 50 ($reason:expr) => { 51 if std::env::var_os("CIRRUS_CI").is_some() { 52 skip!("{}", $reason); 53 } 54 } 55 } 56 57 #[cfg(target_os = "freebsd")] 58 #[macro_export] macro_rules! skip_if_jailed { 59 ($name:expr) => { 60 use ::sysctl::CtlValue; 61 62 if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed") 63 .unwrap() 64 { 65 skip!("{} cannot run in a jail. Skipping test.", $name); 66 } 67 } 68 } 69 70 #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] 71 #[macro_export] macro_rules! skip_if_not_root { 72 ($name:expr) => { 73 use nix::unistd::Uid; 74 75 if !Uid::current().is_root() { 76 skip!("{} requires root privileges. Skipping test.", $name); 77 } 78 }; 79 } 80 81 cfg_if! { 82 if #[cfg(any(target_os = "android", target_os = "linux"))] { 83 #[macro_export] macro_rules! skip_if_seccomp { 84 ($name:expr) => { 85 if let Ok(s) = std::fs::read_to_string("/proc/self/status") { 86 for l in s.lines() { 87 let mut fields = l.split_whitespace(); 88 if fields.next() == Some("Seccomp:") && 89 fields.next() != Some("0") 90 { 91 skip!("{} cannot be run in Seccomp mode. Skipping test.", 92 stringify!($name)); 93 } 94 } 95 } 96 } 97 } 98 } else if #[cfg(not(target_os = "redox"))] { 99 #[macro_export] macro_rules! skip_if_seccomp { 100 ($name:expr) => {} 101 } 102 } 103 } 104 105 cfg_if! { 106 if #[cfg(target_os = "linux")] { 107 #[macro_export] macro_rules! require_kernel_version { 108 ($name:expr, $version_requirement:expr) => { 109 use semver::{Version, VersionReq}; 110 111 let version_requirement = VersionReq::parse($version_requirement) 112 .expect("Bad match_version provided"); 113 114 let uname = nix::sys::utsname::uname(); 115 println!("{}", uname.sysname()); 116 println!("{}", uname.nodename()); 117 println!("{}", uname.release()); 118 println!("{}", uname.version()); 119 println!("{}", uname.machine()); 120 121 // Fix stuff that the semver parser can't handle 122 let fixed_release = &uname.release().to_string() 123 // Fedora 33 reports version as 4.18.el8_2.x86_64 or 124 // 5.18.200-fc33.x86_64. Remove the underscore. 125 .replace("_", "-") 126 // Cirrus-CI reports version as 4.19.112+ . Remove the + 127 .replace("+", ""); 128 let mut version = Version::parse(fixed_release).unwrap(); 129 130 //Keep only numeric parts 131 version.pre = semver::Prerelease::EMPTY; 132 version.build = semver::BuildMetadata::EMPTY; 133 134 if !version_requirement.matches(&version) { 135 skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`", 136 stringify!($name), version, version_requirement); 137 } 138 } 139 } 140 } 141 } 142