use std::{
env::current_dir,
path::{Path, PathBuf},
};
use log::debug;
use crate::{
cargo_integration::{example_target, example_targets},
runtime::initialize,
test_runner::run_example_test,
};
enum Target {
SrcBase(PathBuf),
Example(String),
Examples,
}
const DEFAULT_EXPECTED_EXIT_STATUS: i32 = 101;
#[derive(Clone)]
pub(super) struct Config {
pub(super) rustc_flags: Vec<String>,
pub(super) dylint_toml: Option<String>,
pub(super) expected_exit_status: i32,
pub(super) normalize_codes: bool,
}
impl Default for Config {
fn default() -> Self {
Self {
rustc_flags: Vec::new(),
dylint_toml: None,
expected_exit_status: DEFAULT_EXPECTED_EXIT_STATUS,
normalize_codes: false,
}
}
}
pub struct Test {
name: String,
target: Target,
config: Config,
}
impl Test {
#[must_use]
pub fn src_base(name: &str, src_base: impl AsRef<Path>) -> Self {
Self::new(name, Target::SrcBase(src_base.as_ref().to_owned()))
}
#[must_use]
pub fn example(name: &str, example: &str) -> Self {
Self::new(name, Target::Example(example.to_owned()))
}
#[must_use]
pub fn examples(name: &str) -> Self {
Self::new(name, Target::Examples)
}
pub fn rustc_flags(
&mut self,
rustc_flags: impl IntoIterator<Item = impl AsRef<str>>,
) -> &mut Self {
self.config
.rustc_flags
.extend(rustc_flags.into_iter().map(|s| s.as_ref().to_owned()));
self
}
pub fn dylint_toml(&mut self, dylint_toml: impl AsRef<str>) -> &mut Self {
self.config.dylint_toml = Some(dylint_toml.as_ref().to_owned());
self
}
pub fn expected_exit_status(&mut self, code: i32) -> &mut Self {
self.config.expected_exit_status = code;
self
}
pub fn normalize_codes(&mut self, normalize_codes: bool) -> &mut Self {
self.config.normalize_codes = normalize_codes;
self
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn run(&mut self) {
self.run_immutable();
}
fn new(name: &str, target: Target) -> Self {
Self {
name: name.to_owned(),
target,
config: Config::default(),
}
}
fn run_immutable(&self) {
debug!(
"run_immutable: Starting run_immutable for library '{}'",
self.name
);
let driver = initialize(&self.name).unwrap();
debug!("run_immutable: Got driver: {}", driver.display());
match &self.target {
Target::SrcBase(src_base) => {
debug!(
"run_immutable: Running SrcBase target with src_base: {}",
src_base.display()
);
crate::test_runner::run_tests(driver, src_base, &self.config)
.expect("run tests failed");
}
Target::Example(example) => {
debug!("run_immutable: Running Example target: {}", example);
let metadata = dylint_internal::cargo::current_metadata().unwrap();
let current_dir = current_dir().unwrap();
let package =
dylint_internal::cargo::package_with_root(&metadata, ¤t_dir).unwrap();
let target = example_target(&package, example).unwrap();
crate::test_runner::run_example_test(
driver,
&metadata,
&package,
&target,
&self.config,
)
.unwrap();
}
Target::Examples => {
let metadata = dylint_internal::cargo::current_metadata().unwrap();
let current_dir = current_dir().unwrap();
let package =
dylint_internal::cargo::package_with_root(&metadata, ¤t_dir).unwrap();
let targets = example_targets(&package).unwrap();
for target in targets {
run_example_test(driver, &metadata, &package, &target, &self.config).unwrap();
}
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[allow(dead_code)]
fn rustc_flags() {
let _ = Test::src_base("name", PathBuf::new()).rustc_flags(["--test"]);
}
}