use std::fs;
use std::path::PathBuf;
use std::process::Command;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
use anyhow::{Context, Result};
static COUNTER: AtomicU64 = AtomicU64::new(0);
fn workspace_root() -> Result<PathBuf> {
let mut current = std::env::current_dir()?;
loop {
let cargo_toml = current.join("Cargo.toml");
if cargo_toml.exists() {
let content = fs::read_to_string(&cargo_toml)?;
if content.contains("[workspace]") {
return Ok(current);
}
}
if !current.pop() {
break;
}
}
Err(anyhow::anyhow!("could not locate workspace root"))
}
fn create_unique_test_root() -> Result<PathBuf> {
let nonce = COUNTER.fetch_add(1, Ordering::SeqCst);
let ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.context("system time before unix epoch")?
.as_nanos();
let root = std::env::temp_dir().join(format!(
"terraphim-agent-hermetic-tests-{}-{}-{}",
std::process::id(),
ts,
nonce
));
fs::create_dir_all(&root)?;
Ok(root)
}
pub fn apply_hermetic_env(cmd: &mut Command) -> Result<()> {
let root = create_unique_test_root()?;
let home_dir = root.join("home");
let xdg_config_home = home_dir.join(".config");
let terraphim_config_dir = xdg_config_home.join("terraphim");
let data_dir = root.join("data");
let dashmap_dir = root.join("dashmap");
let sqlite_dir = root.join("sqlite");
fs::create_dir_all(&home_dir)?;
fs::create_dir_all(&terraphim_config_dir)?;
fs::create_dir_all(&data_dir)?;
fs::create_dir_all(&dashmap_dir)?;
fs::create_dir_all(&sqlite_dir)?;
let sqlite_db = sqlite_dir.join("terraphim.db");
let role_config = workspace_root()?
.join("crates/terraphim_agent/tests/fixtures/terraphim_engineer_config.json");
let settings_toml = format!(
r#"
server_hostname = "127.0.0.1:8000"
api_endpoint = "http://localhost:8000/api"
initialized = "false"
default_data_path = "{data}"
role_config = "{role_config}"
[profiles.dashmap]
type = "dashmap"
root = "{dashmap}"
[profiles.sqlite]
type = "sqlite"
datadir = "{sqlite}"
connection_string = "{db}"
table = "terraphim_kv"
"#,
data = data_dir.display(),
dashmap = dashmap_dir.display(),
sqlite = sqlite_dir.display(),
db = sqlite_db.display(),
role_config = role_config.display(),
);
let settings_dirs = [
terraphim_config_dir.clone(),
home_dir
.join("Library")
.join("Application Support")
.join("com.aks.terraphim"),
];
for dir in &settings_dirs {
fs::create_dir_all(dir)?;
fs::write(dir.join("settings.toml"), &settings_toml)?;
}
let workspace = workspace_root()?;
cmd.current_dir(&workspace)
.env("HOME", &home_dir)
.env("XDG_CONFIG_HOME", &xdg_config_home)
.env("TERRAPHIM_SETTINGS_PATH", &terraphim_config_dir)
.env("TERRAPHIM_DEFAULT_DATA_PATH", &data_dir);
Ok(())
}