use std::fs::{read_to_string, File};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::{env, fs};
use crate::core::config::{default_base, DEFAULT_BASE};
use crate::core::{settings, Settings};
use crate::errors::{ConfGuardError, ConfGuardResult};
use crate::util::helper::file_contents;
use crate::util::home_based::to_home_based;
use chrono::TimeZone;
use fs_extra::{copy_items, dir, remove_items};
use itertools::Itertools;
use once_cell::sync::Lazy;
use remove_dir_all::ensure_empty_dir;
use rstest::{fixture, rstest};
use std::sync::Once;
use tempfile::TempDir;
use tracing::info;
use tracing::{debug, warn};
use tracing_subscriber::fmt::format::FmtSpan;
static TEST_SETUP: Once = Once::new();
pub const TEST_VERSION: i64 = 999;
pub const TEST_ENV_VARS: &[&str] = &["CONFGUARD_BASE_DIR", "RUST_LOG", "NO_CLEANUP"];
pub fn testing_dir() -> String {
env::var("HOME")
.map(|home| format!("{}/xxx/rs-cg", home))
.unwrap_or_else(|_| "/tmp/xxx/rs-cg".to_string())
}
pub static TESTING_DIR: Lazy<String> = Lazy::new(testing_dir);
pub fn init_test_setup() {
TEST_SETUP.call_once(|| {
if env::var("RUST_LOG").is_err() {
env::set_var("RUST_LOG", "debug");
}
tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.with_target(true) .with_thread_names(false) .with_test_writer()
.init();
env::remove_var("CONFGUARD_BASE_DIR");
env::remove_var("CONFGUARD_VERSION");
env::set_var("CONFGUARD_BASE_DIR", DEFAULT_BASE.as_str());
env::set_var("CONFGUARD_VERSION", TEST_VERSION.to_string());
Settings::reload().expect("test env vars are set - reload must succeed");
info!("Test Setup complete");
});
}
pub fn setup_test_dir() -> PathBuf {
init_test_setup(); let settings = settings();
let test_dir = settings.confguard_base_dir.clone();
assert_eq!(
test_dir,
DEFAULT_BASE.as_str(),
"Test directory must be DEFAULT_BASE, is: {}",
test_dir
);
let path = PathBuf::from(&test_dir);
ensure_empty_dir(&path).expect("test dir under temp - creation must succeed");
path
}
pub fn teardown_test_dir(test_dir: &Path) {
if env::var("NO_CLEANUP").is_err() && test_dir.exists() {
fs::remove_dir_all(test_dir).expect("test dir exists and is removable");
} else {
println!("Test artifacts left at: {}", test_dir.display());
}
}
pub fn print_active_env_vars(vars: &[&str]) {
for var in vars {
if let Ok(value) = env::var(var) {
println!("{}={}", var, value);
} else {
println!("{} is not set", var);
}
}
}
pub fn create_file_with_content(file_path: &str, content: &str) -> ConfGuardResult<()> {
let path = Path::new(file_path);
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
let mut file = File::create(path)?;
file.write_all(content.as_bytes())?;
Ok(())
}
pub fn generate_envrc_content(test_dir: &Path) -> ConfGuardResult<String> {
Ok(format!(
"#------------------------------- confguard start --------------------------------
# config.relative = true
# config.version = 2
# state.sentinel = 'test-12345678'
# state.timestamp = '2024-04-15T10:00:00.000Z'
# state.sourceDir = '{}'
export SOPS_PATH=$HOME/path/to/sops
dotenv $SOPS_PATH/environments/local.env
#-------------------------------- confguard end ---------------------------------",
to_home_based(test_dir)?
))
}
#[cfg(test)]
mod tests {
use super::*;
#[fixture]
fn test_dir() -> PathBuf {
setup_test_dir()
}
#[rstest]
fn test_setup_test_dir(test_dir: PathBuf) {
assert!(test_dir.exists());
}
#[rstest]
fn test_teardown_test_dir(test_dir: PathBuf) {
teardown_test_dir(&test_dir);
assert!(!test_dir.exists());
}
#[rstest]
fn test_print_active_env_vars() {
print_active_env_vars(TEST_ENV_VARS);
}
#[rstest]
fn test_generate_envrc_content(test_dir: PathBuf) {
let content = generate_envrc_content(test_dir.as_path()).unwrap();
println!("{}", content);
assert!(content.contains("confguard start"));
assert!(content.contains("confguard end"));
assert!(content.contains("SOPS_PATH=$HOME/path/to/sops"));
}
#[rstest]
fn test_create_file_with_content(test_dir: PathBuf) {
let file_path = test_dir.join("nested/test.txt");
let content = "test content";
create_file_with_content(file_path.to_str().unwrap(), content).unwrap();
let file_content = read_to_string(file_path).unwrap();
assert_eq!(file_content.trim(), content);
}
}