1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::env::current_exe;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::process::Command;
7*bb4ee6a4SAndroid Build Coastguard Worker
8*bb4ee6a4SAndroid Build Coastguard Worker /// The tests below require root privileges.
9*bb4ee6a4SAndroid Build Coastguard Worker /// Re-invoke the test binary to execute the specified test with sudo. The test will fail if
10*bb4ee6a4SAndroid Build Coastguard Worker /// passwordless sudo is not available.
call_test_with_sudo(name: &str)11*bb4ee6a4SAndroid Build Coastguard Worker pub fn call_test_with_sudo(name: &str) {
12*bb4ee6a4SAndroid Build Coastguard Worker check_can_sudo();
13*bb4ee6a4SAndroid Build Coastguard Worker
14*bb4ee6a4SAndroid Build Coastguard Worker let result = Command::new("sudo")
15*bb4ee6a4SAndroid Build Coastguard Worker .args([
16*bb4ee6a4SAndroid Build Coastguard Worker "--preserve-env",
17*bb4ee6a4SAndroid Build Coastguard Worker current_exe().unwrap().to_str().unwrap(),
18*bb4ee6a4SAndroid Build Coastguard Worker "--nocapture",
19*bb4ee6a4SAndroid Build Coastguard Worker "--ignored",
20*bb4ee6a4SAndroid Build Coastguard Worker "--exact",
21*bb4ee6a4SAndroid Build Coastguard Worker name,
22*bb4ee6a4SAndroid Build Coastguard Worker ])
23*bb4ee6a4SAndroid Build Coastguard Worker .status()
24*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
25*bb4ee6a4SAndroid Build Coastguard Worker
26*bb4ee6a4SAndroid Build Coastguard Worker if !result.success() {
27*bb4ee6a4SAndroid Build Coastguard Worker panic!("Test {name} failed in child process.");
28*bb4ee6a4SAndroid Build Coastguard Worker }
29*bb4ee6a4SAndroid Build Coastguard Worker }
30*bb4ee6a4SAndroid Build Coastguard Worker
31*bb4ee6a4SAndroid Build Coastguard Worker /// Checks to see if user has entered their password for sudo.
check_can_sudo()32*bb4ee6a4SAndroid Build Coastguard Worker pub fn check_can_sudo() {
33*bb4ee6a4SAndroid Build Coastguard Worker // Try a passwordless sudo first to provide a proper error message.
34*bb4ee6a4SAndroid Build Coastguard Worker // Note: The combination of SUDO_ASKPASS and --askpass will fail if sudo has to ask for a
35*bb4ee6a4SAndroid Build Coastguard Worker // password. When sudo needs to ask for a password, it will call "false" and fail without
36*bb4ee6a4SAndroid Build Coastguard Worker // prompting.
37*bb4ee6a4SAndroid Build Coastguard Worker let can_sudo = Command::new("sudo")
38*bb4ee6a4SAndroid Build Coastguard Worker .args(["--askpass", "true"]) // Use an askpass program to ask for a password
39*bb4ee6a4SAndroid Build Coastguard Worker .env("SUDO_ASKPASS", "false") // Set the askpass program to false
40*bb4ee6a4SAndroid Build Coastguard Worker .output()
41*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
42*bb4ee6a4SAndroid Build Coastguard Worker if !can_sudo.status.success() {
43*bb4ee6a4SAndroid Build Coastguard Worker panic!("This test need to be run as root or with passwordless sudo.");
44*bb4ee6a4SAndroid Build Coastguard Worker }
45*bb4ee6a4SAndroid Build Coastguard Worker }
46*bb4ee6a4SAndroid Build Coastguard Worker
47*bb4ee6a4SAndroid Build Coastguard Worker /// Assert repeatedly until it's true
48*bb4ee6a4SAndroid Build Coastguard Worker ///
49*bb4ee6a4SAndroid Build Coastguard Worker /// Runs the provided `$cond` closure until it returns true. If it does not return true after
50*bb4ee6a4SAndroid Build Coastguard Worker /// `$tries` times, it will panic.
51*bb4ee6a4SAndroid Build Coastguard Worker /// There is no delay between polls, but the `$cond` can sleep as needed.
52*bb4ee6a4SAndroid Build Coastguard Worker #[macro_export]
53*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! poll_assert {
54*bb4ee6a4SAndroid Build Coastguard Worker ($tries: tt, $cond:expr) => {
55*bb4ee6a4SAndroid Build Coastguard Worker $crate::test_utils::poll_assert_impl(stringify!($cond), $tries, $cond)
56*bb4ee6a4SAndroid Build Coastguard Worker };
57*bb4ee6a4SAndroid Build Coastguard Worker }
58*bb4ee6a4SAndroid Build Coastguard Worker
59*bb4ee6a4SAndroid Build Coastguard Worker /// Implementation of [poll_assert]
poll_assert_impl(msg: &'static str, tries: usize, poll_fn: impl Fn() -> bool)60*bb4ee6a4SAndroid Build Coastguard Worker pub fn poll_assert_impl(msg: &'static str, tries: usize, poll_fn: impl Fn() -> bool) {
61*bb4ee6a4SAndroid Build Coastguard Worker for _ in 0..tries {
62*bb4ee6a4SAndroid Build Coastguard Worker if poll_fn() {
63*bb4ee6a4SAndroid Build Coastguard Worker return;
64*bb4ee6a4SAndroid Build Coastguard Worker }
65*bb4ee6a4SAndroid Build Coastguard Worker }
66*bb4ee6a4SAndroid Build Coastguard Worker panic!("Still failing after {} tries: {}", tries, msg);
67*bb4ee6a4SAndroid Build Coastguard Worker }
68