返回 DeepSeek-Reasonix
service_shutdown_test.go
根目录 / internal / session / service_shutdown_test.go
1 package session
2
3 import (
4 "context"
5 "errors"
6 "testing"
7 )
8
9 func TestServiceCloseAllPreservesBindingAndReleasesIdleLease(t *testing.T) {
10 persistence := NewFilesystemPersistence(t.TempDir())
11 service, err := NewService("local", persistence)
12 if err != nil {
13 t.Fatal(err)
14 }
15 t.Cleanup(func() { _ = service.CloseAll(context.Background()) })
16 runtime, err := service.Create(t.Context(), CreateOptions{SessionID: "shutdown"})
17 if err != nil {
18 t.Fatal(err)
19 }
20 binding, err := service.Bind(runtime)
21 if err != nil {
22 t.Fatal(err)
23 }
24 if err := service.CloseAll(t.Context()); !errors.Is(err, ErrRuntimeBound) {
25 t.Fatalf("close bound runtime = %v", err)
26 }
27 if current, ok := service.Runtime(runtime.Ref()); !ok || current != runtime {
28 t.Fatal("shutdown removed a bound runtime")
29 }
30 if err := binding.Release(t.Context()); err != nil {
31 t.Fatal(err)
32 }
33 if err := service.CloseAll(t.Context()); err != nil {
34 t.Fatal(err)
35 }
36 other, err := NewService("local", persistence)
37 if err != nil {
38 t.Fatal(err)
39 }
40 t.Cleanup(func() { _ = other.CloseAll(context.Background()) })
41 reopened, err := other.EnsureExecution(t.Context(), runtime.Ref())
42 if err != nil {
43 t.Fatalf("writer lease was not released: %v", err)
44 }
45 if err := reopened.Release(t.Context()); err != nil {
46 t.Fatal(err)
47 }
48 if err := other.CloseAll(t.Context()); err != nil {
49 t.Fatal(err)
50 }
51 }
52
53 // A client that never releases its binding must not keep the writer lease and
54 // recovery handles alive past Shutdown: Windows cannot remove the store root
55 // while those handles are open, and the process has no later chance to close
56 // them. Shutdown reports the leak and still releases the root.
57 func TestServiceShutdownReleasesLeakedBindingLease(t *testing.T) {
58 root := t.TempDir()
59 service, err := NewService("local", NewFilesystemPersistence(root))
60 if err != nil {
61 t.Fatal(err)
62 }
63 runtime, err := service.Create(t.Context(), CreateOptions{SessionID: "leaked"})
64 if err != nil {
65 t.Fatal(err)
66 }
67 if _, err := service.Bind(runtime); err != nil {
68 t.Fatal(err)
69 }
70 if err := service.Shutdown(t.Context()); !errors.Is(err, ErrRuntimeBound) {
71 t.Fatalf("Shutdown = %v, want the leaked binding reported", err)
72 }
73 if _, ok := service.Runtime(runtime.Ref()); ok {
74 t.Fatal("Shutdown left the runtime published")
75 }
76 other, err := NewService("local", NewFilesystemPersistence(root))
77 if err != nil {
78 t.Fatal(err)
79 }
80 t.Cleanup(func() { _ = other.Shutdown(context.Background()) })
81 reopened, err := other.EnsureExecution(t.Context(), runtime.Ref())
82 if err != nil {
83 t.Fatalf("writer lease survived Shutdown: %v", err)
84 }
85 if err := reopened.Release(t.Context()); err != nil {
86 t.Fatal(err)
87 }
88 }
89
89 lines GO