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