summaryrefslogtreecommitdiff
path: root/tests/e2e/race_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'tests/e2e/race_test.go')
-rw-r--r--tests/e2e/race_test.go94
1 files changed, 0 insertions, 94 deletions
diff --git a/tests/e2e/race_test.go b/tests/e2e/race_test.go
deleted file mode 100644
index 3f5ecfe..0000000
--- a/tests/e2e/race_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package e2e
-
-import (
- "fmt"
- "os"
- "os/exec"
- "path/filepath"
- "testing"
-)
-
-// TestLifecycleRace proves that a new process joining an existing namespace
-// can have that namespace unpinned if an exiting process incorrectly
-// thinks it's the last one out.
-func TestLifecycleRace(t *testing.T) {
- binaryPath, err := GetBinaryPath()
- if err != nil {
- t.Skipf("Skipping test: %v", err)
- }
-
- tmpRuntimeDir := t.TempDir()
- profile := "race-test"
- pidsDir := filepath.Join(tmpRuntimeDir, "profiles", profile, "pids")
-
- // Setup a valid profile config to ensure tunneling starts
- tmpConfigDir := t.TempDir()
- profilesDir := filepath.Join(tmpConfigDir, "wg-wrap", "profiles")
- if err := os.MkdirAll(profilesDir, 0755); err != nil {
- t.Fatal(err)
- }
- profileConfPath := filepath.Join(profilesDir, profile+".conf")
- conf := `[Interface]
-Address = 10.0.0.2/24
-PrivateKey = 0000000000000000000000000000000000000000000000000000000000000000
-DNS = 1.1.1.1
-
-[Peer]
-PublicKey = 0000000000000000000000000000000000000000000000000000000000000000
-AllowedIPs = 0.0.0.0/0
-Endpoint = 1.1.1.1:51820
-`
- if err := os.WriteFile(profileConfPath, []byte(conf), 0644); err != nil {
- t.Fatal(err)
- }
-
- // We use a a long-running sleep for Process A to keep the namespace active.
- // Process A is the "Victim".
- cmdA := exec.Command(binaryPath, "--profile", profile, "--", "sleep", "10")
- cmdA.Env = append(os.Environ(),
- fmt.Sprintf("XDG_RUNTIME_DIR=%s", tmpRuntimeDir),
- fmt.Sprintf("XDG_CONFIG_HOME=%s", tmpConfigDir),
- )
- if err := cmdA.Start(); err != nil {
- t.Fatalf("Failed to start Process A: %v", err)
- }
- defer func() { _ = cmdA.Process.Kill() }()
-
- // Wait for Process A to establish the namespace and register PID
- waitForPids(t, pidsDir, 1)
-
- // Process B is the "Saboteur". It will join and then exit.
- // We will loop this to increase the chance of hitting the race window.
- for i := 0; i < 5; i++ {
- cmdB := exec.Command(binaryPath, "--profile", profile, "--", "sleep", "0.1")
- cmdB.Env = append(os.Environ(),
- fmt.Sprintf("XDG_RUNTIME_DIR=%s", tmpRuntimeDir),
- fmt.Sprintf("XDG_CONFIG_HOME=%s", tmpConfigDir),
- )
- if err := cmdB.Start(); err != nil {
- t.Fatalf("Failed to start Process B (iteration %d): %v", i, err)
- }
-
- // Wait for Process B to register
- waitForPids(t, pidsDir, 2)
-
- // Let Process B exit. The defer block in ExecuteCommand will:
- // 1. Unregister Process B
- // 2. Check IsLastProcess() -> might return true if Process A's PID is stale or miscounted
- // 3. UnpinNamespace()
- if err := cmdB.Wait(); err != nil {
- t.Fatalf("Process B failed: %v", err)
- }
-
- // After B exits, Process A should still be the only remaining process.
- // We check if the namespace pin file was accidentally deleted by B.
- nsPath := filepath.Join(tmpRuntimeDir, "profiles", profile+".ns")
- if _, err := os.Stat(nsPath); os.IsNotExist(err) {
- t.Errorf("BUG: Namespace pin file was deleted by exiting Process B, despite Process A still running!")
- return
- }
-
- // Wait for the PID count to drop back to 1
- waitForPids(t, pidsDir, 1)
- }
-}