1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
//! The default picker for runt test suites that gathers tests to run from a
//! runt.toml file.
use serde::Deserialize;
use std::{
path::{Path, PathBuf},
time::Duration,
};
use crate::{errors, executor::suite};
/// Configuration for a single runt run.
/// Tests suites for this runt configuration
#[derive(Debug, Deserialize)]
pub struct Config {
/// Version of the runt tool this configuration is compatible with.
pub ver: String,
/// Test suite configurations.
pub tests: Vec<SuiteConfig>,
}
/// Configuration for a test suite.
#[derive(Debug, Deserialize)]
pub struct SuiteConfig {
/// Name of this TestSuite
pub name: String,
/// Paths of input files.
pub paths: Vec<String>,
/// Command to execute. The pattern `{}` in this string is replaced with
/// the matching path.
pub cmd: String,
/// Optional directory to store the generated .expect files.
pub expect_dir: Option<PathBuf>,
/// Optional timeout
pub timeout: Option<u64>,
}
impl Config {
/// Create a configuration by reading a `runt.toml` file.
/// Ensures that the version number specified in the `runt.toml` matches
/// the version of the installed `runt` binary.
pub fn from_path(conf_dir: &Path) -> Result<Self, errors::RuntError> {
// Error if runt.toml doesn't exist.
let conf_path = conf_dir.join("runt.toml");
let contents = &std::fs::read_to_string(&conf_path).map_err(|_| {
errors::RuntError(format!(
"{} is missing. Runt expects a directory with a runt.toml file.",
conf_path.to_str().unwrap()
))
})?;
let conf: Config = toml::from_str(contents).map_err(|err| {
errors::RuntError(format!(
"Failed to parse {}: {}",
conf_path.to_str().unwrap(),
err
))
})?;
// Check if the current `runt` matches the version specified in
// the configuration.
if env!("CARGO_PKG_VERSION") != conf.ver {
return Err(errors::RuntError(format!("Runt version mismatch. Configuration requires: {}, tool version: {}.\nRun `cargo install runt` to get the latest version of runt.", conf.ver, env!("CARGO_PKG_VERSION"))));
}
Ok(conf)
}
}
impl From<SuiteConfig> for suite::Suite {
/// Transform a list of glob patterns into matching paths and
/// list of errors.
fn from(conf: SuiteConfig) -> Self {
// Arcane sorcery
let all_paths = conf
.paths
.into_iter()
.map(|pattern| glob::glob(&pattern))
.collect::<Result<Vec<_>, glob::PatternError>>()
.expect("Glob pattern error")
.into_iter()
.flat_map(|paths| paths.collect::<Vec<_>>())
.collect::<Result<Vec<_>, _>>()
.expect("Failed to read globbed path");
suite::Suite {
paths: all_paths,
config: suite::Config {
name: conf.name,
cmd: conf.cmd,
expect_dir: conf.expect_dir,
timeout: Duration::from_secs(conf.timeout.unwrap_or(1200)),
},
}
}
}