use anyhow::Result;
use serde_json::Value;
use std::env;
use crate::assert::engine::AssertionResult;
use crate::plugins::{
Plugin, PluginContext, PluginPurity, PluginResult, PluginReturnKind, PluginSignature,
};
#[derive(Debug, Clone, Default)]
pub struct EnvPlugin;
impl Plugin for EnvPlugin {
fn name(&self) -> &'static str {
"env"
}
fn description(&self) -> &'static str {
"Read environment variable value"
}
fn signature(&self) -> PluginSignature {
PluginSignature {
return_kind: PluginReturnKind::String,
purity: PluginPurity::ContextDependent,
deterministic: false,
idempotent: false,
safe_for_rewrite: false,
arg_names: &["name"],
}
}
fn execute(&self, args: &[Value], _context: &PluginContext) -> Result<PluginResult> {
if args.is_empty() {
return Ok(PluginResult::Assertion(AssertionResult::fail(
"@env requires 1 argument: the variable name",
)));
}
if args.len() > 1 {
return Ok(PluginResult::Assertion(AssertionResult::fail(
"@env accepts only 1 argument",
)));
}
let var_name = match &args[0] {
Value::String(name) => name,
_ => {
return Ok(PluginResult::Assertion(AssertionResult::fail(
"@env argument must be a string",
)));
}
};
match env::var(var_name) {
Ok(value) => Ok(PluginResult::Value(Value::String(value))),
Err(_) => Ok(PluginResult::Value(Value::Null)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
#[test]
fn test_env_plugin_exists() {
let plugin = EnvPlugin;
unsafe {
env::set_var("TEST_VAR", "test_value");
}
let result = plugin
.execute(
&[Value::String("TEST_VAR".to_string())],
&PluginContext {
response: &Value::Null,
headers: None,
trailers: None,
},
)
.unwrap();
assert!(matches!(result, PluginResult::Value(Value::String(s)) if s == "test_value"));
unsafe {
env::remove_var("TEST_VAR");
}
}
#[test]
fn test_env_plugin_not_exists() {
let plugin = EnvPlugin;
let result = plugin
.execute(
&[Value::String("NONEXISTENT_VAR_12345".to_string())],
&PluginContext {
response: &Value::Null,
headers: None,
trailers: None,
},
)
.unwrap();
assert!(matches!(result, PluginResult::Value(Value::Null)));
}
#[test]
fn test_env_plugin_no_args() {
let plugin = EnvPlugin;
let result = plugin
.execute(
&[],
&PluginContext {
response: &Value::Null,
headers: None,
trailers: None,
},
)
.unwrap();
assert!(matches!(
result,
PluginResult::Assertion(AssertionResult::Fail { .. })
));
}
#[test]
fn test_env_plugin_too_many_args() {
let plugin = EnvPlugin;
let result = plugin
.execute(
&[
Value::String("VAR1".to_string()),
Value::String("VAR2".to_string()),
],
&PluginContext {
response: &Value::Null,
headers: None,
trailers: None,
},
)
.unwrap();
assert!(matches!(
result,
PluginResult::Assertion(AssertionResult::Fail { .. })
));
}
#[test]
fn test_env_plugin_wrong_type() {
let plugin = EnvPlugin;
let result = plugin
.execute(
&[Value::Number(123.into())],
&PluginContext {
response: &Value::Null,
headers: None,
trailers: None,
},
)
.unwrap();
assert!(matches!(
result,
PluginResult::Assertion(AssertionResult::Fail { .. })
));
}
#[test]
fn test_env_plugin_name() {
let plugin = EnvPlugin;
assert_eq!(plugin.name(), "env");
}
#[test]
fn test_env_plugin_description() {
let plugin = EnvPlugin;
assert!(plugin.description().contains("environment"));
}
}