package desktop import ( "context" "encoding/json" "errors" "net" "os" "path/filepath" "testing" "time" "github.com/bnema/dumber/internal/application/port" "github.com/bnema/dumber/internal/infrastructure/process" "github.com/bnema/dumber/internal/infrastructure/runtimeprofile" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) type browserWindowOpenerFunc func(context.Context, string) error func (f browserWindowOpenerFunc) OpenExternalURL(ctx context.Context, url string) error { return f(ctx, url) } func (f browserWindowOpenerFunc) OpenFreshWindow(ctx context.Context, url string) error { return f(ctx, url) } type browserWindowOpener struct { openExternalURL func(context.Context, string) error openFreshWindow func(context.Context, string) error } func (o browserWindowOpener) OpenExternalURL(ctx context.Context, url string) error { return o.openExternalURL(ctx, url) } func (o browserWindowOpener) OpenFreshWindow(ctx context.Context, url string) error { return o.openFreshWindow(ctx, url) } func waitForSocket(t *testing.T, path string) { t.Helper() require.Eventually(t, func() bool { _, err := os.Stat(path) return err == nil }, time.Second, 10*time.Millisecond) } func waitForSocketGone(t *testing.T, path string) { t.Helper() require.Eventually(t, func() bool { _, err := os.Stat(path) return os.IsNotExist(err) }, time.Second, 10*time.Millisecond) } func shortTempDir(t *testing.T) string { t.Helper() dir, err := os.MkdirTemp("", "dbr-") require.NoError(t, err) t.Cleanup(func() { _ = os.RemoveAll(dir) }) return dir } func TestValidateBrowserLaunchSocketDirOwnedAcceptsCurrentUser(t *testing.T) { ipc := testIPC(shortTempDir(t)) require.NoError(t, os.MkdirAll(filepath.Dir(ipc.BrowserLaunchSocket), 0o700)) require.NoError(t, validateBrowserLaunchSocketDirOwned(ipc.BrowserLaunchSocket, uint32(os.Geteuid()))) } func TestValidateBrowserLaunchSocketDirOwnedRejectsUnexpectedOwner(t *testing.T) { ipc := testIPC(shortTempDir(t)) require.NoError(t, os.MkdirAll(filepath.Dir(ipc.BrowserLaunchSocket), 0o700)) unexpectedUID := uint32(os.Geteuid() + 1) if unexpectedUID == uint32(os.Geteuid()) { unexpectedUID++ } err := validateBrowserLaunchSocketDirOwned(ipc.BrowserLaunchSocket, unexpectedUID) require.Error(t, err) require.Contains(t, err.Error(), "browser launch dir owner") } func TestValidateBrowserLaunchSocketDirOwnedRejectsWritableUserParent(t *testing.T) { root := shortTempDir(t) ipc := runtimeprofile.IPCPaths{ RuntimeDir: filepath.Join(root, "dumber", "dev-abc123", "cef"), BrowserLaunchSocket: filepath.Join(root, "dumber", "dev-abc123", "cef", browserLaunchSocketName), } require.NoError(t, os.MkdirAll(filepath.Dir(ipc.BrowserLaunchSocket), 0o700)) require.NoError(t, os.Chmod(filepath.Join(root, "dumber"), 0o777)) t.Cleanup(func() { _ = os.Chmod(filepath.Join(root, "dumber"), 0o700) }) err := validateBrowserLaunchSocketDirOwned(ipc.BrowserLaunchSocket, uint32(os.Geteuid())) require.Error(t, err) require.Contains(t, err.Error(), "browser launch dir permissions") } func testIPC(root string) runtimeprofile.IPCPaths { runtimeDir := filepath.Join(root, "runtime") return runtimeprofile.IPCPaths{ RuntimeDir: runtimeDir, BrowserLaunchSocket: filepath.Join(runtimeDir, browserLaunchSocketName), } } func testNamespacedIPC(root, engine string) runtimeprofile.IPCPaths { runtimeDir := filepath.Join(root, "runtime", engine) return runtimeprofile.IPCPaths{ RuntimeDir: runtimeDir, BrowserLaunchSocket: filepath.Join(runtimeDir, browserLaunchSocketName), } } func overrideBrowserLaunchRequestID(t *testing.T, id string) func() { t.Helper() previous := newBrowserLaunchRequestID newBrowserLaunchRequestID = func() string { return id } return func() { newBrowserLaunchRequestID = previous } } func TestBrowserLaunchRelay_DeliverOpenExternalURL_MissingListenerReturnsFalseNil(t *testing.T) { relay := NewBrowserLaunchRelay(testIPC(shortTempDir(t))) delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com") require.NoError(t, err) assert.False(t, delivered) } func TestBrowserLaunchRelay_SameProfileAndEngine_UsesSameSocket(t *testing.T) { ipc := testNamespacedIPC(shortTempDir(t), "cef") listenerRelay := NewBrowserLaunchRelay(ipc) clientRelay := NewBrowserLaunchRelay(ipc) received := make(chan string, 1) ctx := t.Context() closer, err := listenerRelay.Listen(ctx, browserWindowOpenerFunc(func(_ context.Context, url string) error { received <- url return nil })) require.NoError(t, err) defer closer.Close() waitForSocket(t, ipc.BrowserLaunchSocket) delivered, err := clientRelay.DeliverOpenExternalURL(context.Background(), "https://example.com/same-namespace") require.NoError(t, err) require.True(t, delivered) require.Equal(t, "https://example.com/same-namespace", <-received) } func TestBrowserLaunchRelay_DevCEFAndDevWebKit_UseDifferentSockets(t *testing.T) { root := t.TempDir() cefIPC := testNamespacedIPC(root, "cef") wkIPC := testNamespacedIPC(root, "webkit") require.NotEqual(t, cefIPC.BrowserLaunchSocket, wkIPC.BrowserLaunchSocket) } func TestBrowserLaunchRelay_DeliverOpenExternalURL_SendsRequestIDAndAcceptsMatchingResponse(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) restore := overrideBrowserLaunchRequestID(t, "request-test-1") defer restore() receivedRequest := make(chan browserLaunchRequest, 1) require.NoError(t, os.MkdirAll(ipc.RuntimeDir, 0o700)) listener, err := net.ListenUnix("unix", &net.UnixAddr{Name: ipc.BrowserLaunchSocket, Net: "unix"}) require.NoError(t, err) defer func() { _ = listener.Close() _ = os.Remove(ipc.BrowserLaunchSocket) }() go func() { conn, acceptErr := listener.AcceptUnix() if acceptErr != nil { return } defer conn.Close() var request browserLaunchRequest if decodeErr := json.NewDecoder(conn).Decode(&request); decodeErr != nil { return } receivedRequest <- request _ = json.NewEncoder(conn).Encode(browserLaunchResponse{RequestID: request.RequestID, Accepted: true}) }() delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/request-id") require.NoError(t, err) require.True(t, delivered) request := <-receivedRequest require.Equal(t, "request-test-1", request.RequestID) require.Equal(t, "https://example.com/request-id", request.URL) } func TestBrowserLaunchRelay_DeliverOpenExternalURL_RejectsMismatchedResponseRequestID(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) restore := overrideBrowserLaunchRequestID(t, "request-test-2") defer restore() require.NoError(t, os.MkdirAll(ipc.RuntimeDir, 0o700)) listener, err := net.ListenUnix("unix", &net.UnixAddr{Name: ipc.BrowserLaunchSocket, Net: "unix"}) require.NoError(t, err) defer func() { _ = listener.Close() _ = os.Remove(ipc.BrowserLaunchSocket) }() go func() { conn, acceptErr := listener.AcceptUnix() if acceptErr != nil { return } defer conn.Close() var request browserLaunchRequest if decodeErr := json.NewDecoder(conn).Decode(&request); decodeErr != nil { return } _ = json.NewEncoder(conn).Encode(browserLaunchResponse{RequestID: "different-request", Accepted: true}) }() delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/request-id-mismatch") require.Error(t, err) require.True(t, delivered) require.Contains(t, err.Error(), "mismatched browser launch relay response") } func TestBrowserLaunchRelay_DeliverOpenExternalURL_RoundTrip(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) received := make(chan string, 1) ctx := t.Context() closer, err := relay.Listen(ctx, browserWindowOpener{ openExternalURL: func(_ context.Context, url string) error { received <- url return nil }, openFreshWindow: func(context.Context, string) error { t.Fatal("external URL relay request must preserve configured placement") return nil }, }) require.NoError(t, err) defer closer.Close() waitForSocket(t, ipc.BrowserLaunchSocket) delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/new") require.NoError(t, err) assert.True(t, delivered) select { case got := <-received: assert.Equal(t, "https://example.com/new", got) case <-time.After(time.Second): t.Fatal("expected opener to receive the URL") } } func TestBrowserLaunchRelay_DeliverOpenFreshWindow_RoundTrip(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) freshWindows := make(chan string, 1) ctx := t.Context() closer, err := relay.Listen(ctx, browserWindowOpener{ openExternalURL: func(context.Context, string) error { t.Fatal("external-link placement must not handle standalone omnibox navigation") return nil }, openFreshWindow: func(_ context.Context, url string) error { freshWindows <- url return nil }, }) require.NoError(t, err) defer closer.Close() waitForSocket(t, ipc.BrowserLaunchSocket) delivered, err := relay.DeliverOpenFreshWindow(context.Background(), "https://example.com/omnibox") require.NoError(t, err) require.True(t, delivered) select { case got := <-freshWindows: assert.Equal(t, "https://example.com/omnibox", got) case <-time.After(time.Second): t.Fatal("expected fresh-window opener to receive the URL") } } func TestBrowserLaunchRelay_RequiresBrowserLaunchSocketPath(t *testing.T) { relay := NewBrowserLaunchRelay(runtimeprofile.IPCPaths{}) _, err := relay.Listen(context.Background(), browserWindowOpenerFunc(func(context.Context, string) error { return nil })) require.Error(t, err) require.Contains(t, err.Error(), "browser launch socket path") } func TestBrowserLaunchRelay_SecondListenWhileLiveFailsWithoutReplacingListener(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) firstReceived := make(chan string, 1) ctx := t.Context() closer, err := relay.Listen(ctx, browserWindowOpenerFunc(func(_ context.Context, url string) error { firstReceived <- url return nil })) require.NoError(t, err) defer closer.Close() waitForSocket(t, ipc.BrowserLaunchSocket) _, err = relay.Listen(ctx, browserWindowOpenerFunc(func(context.Context, string) error { return nil })) require.Error(t, err) delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/live") require.NoError(t, err) require.True(t, delivered) select { case got := <-firstReceived: assert.Equal(t, "https://example.com/live", got) case <-time.After(time.Second): t.Fatal("expected the original listener to remain active") } } func TestBrowserLaunchRelay_RebindsStaleSocketPath(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) require.NoError(t, os.MkdirAll(filepath.Dir(ipc.BrowserLaunchSocket), 0o700)) require.NoError(t, os.WriteFile(ipc.BrowserLaunchSocket, []byte("stale"), 0o600)) received := make(chan string, 1) ctx := t.Context() closer, err := relay.Listen(ctx, browserWindowOpenerFunc(func(_ context.Context, url string) error { received <- url return nil })) require.NoError(t, err) defer closer.Close() waitForSocket(t, ipc.BrowserLaunchSocket) delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/stale") require.NoError(t, err) require.True(t, delivered) select { case got := <-received: assert.Equal(t, "https://example.com/stale", got) case <-time.After(time.Second): t.Fatal("expected stale socket path to be rebound") } } func TestBrowserLaunchRelay_RejectsMalformedPayloads(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) received := make(chan string, 1) ctx := t.Context() closer, err := relay.Listen(ctx, browserWindowOpenerFunc(func(_ context.Context, url string) error { received <- url return nil })) require.NoError(t, err) defer closer.Close() waitForSocket(t, ipc.BrowserLaunchSocket) conn, err := net.Dial("unix", ipc.BrowserLaunchSocket) require.NoError(t, err) _, err = conn.Write([]byte("not-json")) require.NoError(t, err) require.NoError(t, conn.Close()) delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/still-works") require.NoError(t, err) assert.True(t, delivered) select { case got := <-received: assert.Equal(t, "https://example.com/still-works", got) case <-time.After(time.Second): t.Fatal("expected opener to receive the URL after malformed payload") } } func TestBrowserLaunchRelay_CloseRemovesSocketPath(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) ctx := t.Context() closer, err := relay.Listen(ctx, browserWindowOpenerFunc(func(context.Context, string) error { return nil })) require.NoError(t, err) waitForSocket(t, ipc.BrowserLaunchSocket) require.NoError(t, closer.Close()) waitForSocketGone(t, ipc.BrowserLaunchSocket) } func TestBrowserLaunchRelay_ContextCancelStopsServing(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) ctx, cancel := context.WithCancel(context.Background()) closer, err := relay.Listen(ctx, browserWindowOpenerFunc(func(context.Context, string) error { return nil })) require.NoError(t, err) waitForSocket(t, ipc.BrowserLaunchSocket) cancel() waitForSocketGone(t, ipc.BrowserLaunchSocket) require.NoError(t, closer.Close()) delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/after-cancel") require.NoError(t, err) assert.False(t, delivered) } func TestBrowserLaunchRelay_DeliverOpenExternalURL_RespectsResponseReadTimeout(t *testing.T) { ipc := testIPC(shortTempDir(t)) require.NoError(t, os.MkdirAll(ipc.RuntimeDir, 0o700)) listener, err := net.ListenUnix("unix", &net.UnixAddr{Name: ipc.BrowserLaunchSocket, Net: "unix"}) require.NoError(t, err) defer func() { _ = listener.Close() _ = os.Remove(ipc.BrowserLaunchSocket) }() ready := make(chan struct{}) go func() { close(ready) conn, acceptErr := listener.AcceptUnix() if acceptErr != nil { return } defer conn.Close() <-time.After(time.Second) }() <-ready relay := NewBrowserLaunchRelay(ipc) ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() delivered, err := relay.DeliverOpenExternalURL(ctx, "https://example.com/slow") require.Error(t, err) require.ErrorIs(t, err, context.DeadlineExceeded) assert.False(t, delivered) } func TestBrowserLaunchRelay_DeliverOpenExternalURL_ReturnsUnconfirmedErrorOnNoDeadlineTimeout(t *testing.T) { ipc := testIPC(shortTempDir(t)) require.NoError(t, os.MkdirAll(ipc.RuntimeDir, 0o700)) listener, err := net.ListenUnix("unix", &net.UnixAddr{Name: ipc.BrowserLaunchSocket, Net: "unix"}) require.NoError(t, err) defer func() { _ = listener.Close() _ = os.Remove(ipc.BrowserLaunchSocket) }() ready := make(chan struct{}) go func() { close(ready) conn, acceptErr := listener.AcceptUnix() if acceptErr != nil { return } defer conn.Close() <-time.After(time.Second) }() <-ready relay := NewBrowserLaunchRelay(ipc) started := make(chan struct{}) type deliverResult struct { delivered bool err error } result := make(chan deliverResult, 1) go func() { close(started) delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/slow") result <- deliverResult{delivered: delivered, err: err} }() <-started select { case got := <-result: assert.True(t, got.delivered) require.Error(t, got.err) require.ErrorIs(t, got.err, ErrBrowserLaunchRelayUnconfirmed) case <-time.After(browserLaunchIOTimeout * 3): t.Fatal("DeliverOpenExternalURL blocked without a caller deadline") } } func TestBrowserLaunchRelay_AcknowledgesBeforeOpenerReturns(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) started := make(chan struct{}) release := make(chan struct{}) ctx := t.Context() closer, err := relay.Listen(ctx, browserWindowOpenerFunc(func(_ context.Context, _ string) error { close(started) <-release return nil })) require.NoError(t, err) defer closer.Close() waitForSocket(t, ipc.BrowserLaunchSocket) conn, err := net.Dial("unix", ipc.BrowserLaunchSocket) require.NoError(t, err) defer conn.Close() require.NoError(t, conn.SetDeadline(time.Now().Add(300*time.Millisecond))) require.NoError(t, json.NewEncoder(conn).Encode(browserLaunchRequest{RequestID: "raw-request-1", URL: "https://example.com/slow-but-healthy"})) var response browserLaunchResponse require.NoError(t, json.NewDecoder(conn).Decode(&response)) assert.Empty(t, response.Error) assert.True(t, response.Accepted) assert.Equal(t, "raw-request-1", response.RequestID) select { case <-started: case <-time.After(time.Second): t.Fatal("expected opener to be invoked after acknowledgement") } close(release) } func TestBrowserLaunchRelay_AcknowledgesAcceptedEvenWhenOpenerReturnsLateError(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) started := make(chan struct{}) ctx := t.Context() closer, err := relay.Listen(ctx, browserWindowOpenerFunc(func(_ context.Context, _ string) error { close(started) return errors.New("late open failure") })) require.NoError(t, err) defer closer.Close() waitForSocket(t, ipc.BrowserLaunchSocket) conn, err := net.Dial("unix", ipc.BrowserLaunchSocket) require.NoError(t, err) defer conn.Close() require.NoError(t, conn.SetDeadline(time.Now().Add(300*time.Millisecond))) require.NoError(t, json.NewEncoder(conn).Encode(browserLaunchRequest{RequestID: "raw-request-2", URL: "https://example.com/fails-later"})) var response browserLaunchResponse require.NoError(t, json.NewDecoder(conn).Decode(&response)) assert.Empty(t, response.Error) assert.True(t, response.Accepted) assert.Equal(t, "raw-request-2", response.RequestID) select { case <-started: case <-time.After(time.Second): t.Fatal("expected opener to be invoked after accepted acknowledgement") } } func TestBrowserLaunchRelay_SilentClientDoesNotStallListener(t *testing.T) { ipc := testIPC(shortTempDir(t)) relay := NewBrowserLaunchRelay(ipc) received := make(chan string, 1) ctx := t.Context() closer, err := relay.Listen(ctx, browserWindowOpenerFunc(func(_ context.Context, url string) error { received <- url return nil })) require.NoError(t, err) defer closer.Close() waitForSocket(t, ipc.BrowserLaunchSocket) conn, err := net.Dial("unix", ipc.BrowserLaunchSocket) require.NoError(t, err) defer conn.Close() time.Sleep(20 * time.Millisecond) type deliverResult struct { delivered bool err error } result := make(chan deliverResult, 1) go func() { delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/recovered") result <- deliverResult{delivered: delivered, err: err} }() select { case got := <-result: require.NoError(t, got.err) require.True(t, got.delivered) case <-time.After(300 * time.Millisecond): t.Fatal("silent client stalled the relay listener") } select { case got := <-received: assert.Equal(t, "https://example.com/recovered", got) case <-time.After(time.Second): t.Fatal("expected opener to receive the URL") } } type blockingRelayOpener struct { release chan struct{} received chan string } func (o *blockingRelayOpener) OpenExternalURL(_ context.Context, url string) error { o.received <- url <-o.release return nil } func (o *blockingRelayOpener) OpenFreshWindow(_ context.Context, url string) error { return o.OpenExternalURL(context.Background(), url) } func startLeaseTestListener(t *testing.T, opener port.BrowserWindowOpener) *browserLaunchRelay { t.Helper() ipc := testIPC(shortTempDir(t)) require.NoError(t, os.MkdirAll(ipc.RuntimeDir, 0o700)) relay := NewBrowserLaunchRelay(ipc).(*browserLaunchRelay) ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) closer, err := relay.Listen(ctx, opener) require.NoError(t, err) t.Cleanup(func() { _ = closer.Close() }) return relay } func waitForLeaseCount(t *testing.T, gate *process.AdmissionGate, want int) { t.Helper() deadline := time.Now().Add(3 * time.Second) for time.Now().Before(deadline) { if gate.Active() == want { return } time.Sleep(5 * time.Millisecond) } t.Fatalf("lease count = %d, want %d", gate.Active(), want) } func TestBrowserLaunchRelay_HoldsLeaseThroughDispatch(t *testing.T) { opener := &blockingRelayOpener{release: make(chan struct{}), received: make(chan string, 2)} relay := startLeaseTestListener(t, opener) gate := relay.AdmissionGate() delivered := make(chan error, 1) go func() { _, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/lease") delivered <- err }() select { case url := <-opener.received: require.Equal(t, "https://example.com/lease", url) case <-time.After(3 * time.Second): t.Fatal("opener never received the request") } // Acknowledged and dispatched: the lease is held until dispatch settles. waitForLeaseCount(t, gate, 1) select { case err := <-delivered: require.NoError(t, err) case <-time.After(3 * time.Second): t.Fatal("client never received acknowledgement") } close(opener.release) waitForLeaseCount(t, gate, 0) } func TestBrowserLaunchRelay_SimultaneousOpensHoldLeases(t *testing.T) { opener := &blockingRelayOpener{release: make(chan struct{}), received: make(chan string, 4)} relay := startLeaseTestListener(t, opener) gate := relay.AdmissionGate() for range 2 { go func() { _, _ = relay.DeliverOpenExternalURL(context.Background(), "https://example.com/parallel") }() } for range 2 { select { case <-opener.received: case <-time.After(3 * time.Second): t.Fatal("opener never received a parallel request") } } waitForLeaseCount(t, gate, 2) close(opener.release) waitForLeaseCount(t, gate, 0) } func TestBrowserLaunchRelay_ClosedAdmissionSendsErrorResponse(t *testing.T) { opener := &blockingRelayOpener{release: make(chan struct{}), received: make(chan string, 1)} relay := startLeaseTestListener(t, opener) gate := relay.AdmissionGate() close(opener.release) gate.Close() delivered, err := relay.DeliverOpenExternalURL(context.Background(), "https://example.com/late") require.Error(t, err, "losing request must receive the error response") require.Contains(t, err.Error(), "shutting down") require.Equal(t, 0, gate.Active(), "refused requests hold no lease") select { case url := <-opener.received: t.Fatalf("refused request reached the opener: %s", url) case <-time.After(300 * time.Millisecond): } _ = delivered } type closeTrackingOpener struct { *blockingRelayOpener closed chan struct{} } func (o *closeTrackingOpener) CloseAllWindows(_ context.Context) error { close(o.closed) return nil } func sendRelayAction(t *testing.T, socketPath, action string) browserLaunchResponse { t.Helper() conn, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: socketPath, Net: "unix"}) require.NoError(t, err) defer func() { _ = conn.Close() }() require.NoError(t, conn.SetDeadline(time.Now().Add(3*time.Second))) require.NoError(t, json.NewEncoder(conn).Encode(browserLaunchRequest{RequestID: "diag-1", Action: browserLaunchAction(action)})) var response browserLaunchResponse require.NoError(t, json.NewDecoder(conn).Decode(&response)) return response } func TestBrowserLaunchRelay_DiagnosticCloseRejectedWithoutOptIn(t *testing.T) { opener := &blockingRelayOpener{release: make(chan struct{}), received: make(chan string, 1)} close(opener.release) relay := startLeaseTestListener(t, opener) response := sendRelayAction(t, relay.ipc.BrowserLaunchSocket, "close-all-windows") require.False(t, response.Accepted, "rejected close must not acknowledge") require.Contains(t, response.Error, "diagnostic close not enabled") } func TestBrowserLaunchRelay_DiagnosticCloseDispatchedWithOptIn(t *testing.T) { t.Setenv(diagnosticWindowCloseEnvVar, "1") opener := &blockingRelayOpener{release: make(chan struct{}), received: make(chan string, 1)} close(opener.release) tracker := &closeTrackingOpener{blockingRelayOpener: opener, closed: make(chan struct{})} relay := startLeaseTestListener(t, tracker) response := sendRelayAction(t, relay.ipc.BrowserLaunchSocket, "close-all-windows") require.True(t, response.Accepted) select { case <-tracker.closed: case <-time.After(3 * time.Second): t.Fatal("diagnostic close never reached the opener") } }