use super::parse::Arg;
use super::parse::CallExpr;
use super::parse::SkipIfArgs;
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum RequiredElement {
EnvVar(String),
}
impl RequiredElement {
pub(crate) fn is_missing(&self) -> bool {
match self {
Self::EnvVar(s) => std::env::var(s).is_err(),
}
}
}
const MISSING_ENV: &str = "missing_env";
impl CallExpr {
fn is_missing_env(&self) -> bool {
self.method == MISSING_ENV
}
}
impl SkipIfArgs {
fn get_required_elements(&self) -> Vec<RequiredElement> {
self.elements
.iter()
.filter_map(|arg| match arg {
Arg::CallExpr(expr) if expr.is_missing_env() => Some(
expr.args
.iter()
.map(ToString::to_string)
.map(RequiredElement::EnvVar),
),
_ => None,
})
.flatten()
.collect()
}
}
#[derive(Debug, PartialEq, Eq)]
pub(crate) struct SkipIf {
pub(crate) required_elements: Vec<RequiredElement>,
}
impl SkipIf {
pub(crate) fn analyze(skipif: SkipIfArgs) -> Self {
let mut required_elements = skipif.get_required_elements();
required_elements.dedup();
Self { required_elements }
}
}
#[cfg(test)]
mod test {
use rstest::rstest;
use super::super::parse::*;
use super::*;
use crate::test::*;
#[rstest]
#[case::single_call_arg(
skip_if_args(vec![call_expr("missing_env", vec!["ENV_VAR"])]),
skipif(vec![required_env_vars(vec!["ENV_VAR"])]),
)]
#[case::multiple_call_args(
skip_if_args(vec![call_expr(
"missing_env",
vec!["ENV_VAR1", "ENV_VAR2", "ENV_VAR3"],
)]),
skipif(vec![required_env_vars(vec![
"ENV_VAR1", "ENV_VAR2", "ENV_VAR3",
])]),
)]
#[case::multiple_instances_of_same_arg(
skip_if_args(vec![
call_expr(
"missing_env",
vec!["ENV_VAR1", "ENV_VAR2", "ENV_VAR3"],
),
call_expr(
"missing_env",
vec!["ENV_VAR3"],
),
]),
skipif(vec![required_env_vars(vec![
"ENV_VAR1", "ENV_VAR2", "ENV_VAR3",
])]),
)]
fn analyze_skipif_args(#[case] input: SkipIfArgs, #[case] expected: SkipIf) {
let actual = SkipIf::analyze(input);
assert_eq!(expected, actual);
for element in actual.required_elements {
assert!(element.is_missing())
}
}
}