返回 DeepSeek-Reasonix
session_navigation_ownership_test.go
根目录 / desktop / session_navigation_ownership_test.go
1 package main
2
3 import (
4 "context"
5 "testing"
6
7 "reasonix/internal/control"
8 "reasonix/internal/session"
9 )
10
11 func TestCanonicalNavigationSameWorkspaceBlankRetainsHost(t *testing.T) {
12 app, tab, _, _, _ := canonicalWorkspaceOpenFixture(t)
13 root, workspace := tab.WorkspaceRoot, tab.SessionWorkspace.ID
14 app.acquireSharedHost(root)
15 tab.SharedHostKey = root
16 original := tab.Ctrl
17 active := &activeNavigationController{SessionAPI: original, IdentityLifecycle: original.(control.IdentityLifecycle), status: control.RuntimeStatus{Running: true}}
18 tab.Ctrl = active
19 t.Cleanup(original.Close)
20 target, err := app.desktopSessionService("").Create(t.Context(), session.CreateOptions{SessionID: "blank", CWD: root, Origin: session.SessionOriginNew})
21 if err != nil {
22 t.Fatal(err)
23 }
24 if err := app.workspaceRegistry().AttachSession(t.Context(), "", workspace, target.Ref().SessionID, ""); err != nil {
25 t.Fatal(err)
26 }
27 source := session.SessionRef{HostID: localDesktopHostID, SessionID: tab.SessionID}
28 if _, err := app.OpenSession(target.Ref()); err != nil {
29 t.Fatal(err)
30 }
31 if ref, _ := active.SessionRef(); ref != source || tab.Ctrl == active {
32 t.Fatal("blank target rebound the active source")
33 }
34 if refs, ok := sharedHostRefsForTest(t, app, root); !ok || refs != 2 {
35 t.Fatalf("both runtimes require a host reference, got %d", refs)
36 }
37 if _, err := app.OpenSession(source); err != nil {
38 t.Fatal(err)
39 }
40 if refs, ok := sharedHostRefsForTest(t, app, root); !ok || refs != 1 {
41 t.Fatalf("idle replacement leaked or released source host, refs=%d", refs)
42 }
43 }
44
45 func TestCanonicalNavigationFailureDoesNotDetachActiveSource(t *testing.T) {
46 app, tab, target, _, _ := canonicalWorkspaceOpenFixture(t)
47 original := tab.Ctrl
48 active := &activeNavigationController{SessionAPI: original, IdentityLifecycle: original.(control.IdentityLifecycle), status: control.RuntimeStatus{PendingPrompt: true}}
49 tab.Ctrl = active
50 before := tab.SessionID
51 if err := app.desktopSessionService("").Close(t.Context(), target.Ref()); err != nil {
52 t.Fatal(err)
53 }
54 other, err := session.NewService(localDesktopHostID, session.NewFilesystemPersistence(app.desktopSessions.root))
55 if err != nil {
56 t.Fatal(err)
57 }
58 t.Cleanup(func() { _ = other.Shutdown(context.Background()) })
59 lease, err := other.Open(t.Context(), target.Ref())
60 if err != nil {
61 t.Fatal(err)
62 }
63 t.Cleanup(func() { _ = lease.Release(context.Background()) })
64 if _, err := app.OpenSession(target.Ref()); err == nil {
65 t.Fatal("writer conflict accepted")
66 }
67 if tab.Ctrl != active || tab.SessionID != before || active.closed || len(app.detachedSessions) != 0 {
68 t.Fatal("failed target changed source ownership")
69 }
70 }
71
71 lines GO