view testharness/tests/end2end.rs @ 141:a508a69c068a

Remove a lot of Results from functions. Many functions are documented to only return failing Results when given improper inputs or when there is a memory allocation failure (which can be verified by looking at the source). In cases where we know our input is correct, we don't need to check for memory allocation errors for the same reason that Rust doesn't do so when you, e.g., create a new Vec.
author Paul Fisher <paul@pfish.zone>
date Sat, 05 Jul 2025 17:16:56 -0400
parents 13b4d2a19674
children
line wrap: on
line source

#![cfg(feature = "test-install")]

use std::any::Any;
use std::convert::Infallible;
use std::error::Error;
use std::io;
use std::panic::UnwindSafe;
use std::path::{Path, PathBuf};
use std::{fs, panic};

const PAM_CONFIG: &str = "\
auth required pam_testharness.so
account required pam_testharness.so
password required pam_testharness.so
session required pam_testharness.so
";
const PAM_CONFIG_PATH: &str = "/etc/pam.d/testharness";
const PAM_MODULE_PATH: &str = "/lib/security/pam_testharness.so";

#[derive(Debug, thiserror::Error)]
enum TestError {
    #[error("error in test harness: {0}")]
    HarnessError(#[from] io::Error),
    #[error("panic in test: {0:?}")]
    Panic(Box<dyn Any + Send>),
    #[error(transparent)]
    TestError(anyhow::Error),
}

#[test]
fn test_auth_only() -> Result<(), TestError> {
    harness(|| Ok::<(), Infallible>(()))
}

fn harness<E: Error + Send + Sync + 'static>(
    test: impl Fn() -> Result<(), E> + UnwindSafe,
) -> Result<(), TestError> {
    let dylib_path = test_cdylib::build_current_project();
    let module_path = Path::new(PAM_MODULE_PATH);
    let config_path = Path::new(PAM_CONFIG_PATH);
    let parent = module_path.parent().unwrap();
    fs::create_dir_all(parent)?;
    fs::copy(dylib_path, module_path)?;
    fs::write(config_path, PAM_CONFIG)?;
    panic::catch_unwind(test)
        .map_err(TestError::Panic)?
        .map_err(|e| TestError::TestError(e.into()))?;
    fs::remove_file(module_path)?;
    fs::remove_file(config_path)?;
    // If the /lib/security directory can't be removed, that's OK.
    let _ = fs::remove_dir(parent);
    Ok(())
}