Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
use std::fs::File;
use std::io::prelude::*;
use std::{env, io};
use tempfile::{tempdir, TempDir};
pub fn tempdir_with_dotenv(dotenv_text: &str) -> io::Result<TempDir> {
env::set_var("EXISTING", "from_env");
let dir = tempdir()?;
env::set_current_dir(dir.path())?;
let dotenv_path = dir.path().join(".env");
let mut dotenv_file = File::create(dotenv_path)?;
dotenv_file.write_all(dotenv_text.as_bytes())?;
dotenv_file.sync_all()?;
Ok(dir)
}
#[allow(dead_code)]
pub fn make_test_dotenv() -> io::Result<TempDir> {
tempdir_with_dotenv("TESTKEY=test_val\nTESTKEY=test_val_overridden\nEXISTING=from_file")
}
@@ -0,0 +1 @@
mod util;
@@ -0,0 +1,69 @@
#![allow(dead_code)]
mod testenv;
use std::env::{self, VarError};
pub use testenv::*;
/// Default key used in envfile
pub const TEST_KEY: &str = "TESTKEY";
/// Default value used in envfile
pub const TEST_VALUE: &str = "test_val";
/// Default existing key set before test is run
pub const TEST_EXISTING_KEY: &str = "TEST_EXISTING_KEY";
/// Default existing value set before test is run
pub const TEST_EXISTING_VALUE: &str = "from_env";
/// Default overriding value in envfile
pub const TEST_OVERRIDING_VALUE: &str = "from_file";
#[inline(always)]
pub fn create_default_envfile() -> String {
format!(
"{}={}\n{}={}",
TEST_KEY, TEST_VALUE, TEST_EXISTING_KEY, TEST_OVERRIDING_VALUE
)
}
/// missing equals
#[inline(always)]
pub fn create_invalid_envfile() -> String {
format!(
"{}{}\n{}{}",
TEST_KEY, TEST_VALUE, TEST_EXISTING_KEY, TEST_OVERRIDING_VALUE
)
}
/// Assert that an environment variable is set and has the expected value.
pub fn assert_env_var(key: &str, expected: &str) {
match env::var(key) {
Ok(actual) => assert_eq!(
expected, actual,
"\n\nFor Environment Variable `{}`:\n EXPECTED: `{}`\n ACTUAL: `{}`\n",
key, expected, actual
),
Err(VarError::NotPresent) => panic!("env var `{}` not found", key),
Err(VarError::NotUnicode(val)) => panic!(
"env var `{}` currently has invalid unicode: `{}`",
key,
val.to_string_lossy()
),
}
}
/// Assert that an environment variable is not currently set.
pub fn assert_env_var_unset(key: &str) {
match env::var(key) {
Ok(actual) => panic!(
"env var `{}` should not be set, currently it is: `{}`",
key, actual
),
Err(VarError::NotUnicode(val)) => panic!(
"env var `{}` should not be set, currently has invalid unicode: `{}`",
key,
val.to_string_lossy()
),
_ => (),
}
}
@@ -0,0 +1,336 @@
use once_cell::sync::OnceCell;
use std::collections::HashMap;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, PoisonError};
use std::{env, fs, io};
use tempfile::{tempdir, TempDir};
use super::*;
/// Env var convenience type.
type EnvMap = HashMap<String, String>;
/// Initialized in [`get_env_locker`]
static ENV_LOCKER: OnceCell<Arc<Mutex<EnvMap>>> = OnceCell::new();
/// A test environment.
///
/// Will create a new temporary directory. Use its builder methods to configure
/// the directory structure, preset variables, envfile name and contents, and
/// the working directory to run the test from.
///
/// Creation methods:
/// - [`TestEnv::init`]: blank environment (no envfile)
/// - [`TestEnv::init_with_envfile`]: blank environment with an envfile
/// - [`TestEnv::default`]: default testing environment (1 existing var and 2
/// set in a `.env` file)
#[derive(Debug)]
pub struct TestEnv {
temp_dir: TempDir,
work_dir: PathBuf,
env_vars: Vec<KeyVal>,
envfile_contents: Option<String>,
envfile_path: PathBuf,
}
/// Simple key value struct for representing environment variables
#[derive(Debug, Clone)]
pub struct KeyVal {
key: String,
value: String,
}
/// Run a test closure within a test environment.
///
/// Resets the environment variables, loads the [`TestEnv`], then runs the test
/// closure. Ensures only one thread has access to the process environment.
pub fn test_in_env<F>(test_env: TestEnv, test: F)
where
F: FnOnce(),
{
let locker = get_env_locker();
// ignore a poisoned mutex
// we expect some tests may panic to indicate a failure
let original_env = locker.lock().unwrap_or_else(PoisonError::into_inner);
// we reset the environment anyway upon acquiring the lock
reset_env(&original_env);
create_env(&test_env);
test();
// drop the lock and the `TestEnv` - should delete the tempdir
}
/// Run a test closure within the default test environment.
///
/// Resets the environment variables, creates the default [`TestEnv`], then runs
/// the test closure. Ensures only one thread has access to the process
/// environment.
///
/// The default testing environment sets an existing environment variable
/// `TEST_EXISTING_KEY`, which is set to `from_env`. It also creates a `.env`
/// file with the two lines:
///
/// ```ini
/// TESTKEY=test_val
/// TEST_EXISTING_KEY=from_file
/// ```
///
/// Notice that file has the potential to override `TEST_EXISTING_KEY` depending
/// on the what's being tested.
pub fn test_in_default_env<F>(test: F)
where
F: FnOnce(),
{
let test_env = TestEnv::default();
test_in_env(test_env, test);
}
impl TestEnv {
/// Blank testing environment in a new temporary directory.
///
/// No envfile_contents or pre-existing variables to set. The envfile_name
/// is set to `.env` but wont be written until its contents is set. The
/// working directory is the created temporary directory.
pub fn init() -> Self {
let tempdir = tempdir().expect("create tempdir");
let work_dir = tempdir.path().to_owned();
let envfile_path = work_dir.join(".env");
Self {
temp_dir: tempdir,
work_dir,
env_vars: Default::default(),
envfile_contents: None,
envfile_path,
}
}
/// Testing environment with custom envfile_contents.
///
/// No pre-existing env_vars set. The envfile_name is set to `.env`. The
/// working directory is the created temporary directory.
pub fn init_with_envfile(contents: impl ToString) -> Self {
let mut test_env = Self::init();
test_env.set_envfile_contents(contents);
test_env
}
/// Change the name of the default `.env` file.
///
/// It will still be placed in the root temporary directory. If you need to
/// put the envfile in a different directory, use
/// [`set_envfile_path`](TestEnv::set_envfile_path) instead.
pub fn set_envfile_name(&mut self, name: impl AsRef<Path>) -> &mut Self {
self.envfile_path = self.temp_path().join(name);
self
}
/// Change the absolute path to the envfile.
pub fn set_envfile_path(&mut self, path: PathBuf) -> &mut Self {
self.envfile_path = path;
self
}
/// Specify the contents of the envfile.
///
/// If this is the only change to the [`TestEnv`] being made, use
/// [`new_with_envfile`](TestEnv::new_with_envfile).
///
/// Setting it to an empty string will cause an empty envfile to be created
pub fn set_envfile_contents(&mut self, contents: impl ToString) -> &mut Self {
self.envfile_contents = Some(contents.to_string());
self
}
/// Set the working directory the test will run from.
///
/// The default is the created temporary directory. This method is useful if
/// you wish to run a test from a subdirectory or somewhere else.
pub fn set_work_dir(&mut self, path: PathBuf) -> &mut Self {
self.work_dir = path;
self
}
/// Add an individual environment variable.
///
/// This adds more pre-existing environment variables to the process before
/// any tests are run.
pub fn add_env_var(&mut self, key: impl ToString, value: impl ToString) -> &mut Self {
self.env_vars.push(KeyVal {
key: key.to_string(),
value: value.to_string(),
});
self
}
/// Set the pre-existing environment variables.
///
/// These variables will get added to the process' environment before the
/// test is run. This overrides any previous env vars added to the
/// [`TestEnv`].
///
/// If you wish to just use a slice of tuples, use
/// [`set_env_vars_tuple`](TestEnv::set_env_vars_tuple) instead.
pub fn set_env_vars(&mut self, env_vars: Vec<KeyVal>) -> &mut Self {
self.env_vars = env_vars;
self
}
/// Set the pre-existing environment variables using [`str`] tuples.
///
/// These variables will get added to the process' environment before the
/// test is run. This overrides any previous env vars added to the
/// [`TestEnv`].
///
/// If you wish to add an owned `Vec<KeyVal>` instead of `str` tuples, use
/// [`set_env_vars`](TestEnv::set_env_vars) instead.
pub fn set_env_vars_tuple(&mut self, env_vars: &[(&str, &str)]) -> &mut Self {
self.env_vars = env_vars
.iter()
.map(|(key, value)| KeyVal {
key: key.to_string(),
value: value.to_string(),
})
.collect();
self
}
/// Create a child folder within the temporary directory.
///
/// This will not change the working directory the test is run in, or where
/// the envfile is created.
///
/// Will create parent directories if they are missing.
pub fn add_child_dir_all(&self, rel_path: impl AsRef<Path>) -> PathBuf {
let rel_path = rel_path.as_ref();
let child_dir = self.temp_path().join(rel_path);
if let Err(err) = fs::create_dir_all(&child_dir) {
panic!(
"unable to create child directory: `{}` in `{}`: {}",
self.temp_path().display(),
rel_path.display(),
err
);
}
child_dir
}
/// Get a reference to the path of the temporary directory.
pub fn temp_path(&self) -> &Path {
self.temp_dir.path()
}
/// Get a reference to the working directory the test will be run from.
pub fn work_dir(&self) -> &Path {
&self.work_dir
}
/// Get a reference to environnement variables that will be set **before**
/// the test.
pub fn env_vars(&self) -> &[KeyVal] {
&self.env_vars
}
/// Get a reference to the string that will be placed in the envfile.
///
/// If `None` is returned, an envfile will not be created
pub fn envfile_contents(&self) -> Option<&str> {
self.envfile_contents.as_deref()
}
/// Get a reference to the path of the envfile.
pub fn envfile_path(&self) -> &Path {
&self.envfile_path
}
}
impl Default for TestEnv {
fn default() -> Self {
let temp_dir = tempdir().expect("create tempdir");
let work_dir = temp_dir.path().to_owned();
let env_vars = vec![KeyVal {
key: TEST_EXISTING_KEY.into(),
value: TEST_EXISTING_VALUE.into(),
}];
let envfile_contents = Some(create_default_envfile());
let envfile_path = work_dir.join(".env");
Self {
temp_dir,
work_dir,
env_vars,
envfile_contents,
envfile_path,
}
}
}
impl From<(&str, &str)> for KeyVal {
fn from(kv: (&str, &str)) -> Self {
let (key, value) = kv;
Self {
key: key.to_string(),
value: value.to_string(),
}
}
}
impl From<(String, String)> for KeyVal {
fn from(kv: (String, String)) -> Self {
let (key, value) = kv;
Self { key, value }
}
}
/// Get a guarded copy of the original process' env vars.
fn get_env_locker() -> Arc<Mutex<EnvMap>> {
Arc::clone(ENV_LOCKER.get_or_init(|| {
let map: EnvMap = env::vars().collect();
Arc::new(Mutex::new(map))
}))
}
/// Reset the process' env vars back to what was in `original_env`.
fn reset_env(original_env: &EnvMap) {
// remove keys if they weren't in the original environment
env::vars()
.filter(|(key, _)| !original_env.contains_key(key))
.for_each(|(key, _)| env::remove_var(key));
// ensure original keys have their original values
original_env
.iter()
.for_each(|(key, value)| env::set_var(key, value));
}
/// Create an environment to run tests in.
///
/// Writes the envfile, sets the working directory, and sets environment vars.
fn create_env(test_env: &TestEnv) {
// only create the envfile if its contents has been set
if let Some(contents) = test_env.envfile_contents() {
create_envfile(&test_env.envfile_path, contents);
}
env::set_current_dir(&test_env.work_dir).expect("setting working directory");
for KeyVal { key, value } in &test_env.env_vars {
env::set_var(key, value)
}
}
/// Create an envfile for use in tests.
fn create_envfile(path: &Path, contents: &str) {
if path.exists() {
panic!("envfile `{}` already exists", path.display())
}
// inner function to group together io::Results
fn create_env_file_inner(path: &Path, contents: &str) -> io::Result<()> {
let mut file = fs::File::create(path)?;
file.write_all(contents.as_bytes())?;
file.sync_all()
}
// call inner function
if let Err(err) = create_env_file_inner(path, contents) {
// handle any io::Result::Err
panic!("error creating envfile `{}`: {}", path.display(), err);
}
}
+22
View File
@@ -0,0 +1,22 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, fs, result::Result};
use crate::common::*;
#[test]
fn test_child_dir() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
fs::create_dir("child")?;
env::set_current_dir("child")?;
dotenv()?;
assert_eq!(env::var("TESTKEY")?, "test_val");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,21 @@
mod common;
use std::{env, error::Error, result::Result};
use dotenvy::*;
use crate::common::*;
#[test]
fn test_default_location_override() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
dotenv_override()?;
assert_eq!(env::var("TESTKEY")?, "test_val_overridden");
assert_eq!(env::var("EXISTING")?, "from_file");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,21 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, result::Result};
use crate::common::*;
#[test]
fn test_default_location() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
dotenv()?;
assert_eq!(env::var("TESTKEY")?, "test_val");
assert_eq!(env::var("EXISTING")?, "from_env");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
+21
View File
@@ -0,0 +1,21 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, result::Result};
use crate::common::*;
#[test]
fn test_dotenv_iter() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
let iter = dotenv_iter()?;
assert!(env::var("TESTKEY").is_err());
iter.load()?;
assert_eq!(env::var("TESTKEY")?, "test_val");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,23 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, result::Result};
use crate::common::*;
#[test]
fn test_from_filename_iter() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
let iter = from_filename_iter(".env")?;
assert!(env::var("TESTKEY").is_err());
iter.load()?;
assert_eq!(env::var("TESTKEY").unwrap(), "test_val");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,20 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, result::Result};
use crate::common::*;
#[test]
fn test_from_filename_override() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
from_filename_override(".env")?;
assert_eq!(env::var("TESTKEY")?, "test_val_overridden");
assert_eq!(env::var("EXISTING")?, "from_file");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,20 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, result::Result};
use crate::common::*;
#[test]
fn test_from_filename() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
from_filename(".env")?;
assert_eq!(env::var("TESTKEY")?, "test_val");
assert_eq!(env::var("EXISTING")?, "from_env");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,26 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, result::Result};
use crate::common::*;
#[test]
fn test_from_path_iter() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
let mut path = env::current_dir()?;
path.push(".env");
let iter = from_path_iter(&path)?;
assert!(env::var("TESTKEY").is_err());
iter.load()?;
assert_eq!(env::var("TESTKEY")?, "test_val");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,22 @@
mod common;
use crate::common::*;
use dotenvy::*;
use std::{env, error::Error, result::Result};
#[test]
fn test_from_path_override() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
let mut path = env::current_dir()?;
path.push(".env");
from_path_override(&path)?;
assert_eq!(env::var("TESTKEY")?, "test_val_overridden");
assert_eq!(env::var("EXISTING")?, "from_file");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
+22
View File
@@ -0,0 +1,22 @@
mod common;
use crate::common::*;
use dotenvy::*;
use std::{env, error::Error, result::Result};
#[test]
fn test_from_path() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
let mut path = env::current_dir()?;
path.push(".env");
from_path(&path)?;
assert_eq!(env::var("TESTKEY")?, "test_val");
assert_eq!(env::var("EXISTING")?, "from_env");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,20 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, fs::File, result::Result};
use crate::common::*;
#[test]
fn test_from_read_override() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
from_read_override(File::open(".env")?)?;
assert_eq!(env::var("TESTKEY")?, "test_val_overridden");
assert_eq!(env::var("EXISTING")?, "from_file");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
+20
View File
@@ -0,0 +1,20 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, fs::File, result::Result};
use crate::common::*;
#[test]
fn test_from_read() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
from_read(File::open(".env")?)?;
assert_eq!(env::var("TESTKEY")?, "test_val");
assert_eq!(env::var("EXISTING")?, "from_env");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
+22
View File
@@ -0,0 +1,22 @@
mod common;
use crate::common::*;
use dotenvy::*;
use std::{env, error::Error, result::Result};
#[test]
fn test_ignore_bom() -> Result<(), Box<dyn Error>> {
let bom = "\u{feff}";
let dir = tempdir_with_dotenv(&format!("{}TESTKEY=test_val", bom))?;
let mut path = env::current_dir()?;
path.push(".env");
from_path(&path)?;
assert_eq!(env::var("TESTKEY")?, "test_val");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,56 @@
mod common;
use std::env;
use common::tempdir_with_dotenv;
use dotenvy::dotenv;
#[test]
fn test_issue_12() {
let _f = tempdir_with_dotenv(
r#"
# Start of .env file
# Comment line with single ' quote
# Comment line with double " quote
# Comment line with double " quote and starts with a space
TESTKEY1=test_val # 1 '" comment
TESTKEY2=test_val_with_#_hash # 2 '" comment
TESTKEY3="test_val quoted with # hash" # 3 '" comment
TESTKEY4="Line 1
# Line 2
Line 3" # 4 Multiline "' comment
TESTKEY5="Line 4
# Line 5
Line 6
" # 5 Multiline "' comment
# End of .env file
"#,
)
.expect("should write test env");
dotenv().expect("should succeed");
assert_eq!(
env::var("TESTKEY1").expect("testkey1 env key not set"),
"test_val"
);
assert_eq!(
env::var("TESTKEY2").expect("testkey2 env key not set"),
"test_val_with_#_hash"
);
assert_eq!(
env::var("TESTKEY3").expect("testkey3 env key not set"),
"test_val quoted with # hash"
);
assert_eq!(
env::var("TESTKEY4").expect("testkey4 env key not set"),
r#"Line 1
# Line 2
Line 3"#
);
assert_eq!(
env::var("TESTKEY5").expect("testkey5 env key not set"),
r#"Line 4
# Line 5
Line 6
"#
);
}
+46
View File
@@ -0,0 +1,46 @@
mod common;
use crate::common::*;
use dotenvy::*;
use std::{env, error::Error, result::Result};
#[test]
fn test_multiline() -> Result<(), Box<dyn Error>> {
let value = "-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\\n\\\"QUOTED\\\"";
let weak = "-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----\n\"QUOTED\"";
let dir = tempdir_with_dotenv(&format!(
r#"
KEY=my\ cool\ value
KEY3="awesome \"stuff\"
more
on other
lines"
KEY4='hello '\''world'"
good ' \'morning"
WEAK="{}"
STRONG='{}'
"#,
value, value
))?;
dotenv()?;
assert_eq!(var("KEY")?, r#"my cool value"#);
assert_eq!(
var("KEY3")?,
r#"awesome "stuff"
more
on other
lines"#
);
assert_eq!(
var("KEY4")?,
r#"hello 'world
good ' 'morning"#
);
assert_eq!(var("WEAK")?, weak);
assert_eq!(var("STRONG")?, value);
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
+17
View File
@@ -0,0 +1,17 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, result::Result};
use crate::common::*;
#[test]
fn test_var() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
assert_eq!(var("TESTKEY")?, "test_val");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
@@ -0,0 +1,64 @@
mod common;
use dotenvy::*;
use std::{env, error::Error, result::Result};
use crate::common::*;
#[test]
fn test_variable_substitutions() -> Result<(), Box<dyn Error>> {
std::env::set_var("KEY", "value");
std::env::set_var("KEY1", "value1");
let substitutions_to_test = [
"$ZZZ", "$KEY", "$KEY1", "${KEY}1", "$KEY_U", "${KEY_U}", "\\$KEY",
];
let common_string = substitutions_to_test.join(">>");
let dir = tempdir_with_dotenv(&format!(
r#"
KEY1=new_value1
KEY_U=$KEY+valueU
SUBSTITUTION_FOR_STRONG_QUOTES='{}'
SUBSTITUTION_FOR_WEAK_QUOTES="{}"
SUBSTITUTION_WITHOUT_QUOTES={}
"#,
common_string, common_string, common_string
))?;
assert_eq!(var("KEY")?, "value");
assert_eq!(var("KEY1")?, "value1");
assert_eq!(var("KEY_U")?, "value+valueU");
assert_eq!(var("SUBSTITUTION_FOR_STRONG_QUOTES")?, common_string);
assert_eq!(
var("SUBSTITUTION_FOR_WEAK_QUOTES")?,
[
"",
"value",
"value1",
"value1",
"value_U",
"value+valueU",
"$KEY"
]
.join(">>")
);
assert_eq!(
var("SUBSTITUTION_WITHOUT_QUOTES")?,
[
"",
"value",
"value1",
"value1",
"value_U",
"value+valueU",
"$KEY"
]
.join(">>")
);
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}
+20
View File
@@ -0,0 +1,20 @@
mod common;
use std::{collections::HashMap, env, error::Error, result::Result};
use dotenvy::*;
use crate::common::*;
#[test]
fn test_vars() -> Result<(), Box<dyn Error>> {
let dir = make_test_dotenv()?;
let vars: HashMap<String, String> = vars().collect();
assert_eq!(vars["TESTKEY"], "test_val");
env::set_current_dir(dir.path().parent().unwrap())?;
dir.close()?;
Ok(())
}