Skip to content

Commit 4305ea2

Browse files
evaluate environment variable at runtime
1 parent 939ec97 commit 4305ea2

File tree

4 files changed

+100
-24
lines changed

4 files changed

+100
-24
lines changed

Cargo.lock

Lines changed: 41 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
[package]
22
name = "needs_env_var"
3-
version = "1.1.0"
3+
version = "2.0.0"
44
edition = "2021"
5-
description = "Skip compilation if environment variable is missing"
5+
description = "Skip a test if an environment variable is undefined or has a specific value."
66
license = "MIT"
77
repository = "https://github.com/HerrMuellerluedenscheid/needs_env_var"
88
keywords = ["test"]
99

1010
[lib]
1111
proc-macro = true
12+
13+
[dependencies]
14+
syn = { version = "2.0.100", features = ["full"] }
15+
quote = "1.0"
16+

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ Needs Environment Variable
33

44
[![Crates.io Version](https://img.shields.io/crates/v/needs_env_var)](https://crates.io/crates/needs_env_var)
55

6-
Skip code (such as a test) **at compile time** if an environment variable is undefined.
6+
Early return from a test (or method in general) if an environment variable is undefined or does not match a specific value.
77

88
# Example
99

10-
`some_test` will not be compiled if `SOMEENVIRONMENTVARIABLE` is not defined:
10+
`some_test` will be skipped if `SOMEENVIRONMENTVARIABLE` is not defined or does not match `1` (examples 2 & 3).
1111

1212
```rust
1313
use needs_env_var::*;
@@ -32,6 +32,3 @@ fn some_test() {
3232
assert!(1 == 1);
3333
}
3434
```
35-
36-
**Note:** As `needs_env_var` is evaluated at compile time you need to force a re-compilation an environment variable
37-
is defined after compilation, e.g. with `cargo clean`

src/lib.rs

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,58 @@
11
use proc_macro::TokenStream;
2-
use std::env::var;
2+
use quote::quote;
3+
use syn::{
4+
parse::{Parse, ParseStream},
5+
parse_macro_input, ItemFn, LitStr,
6+
};
37

8+
struct InputArgs {
9+
environment_variable: LitStr,
10+
}
11+
12+
impl Parse for InputArgs {
13+
fn parse(input: ParseStream) -> syn::Result<Self> {
14+
let environment_variable = input.parse::<LitStr>()?;
15+
Ok(Self {
16+
environment_variable,
17+
})
18+
}
19+
}
420

5-
/// Skip compilation if the environment variable `env_var` is undefined or if its content does not
6-
/// match the provided value.
721
#[proc_macro_attribute]
8-
pub fn needs_env_var(env_var: TokenStream, input: TokenStream) -> TokenStream {
9-
let macro_string = env_var.to_string().replace(" = ", "=");
10-
let mut parts = macro_string.split('=');
22+
pub fn needs_env_var(attr: TokenStream, item: TokenStream) -> TokenStream {
23+
let input = parse_macro_input!(item as ItemFn);
24+
let input_args = parse_macro_input!(attr as InputArgs);
25+
let environment_variable = input_args.environment_variable.value().replace(" ", "");
1126

12-
let var_str = parts.next().expect("macro needs an environment variable name");
13-
let matches = parts.next();
27+
let (env_var, expected_value): (String, Option<String>) =
28+
match environment_variable.split_once("=") {
29+
Some((key, value)) => (key.to_string(), Some(value.to_string())),
30+
None => (environment_variable.clone(), None),
31+
};
1432

15-
let var_content = var(var_str);
16-
let exists = var_content.is_ok();
33+
let ItemFn {
34+
attrs,
35+
vis,
36+
sig,
37+
block,
38+
} = input;
1739

18-
if !exists || matches.is_some() && matches != var_content.ok().as_deref() {
19-
println!("\x1b[93mskipped. environment variable: \"{}\" did not match or was not set.\x1b[0m", var_str);
20-
return TokenStream::new();
21-
}
22-
input
40+
let expanded = quote! {
41+
#(#attrs)* #vis #sig {
42+
match std::env::var(#env_var) {
43+
Err(_) => {eprintln!("\x1b[93mSkipping test because environment variable {} is not set.\x1b[0m", #env_var);
44+
return;
45+
}
46+
Ok(value) => {
47+
if value != #expected_value {
48+
eprintln!("\x1b[93mSkipping test because environment variable {}={}. Expected: {}.\x1b[0m", #env_var, value, #expected_value);
49+
return;
50+
}
51+
}
52+
};
53+
#block
54+
}
55+
};
56+
57+
TokenStream::from(expanded)
2358
}

0 commit comments

Comments
 (0)