summaryrefslogtreecommitdiff
path: root/internal/namespace/lifecycle_test.go
diff options
context:
space:
mode:
authorJames O'Doherty <james@theodohertyfamily.com>2026-06-03 23:45:45 -0400
committerJames O'Doherty <james@theodohertyfamily.com>2026-06-03 23:45:45 -0400
commit51a0845adba702ac02437405988b24b3b2c9fb45 (patch)
tree62174471b2bf2240f5cbe8532c991e33afce9e18 /internal/namespace/lifecycle_test.go
parentda70b10fbd056f19d892acad542ce96c40c58389 (diff)
fix: resolve resource leaks and improve namespace lifecycle management
- Fix DNS resolver leaks by creating temporary resolv.conf files within the profile's runtime directory and ensuring robust cleanup. - Fix isolation block directory leaks by explicitly removing the block directory during namespace unpinning. - Improve namespace lifecycle management: - Register processes before joining an active namespace to prevent race conditions in reference counting. - Update `IsLastProcess` and corresponding tests to reflect the unregister-then-check cleanup flow. - Improve test reliability and correctness: - Convert `TestAppRun_ProfileDirInjection` to use separate binary execution, preventing process replacement and ensuring `t.TempDir()` cleanup. - Replace hardcoded test configuration paths with `t.TempDir()` in `mount_leak_test.go`. - Implement `SetEnvOverrides` helper for cleaner environment variable management in E2E tests. - Improve E2E lifecycle tests with better environment handling and output redirection.
Diffstat (limited to 'internal/namespace/lifecycle_test.go')
-rw-r--r--internal/namespace/lifecycle_test.go27
1 files changed, 25 insertions, 2 deletions
diff --git a/internal/namespace/lifecycle_test.go b/internal/namespace/lifecycle_test.go
index 1fb0a13..9962e14 100644
--- a/internal/namespace/lifecycle_test.go
+++ b/internal/namespace/lifecycle_test.go
@@ -87,17 +87,40 @@ func TestLifecycleReferenceCounting(t *testing.T) {
if err := RegisterProcess(pm, profile); err != nil {
t.Fatal(err)
}
+
+ // Simulate the application flow: Unregister before checking if we are the last one
+ if err := UnregisterProcess(pm, profile); err != nil {
+ t.Fatal(err)
+ }
+
isLast, err = IsLastProcess(pm, profile)
if err != nil || !isLast {
- t.Errorf("Expected IsLastProcess to be true for single process, got %v, err: %v", isLast, err)
+ t.Errorf("Expected IsLastProcess to be true after unregistering the only process, got %v, err: %v", isLast, err)
}
+ // Add a "stale" process to ensure it's pruned and doesn't count as active
if err := os.WriteFile(filepath.Join(pidsDir, "1234567"), []byte(""), 0644); err != nil {
t.Fatal(err)
}
+
+ // Register a real process so that pruning has something to do
+ if err := RegisterProcess(pm, profile); err != nil {
+ t.Fatal(err)
+ }
+
+ // Prune the stale one
+ if err := PruneStalePids(pm, profile); err != nil {
+ t.Fatal(err)
+ }
+
+ // Unregister the real one
+ if err := UnregisterProcess(pm, profile); err != nil {
+ t.Fatal(err)
+ }
+
isLast, err = IsLastProcess(pm, profile)
if err != nil || !isLast {
- t.Errorf("Expected IsLastProcess to be true because 1234567 is dead, got %v, err: %v", isLast, err)
+ t.Errorf("Expected IsLastProcess to be true after pruning stale and unregistering current, got %v, err: %v", isLast, err)
}
})
}