// Copyright 2023 The ChromiumOS Authors1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.34use std::env::current_exe;5use std::process::Command;67/// The tests below require root privileges.8/// Re-invoke the test binary to execute the specified test with sudo. The test will fail if9/// passwordless sudo is not available.10///11/// Warning: If you use this, add your test to ROOT_TESTS in tools/impl/test_config.py12/// This will ensure they are not run when passwordless root is unavailable.13pub fn call_test_with_sudo(name: &str) {14check_can_sudo();1516let result = Command::new("sudo")17.args([18"--preserve-env",19current_exe().unwrap().to_str().unwrap(),20"--nocapture",21"--ignored",22"--exact",23name,24])25.status()26.unwrap();2728if !result.success() {29panic!("Test {name} failed in child process.");30}31}3233/// Checks to see if user has entered their password for sudo.34pub fn check_can_sudo() {35// Try a passwordless sudo first to provide a proper error message.36// Note: The combination of SUDO_ASKPASS and --askpass will fail if sudo has to ask for a37// password. When sudo needs to ask for a password, it will call "false" and fail without38// prompting.39let can_sudo = Command::new("sudo")40.args(["--askpass", "true"]) // Use an askpass program to ask for a password41.env("SUDO_ASKPASS", "false") // Set the askpass program to false42.output()43.unwrap();44if !can_sudo.status.success() {45panic!("This test need to be run as root or with passwordless sudo.");46}47}4849/// Assert repeatedly until it's true50///51/// Runs the provided `$cond` closure until it returns true. If it does not return true after52/// `$tries` times, it will panic.53/// There is no delay between polls, but the `$cond` can sleep as needed.54#[macro_export]55macro_rules! poll_assert {56($tries: tt, $cond:expr) => {57$crate::test_utils::poll_assert_impl(stringify!($cond), $tries, $cond)58};59}6061/// Implementation of [poll_assert]62pub fn poll_assert_impl(msg: &'static str, tries: usize, poll_fn: impl Fn() -> bool) {63for _ in 0..tries {64if poll_fn() {65return;66}67}68panic!("Still failing after {tries} tries: {msg}");69}707172