home-dirの整理
This commit is contained in:
@@ -28,17 +28,47 @@ use tokio::net::UnixListener;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
/// Serialises env-mutating tests. The test harness runs tasks across
|
||||
/// threads, and `INSOMNIA_SCOPE_LOCK` is a process-wide resource.
|
||||
/// threads, and `INSOMNIA_RUNTIME_DIR` is a process-wide resource.
|
||||
static ENV_LOCK: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
|
||||
|
||||
/// Take `ENV_LOCK` and clear any env vars that would outrank
|
||||
/// `INSOMNIA_RUNTIME_DIR` in `paths::runtime_dir` resolution; restore
|
||||
/// previous values on drop.
|
||||
struct EnvGuard {
|
||||
prev_home: Option<String>,
|
||||
prev_xdg: Option<String>,
|
||||
_lock: std::sync::MutexGuard<'static, ()>,
|
||||
}
|
||||
|
||||
impl EnvGuard {
|
||||
fn acquire() -> Self {
|
||||
let lock = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let prev_home = std::env::var("INSOMNIA_HOME").ok();
|
||||
let prev_xdg = std::env::var("XDG_RUNTIME_DIR").ok();
|
||||
unsafe {
|
||||
std::env::remove_var("INSOMNIA_HOME");
|
||||
std::env::remove_var("XDG_RUNTIME_DIR");
|
||||
}
|
||||
Self {
|
||||
_lock: ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner()),
|
||||
prev_home,
|
||||
prev_xdg,
|
||||
_lock: lock,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EnvGuard {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
match &self.prev_home {
|
||||
Some(v) => std::env::set_var("INSOMNIA_HOME", v),
|
||||
None => std::env::remove_var("INSOMNIA_HOME"),
|
||||
}
|
||||
match &self.prev_xdg {
|
||||
Some(v) => std::env::set_var("XDG_RUNTIME_DIR", v),
|
||||
None => std::env::remove_var("XDG_RUNTIME_DIR"),
|
||||
}
|
||||
std::env::remove_var("INSOMNIA_RUNTIME_DIR");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,10 +323,10 @@ async fn read_pod_output_reports_stopped_on_dead_socket() {
|
||||
async fn stop_pod_sends_shutdown_and_releases_scope() {
|
||||
let _env = EnvGuard::acquire();
|
||||
let (tmp, registry, rd) = setup_registry().await;
|
||||
let lock_path = tmp.path().join("scope.lock");
|
||||
unsafe {
|
||||
std::env::set_var("INSOMNIA_SCOPE_LOCK", &lock_path);
|
||||
std::env::set_var("INSOMNIA_RUNTIME_DIR", tmp.path());
|
||||
}
|
||||
let lock_path = tmp.path().join("scope.lock");
|
||||
|
||||
// Seed scope.lock with a top-level `spawner` allocation plus a
|
||||
// delegated `child` allocation — mimics what SpawnPod would have
|
||||
@@ -356,19 +386,14 @@ async fn stop_pod_sends_shutdown_and_releases_scope() {
|
||||
let contents = std::fs::read_to_string(&spawned).unwrap();
|
||||
let records: Vec<SpawnedPodRecord> = serde_json::from_str(&contents).unwrap();
|
||||
assert!(records.is_empty());
|
||||
|
||||
unsafe {
|
||||
std::env::remove_var("INSOMNIA_SCOPE_LOCK");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn stop_pod_succeeds_even_when_child_unreachable() {
|
||||
let _env = EnvGuard::acquire();
|
||||
let (tmp, registry, _rd) = setup_registry().await;
|
||||
let lock_path = tmp.path().join("scope.lock");
|
||||
unsafe {
|
||||
std::env::set_var("INSOMNIA_SCOPE_LOCK", &lock_path);
|
||||
std::env::set_var("INSOMNIA_RUNTIME_DIR", tmp.path());
|
||||
}
|
||||
|
||||
// No live listener — socket never bound. Registered record points
|
||||
@@ -384,10 +409,6 @@ async fn stop_pod_succeeds_even_when_child_unreachable() {
|
||||
|
||||
// Registry no longer knows about the child.
|
||||
assert!(registry.get("child").await.is_none());
|
||||
|
||||
unsafe {
|
||||
std::env::remove_var("INSOMNIA_SCOPE_LOCK");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -18,30 +18,61 @@ use protocol::{Method, Permission, PodEvent, ScopeRule};
|
||||
use tempfile::TempDir;
|
||||
use tokio::net::UnixListener;
|
||||
|
||||
/// Serialises tests that mutate `INSOMNIA_SCOPE_LOCK`.
|
||||
/// Serialises tests that mutate `INSOMNIA_RUNTIME_DIR`.
|
||||
static ENV_LOCK: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
|
||||
|
||||
/// Take `ENV_LOCK` and clear any env vars that would outrank
|
||||
/// `INSOMNIA_RUNTIME_DIR`; restore previous values on drop.
|
||||
struct EnvGuard {
|
||||
prev_home: Option<String>,
|
||||
prev_xdg: Option<String>,
|
||||
_lock: std::sync::MutexGuard<'static, ()>,
|
||||
}
|
||||
|
||||
impl EnvGuard {
|
||||
fn acquire() -> Self {
|
||||
let lock = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let prev_home = std::env::var("INSOMNIA_HOME").ok();
|
||||
let prev_xdg = std::env::var("XDG_RUNTIME_DIR").ok();
|
||||
unsafe {
|
||||
std::env::remove_var("INSOMNIA_HOME");
|
||||
std::env::remove_var("XDG_RUNTIME_DIR");
|
||||
}
|
||||
Self {
|
||||
_lock: ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner()),
|
||||
prev_home,
|
||||
prev_xdg,
|
||||
_lock: lock,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_scope_lock_path(path: &std::path::Path) {
|
||||
unsafe {
|
||||
std::env::set_var("INSOMNIA_SCOPE_LOCK", path);
|
||||
impl Drop for EnvGuard {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
match &self.prev_home {
|
||||
Some(v) => std::env::set_var("INSOMNIA_HOME", v),
|
||||
None => std::env::remove_var("INSOMNIA_HOME"),
|
||||
}
|
||||
match &self.prev_xdg {
|
||||
Some(v) => std::env::set_var("XDG_RUNTIME_DIR", v),
|
||||
None => std::env::remove_var("XDG_RUNTIME_DIR"),
|
||||
}
|
||||
std::env::remove_var("INSOMNIA_RUNTIME_DIR");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_scope_lock_path() {
|
||||
/// Point `INSOMNIA_RUNTIME_DIR` at `dir`. The scope-lock then lives at
|
||||
/// `<dir>/scope.lock` and Pod runtime sub-dirs at `<dir>/{pod_name}/`.
|
||||
fn set_runtime_dir(dir: &std::path::Path) {
|
||||
unsafe {
|
||||
std::env::remove_var("INSOMNIA_SCOPE_LOCK");
|
||||
std::env::set_var("INSOMNIA_RUNTIME_DIR", dir);
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_runtime_dir() {
|
||||
unsafe {
|
||||
std::env::remove_var("INSOMNIA_RUNTIME_DIR");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +164,7 @@ async fn fresh_registry(runtime_base: &std::path::Path, pod_name: &str) -> Arc<S
|
||||
async fn apply_shutdown_removes_from_registry_and_tolerates_missing() {
|
||||
let _env = EnvGuard::acquire();
|
||||
let scope_dir = TempDir::new().unwrap();
|
||||
set_scope_lock_path(&scope_dir.path().join("scope.lock"));
|
||||
set_runtime_dir(scope_dir.path());
|
||||
|
||||
let runtime_base = TempDir::new().unwrap();
|
||||
let registry = fresh_registry(runtime_base.path(), "parent").await;
|
||||
@@ -161,14 +192,14 @@ async fn apply_shutdown_removes_from_registry_and_tolerates_missing() {
|
||||
apply_event_side_effects(&event, ®istry, "parent", &None).await;
|
||||
assert!(registry.get("child").await.is_none());
|
||||
|
||||
clear_scope_lock_path();
|
||||
clear_runtime_dir();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn apply_scope_sub_delegated_adds_grandchild_then_duplicate_is_noop() {
|
||||
let _env = EnvGuard::acquire();
|
||||
let scope_dir = TempDir::new().unwrap();
|
||||
set_scope_lock_path(&scope_dir.path().join("scope.lock"));
|
||||
set_runtime_dir(scope_dir.path());
|
||||
|
||||
let runtime_base = TempDir::new().unwrap();
|
||||
let registry = fresh_registry(runtime_base.path(), "grandparent").await;
|
||||
@@ -208,14 +239,14 @@ async fn apply_scope_sub_delegated_adds_grandchild_then_duplicate_is_noop() {
|
||||
let gc2 = registry.get("grandchild").await.unwrap();
|
||||
assert_eq!(gc2.socket_path, PathBuf::from("/tmp/grandchild.sock"));
|
||||
|
||||
clear_scope_lock_path();
|
||||
clear_runtime_dir();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn apply_scope_sub_delegated_reemits_to_own_parent() {
|
||||
let _env = EnvGuard::acquire();
|
||||
let scope_dir = TempDir::new().unwrap();
|
||||
set_scope_lock_path(&scope_dir.path().join("scope.lock"));
|
||||
set_runtime_dir(scope_dir.path());
|
||||
|
||||
let runtime_base = TempDir::new().unwrap();
|
||||
let registry = fresh_registry(runtime_base.path(), "B").await;
|
||||
@@ -268,14 +299,14 @@ async fn apply_scope_sub_delegated_reemits_to_own_parent() {
|
||||
other => panic!("expected re-emitted ScopeSubDelegated, got {other:?}"),
|
||||
}
|
||||
|
||||
clear_scope_lock_path();
|
||||
clear_runtime_dir();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn apply_turn_ended_and_errored_are_system_noops() {
|
||||
let _env = EnvGuard::acquire();
|
||||
let scope_dir = TempDir::new().unwrap();
|
||||
set_scope_lock_path(&scope_dir.path().join("scope.lock"));
|
||||
set_runtime_dir(scope_dir.path());
|
||||
|
||||
let runtime_base = TempDir::new().unwrap();
|
||||
let registry = fresh_registry(runtime_base.path(), "parent").await;
|
||||
@@ -312,7 +343,7 @@ async fn apply_turn_ended_and_errored_are_system_noops() {
|
||||
.await;
|
||||
|
||||
assert!(registry.get("child").await.is_some());
|
||||
clear_scope_lock_path();
|
||||
clear_runtime_dir();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -320,7 +351,7 @@ async fn shutdown_releases_scope_allocation_when_present() {
|
||||
let _env = EnvGuard::acquire();
|
||||
let scope_dir = TempDir::new().unwrap();
|
||||
let lock_path = scope_dir.path().join("scope.lock");
|
||||
set_scope_lock_path(&lock_path);
|
||||
set_runtime_dir(scope_dir.path());
|
||||
|
||||
// Install a top-level allocation for "kid" so ShutDown has
|
||||
// something to release.
|
||||
@@ -362,5 +393,5 @@ async fn shutdown_releases_scope_allocation_when_present() {
|
||||
"ShutDown should have released the scope allocation"
|
||||
);
|
||||
|
||||
clear_scope_lock_path();
|
||||
clear_runtime_dir();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use std::sync::Arc;
|
||||
use tempfile::TempDir;
|
||||
use tokio::net::UnixListener;
|
||||
|
||||
/// Serialises tests that mutate `INSOMNIA_SCOPE_LOCK` /
|
||||
/// Serialises tests that mutate `INSOMNIA_RUNTIME_DIR` /
|
||||
/// `INSOMNIA_POD_COMMAND` across the thread-pooled test harness.
|
||||
static ENV_LOCK: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
|
||||
|
||||
@@ -39,22 +39,26 @@ impl EnvGuard {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set up a tempdir, point `INSOMNIA_SCOPE_LOCK` + runtime-dir base at
|
||||
/// it, and install a live top-level "spawner" allocation so the tool
|
||||
/// has something to delegate from. Returns the tempdir (keeps it alive
|
||||
/// for the test's lifetime), runtime base, spawner socket, and the
|
||||
/// spawner's runtime dir.
|
||||
/// Set up a tempdir, point `INSOMNIA_RUNTIME_DIR` at it (so
|
||||
/// `scope.lock` and per-Pod runtime subdirs both land in the
|
||||
/// sandbox), and install a live top-level "spawner" allocation so the
|
||||
/// tool has something to delegate from. Returns the tempdir (keeps it
|
||||
/// alive for the test's lifetime), runtime base, spawner socket, and
|
||||
/// the spawner's runtime dir.
|
||||
async fn setup_spawner(
|
||||
spawner_name: &str,
|
||||
allow_root: &Path,
|
||||
) -> (TempDir, PathBuf, PathBuf, Arc<RuntimeDir>) {
|
||||
let tmp = TempDir::new().unwrap();
|
||||
let lock_path = tmp.path().join("scope.lock");
|
||||
let runtime_base = tmp.path().to_path_buf();
|
||||
unsafe {
|
||||
std::env::set_var("INSOMNIA_SCOPE_LOCK", &lock_path);
|
||||
// Outranking env vars must be cleared so `paths::runtime_dir`
|
||||
// resolves to our sandbox instead of the developer's real one.
|
||||
std::env::remove_var("INSOMNIA_HOME");
|
||||
std::env::remove_var("XDG_RUNTIME_DIR");
|
||||
std::env::set_var("INSOMNIA_RUNTIME_DIR", &runtime_base);
|
||||
}
|
||||
|
||||
let runtime_base = tmp.path().join("runtime");
|
||||
let spawner_rd = RuntimeDir::create(&runtime_base, spawner_name)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -148,7 +152,7 @@ fn dummy_model() -> ModelManifest {
|
||||
|
||||
fn clear_env() {
|
||||
unsafe {
|
||||
std::env::remove_var("INSOMNIA_SCOPE_LOCK");
|
||||
std::env::remove_var("INSOMNIA_RUNTIME_DIR");
|
||||
std::env::remove_var("INSOMNIA_POD_COMMAND");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user