//go:build integration package floxenv import ( "os" "os/exec" "path/filepath" "strings" "testing" "time" ) // TestIntegration_ActivateDeactivate exercises the real flox binary if present. // Run with: go test -tags=integration ./pkg/floxenv func TestIntegration_ActivateDeactivate(t *testing.T) { if _, err := exec.LookPath(defaultFloxPath); err != nil { t.Skip("flox not installed; skipping integration test") } // Verify that the installed flox supports --detach. if out, err := exec.Command(defaultFloxPath, "activate", "--help").Output(); err == nil { if !strings.Contains(string(out), "detach") { t.Skip("installed flox does not support --detach; skipping integration test") } } else { t.Skipf("unable to query flox activate help: %v", err) } tmpDir := t.TempDir() manifest := filepath.Join(tmpDir, "flox.nix") if err := os.WriteFile(manifest, []byte(`{ description = "test env"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; outputs = { self, nixpkgs }: {}; }`), 0600); err != nil { t.Fatalf("write manifest: %v", err) } r := NewRegistry() envID, pid, err := r.Activate(manifest) if err != nil { t.Fatalf("activate failed: %v", err) } if !IsAlive(pid) { t.Fatalf("expected pid %d to be alive after activation", pid) } // Ensure we clean up even if the test panics. t.Cleanup(func() { _ = r.Deactivate(envID, pid) }) // Give flox a moment to fully initialise detached state. time.Sleep(500 * time.Millisecond) if err := r.Deactivate(envID, pid); err != nil { t.Fatalf("deactivate failed: %v", err) } // Polling isAlive because flox may take a moment to tear down. for i := 0; i < 30; i++ { if !IsAlive(pid) { return } time.Sleep(100 * time.Millisecond) } t.Fatalf("expected pid %d to be dead after deactivate, but it is still alive", pid) }