返回 DeepSeek-Reasonix
inspect_test.go
根目录 / internal / sessioncatalog / inspect_test.go
1 package sessioncatalog
2
3 import (
4 "context"
5 "errors"
6 "path/filepath"
7 "strings"
8 "testing"
9 )
10
11 func TestInspectReturnsCompleteHealthyStatistics(t *testing.T) {
12 ctx := context.Background()
13 path := filepath.Join(t.TempDir(), "catalog %20 # 会话.sqlite")
14 catalog, err := Open(ctx, Options{Path: path, DisableRepair: true})
15 if err != nil {
16 t.Fatal(err)
17 }
18 for _, statement := range []string{
19 `UPDATE catalog_state SET revision=42 WHERE id=1`,
20 `INSERT INTO catalog_sessions(path,path_key,directory,directory_key,scope,topic_id,turns_state,repair_state,repair_error_kind)
21 VALUES('/sessions/a.jsonl','/sessions/a.jsonl','/sessions','/sessions','global','topic-a','unknown','blocked','parse')`,
22 `INSERT INTO catalog_topics(scope,workspace_root_key,topic_id) VALUES('global','','topic-a')`,
23 } {
24 if _, err := catalog.db.ExecContext(ctx, statement); err != nil {
25 _ = catalog.Close(ctx)
26 t.Fatal(err)
27 }
28 }
29 if err := catalog.Close(ctx); err != nil {
30 t.Fatal(err)
31 }
32
33 status, err := Inspect(ctx, path)
34 if err != nil {
35 t.Fatal(err)
36 }
37 if status.State != StateReady || status.Revision != 42 || status.Indexed != 1 || status.PhysicalSessions != 1 || status.LogicalSessions != 1 {
38 t.Fatalf("unexpected inspection: %+v", status)
39 }
40 if status.RepairPending != 1 || status.RepairBlocked != 1 || status.RepairErrorKinds["parse"] != 1 {
41 t.Fatalf("repair statistics: %+v", status)
42 }
43 }
44
45 func TestInspectReportsQueryFailureAsDegradedWithoutPartialStatistics(t *testing.T) {
46 ctx := context.Background()
47 path := filepath.Join(t.TempDir(), "catalog.sqlite")
48 catalog, err := Open(ctx, Options{Path: path, DisableRepair: true})
49 if err != nil {
50 t.Fatal(err)
51 }
52 if _, err := catalog.db.ExecContext(ctx, `UPDATE catalog_state SET revision=42 WHERE id=1; DROP TABLE catalog_sessions`); err != nil {
53 _ = catalog.Close(ctx)
54 t.Fatal(err)
55 }
56 if err := catalog.Close(ctx); err != nil {
57 t.Fatal(err)
58 }
59
60 status, err := Inspect(ctx, path)
61 if err != nil {
62 t.Fatal(err)
63 }
64 if status.State != StateDegraded || status.Revision != 0 || status.Indexed != 0 {
65 t.Fatalf("query failure published partial statistics: %+v", status)
66 }
67 if !strings.Contains(status.LastError, "count indexed sessions") {
68 t.Fatalf("last error lacks failing stage: %q", status.LastError)
69 }
70 }
71
72 func TestInspectReturnsContextCancellation(t *testing.T) {
73 ctx, cancel := context.WithCancel(context.Background())
74 cancel()
75 _, err := Inspect(ctx, filepath.Join(t.TempDir(), "missing.sqlite"))
76 if !errors.Is(err, context.Canceled) {
77 t.Fatalf("Inspect error = %v, want context cancellation", err)
78 }
79 }
80
81 func TestInspectReadsCommittedWALWhileCatalogIsOpen(t *testing.T) {
82 path := filepath.Join(t.TempDir(), "live.sqlite")
83 catalog, err := Open(t.Context(), Options{Path: path, DisableRepair: true})
84 if err != nil {
85 t.Fatal(err)
86 }
87 defer catalog.Close(t.Context())
88 if _, err := catalog.db.ExecContext(t.Context(), `PRAGMA wal_autocheckpoint=0; UPDATE catalog_state SET revision=42 WHERE id=1`); err != nil {
89 t.Fatal(err)
90 }
91 status, err := Inspect(t.Context(), path)
92 if err != nil || status.State != StateReady || status.Revision != 42 {
93 t.Fatalf("live WAL inspection = %+v, %v", status, err)
94 }
95 }
96
96 lines GO