13da5c369Sopenharmony_ciuse cfg_if::cfg_if;
23da5c369Sopenharmony_ci
33da5c369Sopenharmony_ci#[macro_export]
43da5c369Sopenharmony_cimacro_rules! skip {
53da5c369Sopenharmony_ci    ($($reason: expr),+) => {
63da5c369Sopenharmony_ci        use ::std::io::{self, Write};
73da5c369Sopenharmony_ci
83da5c369Sopenharmony_ci        let stderr = io::stderr();
93da5c369Sopenharmony_ci        let mut handle = stderr.lock();
103da5c369Sopenharmony_ci        writeln!(handle, $($reason),+).unwrap();
113da5c369Sopenharmony_ci        return;
123da5c369Sopenharmony_ci    }
133da5c369Sopenharmony_ci}
143da5c369Sopenharmony_ci
153da5c369Sopenharmony_cicfg_if! {
163da5c369Sopenharmony_ci    if #[cfg(any(target_os = "android", target_os = "linux"))] {
173da5c369Sopenharmony_ci        #[macro_export] macro_rules! require_capability {
183da5c369Sopenharmony_ci            ($name:expr, $capname:ident) => {
193da5c369Sopenharmony_ci                use ::caps::{Capability, CapSet, has_cap};
203da5c369Sopenharmony_ci
213da5c369Sopenharmony_ci                if !has_cap(None, CapSet::Effective, Capability::$capname)
223da5c369Sopenharmony_ci                    .unwrap()
233da5c369Sopenharmony_ci                {
243da5c369Sopenharmony_ci                    skip!("{} requires capability {}. Skipping test.", $name, Capability::$capname);
253da5c369Sopenharmony_ci                }
263da5c369Sopenharmony_ci            }
273da5c369Sopenharmony_ci        }
283da5c369Sopenharmony_ci    } else if #[cfg(not(target_os = "redox"))] {
293da5c369Sopenharmony_ci        #[macro_export] macro_rules! require_capability {
303da5c369Sopenharmony_ci            ($name:expr, $capname:ident) => {}
313da5c369Sopenharmony_ci        }
323da5c369Sopenharmony_ci    }
333da5c369Sopenharmony_ci}
343da5c369Sopenharmony_ci
353da5c369Sopenharmony_ci/// Skip the test if we don't have the ability to mount file systems.
363da5c369Sopenharmony_ci#[cfg(target_os = "freebsd")]
373da5c369Sopenharmony_ci#[macro_export]
383da5c369Sopenharmony_cimacro_rules! require_mount {
393da5c369Sopenharmony_ci    ($name:expr) => {
403da5c369Sopenharmony_ci        use ::sysctl::{CtlValue, Sysctl};
413da5c369Sopenharmony_ci        use nix::unistd::Uid;
423da5c369Sopenharmony_ci
433da5c369Sopenharmony_ci        let ctl = ::sysctl::Ctl::new("vfs.usermount").unwrap();
443da5c369Sopenharmony_ci        if !Uid::current().is_root() && CtlValue::Int(0) == ctl.value().unwrap()
453da5c369Sopenharmony_ci        {
463da5c369Sopenharmony_ci            skip!(
473da5c369Sopenharmony_ci                "{} requires the ability to mount file systems. Skipping test.",
483da5c369Sopenharmony_ci                $name
493da5c369Sopenharmony_ci            );
503da5c369Sopenharmony_ci        }
513da5c369Sopenharmony_ci    };
523da5c369Sopenharmony_ci}
533da5c369Sopenharmony_ci
543da5c369Sopenharmony_ci#[cfg(any(target_os = "linux", target_os = "android"))]
553da5c369Sopenharmony_ci#[macro_export]
563da5c369Sopenharmony_cimacro_rules! skip_if_cirrus {
573da5c369Sopenharmony_ci    ($reason:expr) => {
583da5c369Sopenharmony_ci        if std::env::var_os("CIRRUS_CI").is_some() {
593da5c369Sopenharmony_ci            skip!("{}", $reason);
603da5c369Sopenharmony_ci        }
613da5c369Sopenharmony_ci    };
623da5c369Sopenharmony_ci}
633da5c369Sopenharmony_ci
643da5c369Sopenharmony_ci#[cfg(target_os = "freebsd")]
653da5c369Sopenharmony_ci#[macro_export]
663da5c369Sopenharmony_cimacro_rules! skip_if_jailed {
673da5c369Sopenharmony_ci    ($name:expr) => {
683da5c369Sopenharmony_ci        use ::sysctl::{CtlValue, Sysctl};
693da5c369Sopenharmony_ci
703da5c369Sopenharmony_ci        let ctl = ::sysctl::Ctl::new("security.jail.jailed").unwrap();
713da5c369Sopenharmony_ci        if let CtlValue::Int(1) = ctl.value().unwrap() {
723da5c369Sopenharmony_ci            skip!("{} cannot run in a jail. Skipping test.", $name);
733da5c369Sopenharmony_ci        }
743da5c369Sopenharmony_ci    };
753da5c369Sopenharmony_ci}
763da5c369Sopenharmony_ci
773da5c369Sopenharmony_ci#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
783da5c369Sopenharmony_ci#[macro_export]
793da5c369Sopenharmony_cimacro_rules! skip_if_not_root {
803da5c369Sopenharmony_ci    ($name:expr) => {
813da5c369Sopenharmony_ci        use nix::unistd::Uid;
823da5c369Sopenharmony_ci
833da5c369Sopenharmony_ci        if !Uid::current().is_root() {
843da5c369Sopenharmony_ci            skip!("{} requires root privileges. Skipping test.", $name);
853da5c369Sopenharmony_ci        }
863da5c369Sopenharmony_ci    };
873da5c369Sopenharmony_ci}
883da5c369Sopenharmony_ci
893da5c369Sopenharmony_cicfg_if! {
903da5c369Sopenharmony_ci    if #[cfg(any(target_os = "android", target_os = "linux"))] {
913da5c369Sopenharmony_ci        #[macro_export] macro_rules! skip_if_seccomp {
923da5c369Sopenharmony_ci            ($name:expr) => {
933da5c369Sopenharmony_ci                if let Ok(s) = std::fs::read_to_string("/proc/self/status") {
943da5c369Sopenharmony_ci                    for l in s.lines() {
953da5c369Sopenharmony_ci                        let mut fields = l.split_whitespace();
963da5c369Sopenharmony_ci                        if fields.next() == Some("Seccomp:") &&
973da5c369Sopenharmony_ci                            fields.next() != Some("0")
983da5c369Sopenharmony_ci                        {
993da5c369Sopenharmony_ci                            skip!("{} cannot be run in Seccomp mode.  Skipping test.",
1003da5c369Sopenharmony_ci                                stringify!($name));
1013da5c369Sopenharmony_ci                        }
1023da5c369Sopenharmony_ci                    }
1033da5c369Sopenharmony_ci                }
1043da5c369Sopenharmony_ci            }
1053da5c369Sopenharmony_ci        }
1063da5c369Sopenharmony_ci    } else if #[cfg(not(target_os = "redox"))] {
1073da5c369Sopenharmony_ci        #[macro_export] macro_rules! skip_if_seccomp {
1083da5c369Sopenharmony_ci            ($name:expr) => {}
1093da5c369Sopenharmony_ci        }
1103da5c369Sopenharmony_ci    }
1113da5c369Sopenharmony_ci}
1123da5c369Sopenharmony_ci
1133da5c369Sopenharmony_cicfg_if! {
1143da5c369Sopenharmony_ci    if #[cfg(target_os = "linux")] {
1153da5c369Sopenharmony_ci        #[macro_export] macro_rules! require_kernel_version {
1163da5c369Sopenharmony_ci            ($name:expr, $version_requirement:expr) => {
1173da5c369Sopenharmony_ci                use semver::{Version, VersionReq};
1183da5c369Sopenharmony_ci
1193da5c369Sopenharmony_ci                let version_requirement = VersionReq::parse($version_requirement)
1203da5c369Sopenharmony_ci                        .expect("Bad match_version provided");
1213da5c369Sopenharmony_ci
1223da5c369Sopenharmony_ci                let uname = nix::sys::utsname::uname().unwrap();
1233da5c369Sopenharmony_ci                println!("{}", uname.sysname().to_str().unwrap());
1243da5c369Sopenharmony_ci                println!("{}", uname.nodename().to_str().unwrap());
1253da5c369Sopenharmony_ci                println!("{}", uname.release().to_str().unwrap());
1263da5c369Sopenharmony_ci                println!("{}", uname.version().to_str().unwrap());
1273da5c369Sopenharmony_ci                println!("{}", uname.machine().to_str().unwrap());
1283da5c369Sopenharmony_ci
1293da5c369Sopenharmony_ci                // Fix stuff that the semver parser can't handle
1303da5c369Sopenharmony_ci                let fixed_release = &uname.release().to_str().unwrap().to_string()
1313da5c369Sopenharmony_ci                    // Fedora 33 reports version as 4.18.el8_2.x86_64 or
1323da5c369Sopenharmony_ci                    // 5.18.200-fc33.x86_64.  Remove the underscore.
1333da5c369Sopenharmony_ci                    .replace("_", "-")
1343da5c369Sopenharmony_ci                    // Cirrus-CI reports version as 4.19.112+ .  Remove the +
1353da5c369Sopenharmony_ci                    .replace("+", "");
1363da5c369Sopenharmony_ci                let mut version = Version::parse(fixed_release).unwrap();
1373da5c369Sopenharmony_ci
1383da5c369Sopenharmony_ci                //Keep only numeric parts
1393da5c369Sopenharmony_ci                version.pre = semver::Prerelease::EMPTY;
1403da5c369Sopenharmony_ci                version.build = semver::BuildMetadata::EMPTY;
1413da5c369Sopenharmony_ci
1423da5c369Sopenharmony_ci                if !version_requirement.matches(&version) {
1433da5c369Sopenharmony_ci                    skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`",
1443da5c369Sopenharmony_ci                        stringify!($name), version, version_requirement);
1453da5c369Sopenharmony_ci                }
1463da5c369Sopenharmony_ci            }
1473da5c369Sopenharmony_ci        }
1483da5c369Sopenharmony_ci    }
1493da5c369Sopenharmony_ci}
150