Skip to content

Commit

Permalink
Add tests and #[ignore_missing_env_vars]
Browse files Browse the repository at this point in the history
  • Loading branch information
hansl authored and la10736 committed Sep 26, 2024
1 parent 7dff8f4 commit c65d1c0
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 21 deletions.
13 changes: 12 additions & 1 deletion rstest/tests/resources/rstest/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::PathBuf;

#[rstest]
fn start_with_name(
#[files("${HELLO_WORLD}files/**/*.txt")]
#[files("files/**/*.txt")]
#[exclude("exclude")]
#[files("../files_test_sub_folder/**/*.txt")]
path: PathBuf,
Expand Down Expand Up @@ -33,6 +33,16 @@ fn start_with_name_with_include(
assert!(contents.starts_with(name.to_str().unwrap()))
}

#[rstest]
fn ignore_missing_env_vars(
#[ignore_missing_env_vars]
#[files("files/**/${__SHOULD_NOT_BE_DECLARED__}*.txt")]
#[exclude("exclude")]
path: PathBuf,
) {
let _ = path;
}

mod module {
#[rstest::rstest]
fn pathbuf_need_not_be_in_scope(
Expand All @@ -41,5 +51,6 @@ mod module {
#[include_dot_files]
path: std::path::PathBuf,
) {
let _ = path;
}
}
5 changes: 5 additions & 0 deletions rstest/tests/rstest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ fn files() {
let output = prj.run_tests().unwrap();

TestResults::new()
.ok("ignore_missing_env_vars::path_1_files_element_0_txt")
.ok("ignore_missing_env_vars::path_2_files_element_1_txt")
.ok("ignore_missing_env_vars::path_4_files_element_3_txt")
.ok("ignore_missing_env_vars::path_3_files_element_2_txt")
.ok("ignore_missing_env_vars::path_5_files_sub_sub_dir_file_txt")
.ok("start_with_name::path_1__UP_files_test_sub_folder_from_parent_folder_txt")
.ok("start_with_name::path_2_files_element_0_txt")
.ok("start_with_name::path_3_files_element_1_txt")
Expand Down
68 changes: 48 additions & 20 deletions rstest_macros/src/parse/rstest/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,14 @@ use crate::{
};

/// Replace environment variables in a string.
fn replace_env_vars(attr: &LitStrAttr) -> Result<String, syn::Error> {
// Search-and-replace the `base_dir` for environment variables,
// in the form of `$VAR` or `${VAR}`.

fn replace_env_vars(attr: &LitStrAttr, ignore_missing: bool) -> Result<String, syn::Error> {
let re =
Regex::new(r"\$([a-zA-Z_][a-zA-Z0-9_]*)|\$\{([^}]*)}").expect("Could not build the regex");

let mut result = String::with_capacity(attr.value().len());
let mut last_match = 0;
let path = attr.value();
let haystack = path.as_str();
let mut result = String::with_capacity(attr.value().len());
let mut last_match = 0;

for caps in re.captures_iter(haystack) {
let m = caps.get(0).expect("The regex should have matched");
Expand All @@ -37,12 +34,16 @@ fn replace_env_vars(attr: &LitStrAttr) -> Result<String, syn::Error> {
.expect("The regex should have matched either $VAR or ${VAR}")
.as_str();

let replacement = env::var(var_name).map_err(|_| {
attr.error(&format!(
"Could not find the environment variable {:?}",
var_name
))
})?;
let replacement = match env::var(var_name) {
Ok(val) => val,
Err(_) if ignore_missing => String::new(),
Err(_) => {
return Err(attr.error(&format!(
"Could not find the environment variable {:?}",
var_name
)))
}
};

// Make sure cargo would rerun if the value of this environment variable changes.
println!("cargo::rerun-if-env-changed={var_name}");
Expand All @@ -62,6 +63,7 @@ pub(crate) struct FilesGlobReferences {
glob: Vec<LitStrAttr>,
exclude: Vec<Exclude>,
ignore_dot_files: bool,
ignore_missing_env_vars: bool,
}

impl FilesGlobReferences {
Expand All @@ -70,7 +72,7 @@ impl FilesGlobReferences {
self.glob
.iter()
.map(|attr| {
let path = replace_env_vars(&attr)?;
let path = replace_env_vars(&attr, self.ignore_missing_env_vars)?;
RelativePath::from_path(&path)
.map_err(|e| attr.error(&format!("Invalid glob path: {e}")))
.map(|p| p.to_logical_path(base_dir))
Expand All @@ -95,11 +97,12 @@ impl ToTokens for LitStrAttr {
}

impl FilesGlobReferences {
fn new(glob: Vec<LitStrAttr>, exclude: Vec<Exclude>, ignore_dot_files: bool) -> Self {
fn new(glob: Vec<LitStrAttr>, exclude: Vec<Exclude>, ignore_dot_files: bool, ignore_missing_env_vars: bool) -> Self {
Self {
glob,
exclude,
ignore_dot_files,
ignore_missing_env_vars
}
}

Expand Down Expand Up @@ -166,7 +169,7 @@ impl TryFrom<Attribute> for Exclude {

impl From<Vec<LitStrAttr>> for FilesGlobReferences {
fn from(value: Vec<LitStrAttr>) -> Self {
Self::new(value, Default::default(), true)
Self::new(value, Default::default(), true, false)
}
}

Expand Down Expand Up @@ -237,6 +240,19 @@ impl ValueFilesExtractor {
},
)
}

fn extract_ignore_missing_env_vars(&mut self, node: &mut FnArg) -> Vec<Attribute> {
self.extract_argument_attrs(
node,
|a| attr_is(a, "ignore_missing_env_vars"),
|attr| {
attr.meta
.require_path_only()
.map_err(|_| attr.error("Use #[ignore_missing_env_vars] to ignore missing environment variables"))?;
Ok(attr)
},
)
}
}

impl VisitMut for ValueFilesExtractor {
Expand All @@ -255,10 +271,17 @@ impl VisitMut for ValueFilesExtractor {
.push(attr.error("Cannot use #[include_dot_files] more than once"))
})
}
let ignore_missing_env_vars = self.extract_ignore_missing_env_vars(node);
if !ignore_missing_env_vars.is_empty() {
ignore_missing_env_vars.iter().skip(1).for_each(|attr| {
self.errors
.push(attr.error("Cannot use #[ignore_missing_env_vars] more than once"))
})
}
if !files.is_empty() {
self.files.push((
name,
FilesGlobReferences::new(files, excludes, include_dot_files.is_empty()),
FilesGlobReferences::new(files, excludes, include_dot_files.is_empty(), !ignore_missing_env_vars.is_empty()),
))
} else {
excludes.into_iter().for_each(|e| {
Expand All @@ -271,6 +294,10 @@ impl VisitMut for ValueFilesExtractor {
self.errors
.push(attr.error("You cannot use #[include_dot_files] without #[files(...)]"))
});
ignore_missing_env_vars.into_iter().for_each(|attr| {
self.errors
.push(attr.error("You cannot use #[ignore_missing_env_vars] without #[files(...)]"))
});
}
}
}
Expand Down Expand Up @@ -510,7 +537,8 @@ mod should {
FilesGlobReferences::new(
globs.as_ref().iter().map(files_attr).collect(),
ex.as_ref().iter().map(|&ex| ex.into()).collect(),
*ignore
*ignore,
false
)
))
.collect::<Vec<_>>()
Expand Down Expand Up @@ -670,7 +698,7 @@ mod should {
let values = ValueListFromFiles::new(FakeBaseDir::from(bdir), resolver)
.to_value_list(vec![(
ident("a"),
FilesGlobReferences::new(paths, exclude, ignore_dot_files),
FilesGlobReferences::new(paths, exclude, ignore_dot_files, false),
)])
.unwrap();

Expand Down Expand Up @@ -727,7 +755,7 @@ mod should {
ValueListFromFiles::new(ErrorBaseDir::default(), FakeResolver::default())
.to_value_list(vec![(
ident("a"),
FilesGlobReferences::new(vec![files_attr("no_mater")], Default::default(), true),
FilesGlobReferences::new(vec![files_attr("no_mater")], Default::default(), true, false),
)])
.unwrap();
}
Expand All @@ -738,7 +766,7 @@ mod should {
ValueListFromFiles::new(FakeBaseDir::default(), FakeResolver::default())
.to_value_list(vec![(
ident("a"),
FilesGlobReferences::new(vec![files_attr("no_mater")], Default::default(), true),
FilesGlobReferences::new(vec![files_attr("no_mater")], Default::default(), true, false),
)])
.unwrap();
}
Expand Down

0 comments on commit c65d1c0

Please sign in to comment.