返回 DeepSeek-Reasonix
session_catalog_topic_helpers_test.go
根目录 / desktop / session_catalog_topic_helpers_test.go
1 package main
2
3 import (
4 "testing"
5 "time"
6 )
7
8 const sessionCatalogTestDeadline = 30 * time.Second
9
10 func waitForInitialCatalogReconcile(t *testing.T, app *App) bool {
11 t.Helper()
12 app.catalogLifecycleMu.Lock()
13 alreadyStarted := app.catalogInitialReconcileDone != nil
14 app.catalogLifecycleMu.Unlock()
15 app.startSessionCatalog()
16 app.catalogLifecycleMu.Lock()
17 done := app.catalogInitialReconcileDone
18 app.catalogLifecycleMu.Unlock()
19 if done == nil {
20 t.Fatal("session catalog initial reconcile was not armed")
21 }
22 select {
23 case <-done:
24 case <-time.After(sessionCatalogTestDeadline):
25 t.Fatal("session catalog initial reconcile did not finish")
26 }
27 if app.sessionCatalog.Load() == nil {
28 t.Fatal("session catalog exited before publication")
29 }
30 return alreadyStarted
31 }
32
33 func waitForCatalogReconcileJobs(t *testing.T, app *App) {
34 t.Helper()
35 jobs := make([]<-chan struct{}, 0)
36 for _, target := range app.sessionCatalogTargets() {
37 if !app.requestSessionCatalogReconcile(target.Path) {
38 t.Fatalf("request catalog reconcile for %q", target.Path)
39 }
40 key := projectRootKey(target.Path)
41 app.catalogReconcileMu.Lock()
42 if job := app.catalogReconcileJobs[key]; job != nil {
43 jobs = append(jobs, job.done)
44 }
45 app.catalogReconcileMu.Unlock()
46 }
47 deadline := time.Now().Add(sessionCatalogTestDeadline)
48 for _, done := range jobs {
49 if !waitChannelBefore(done, deadline) {
50 t.Fatal("explicit session catalog reconcile did not finish")
51 }
52 }
53 }
54
55 func waitForCatalogTopic(t *testing.T, app *App, scope, workspaceRoot, topicID string) []ProjectNode {
56 t.Helper()
57 alreadyStarted := waitForInitialCatalogReconcile(t, app)
58 t.Cleanup(func() { app.stopSessionCatalog(time.Second) })
59 if alreadyStarted {
60 waitForCatalogReconcileJobs(t, app)
61 }
62 nodes := app.ListProjectTree()
63 for _, folder := range nodes {
64 if scope == "project" && (!sameProjectRoot(folder.Root, workspaceRoot) || folder.Kind != "project") {
65 continue
66 }
67 if scope != "project" && folder.Kind != "global_folder" {
68 continue
69 }
70 for _, topic := range folder.Children {
71 if topic.TopicID == topicID {
72 return nodes
73 }
74 }
75 }
76 t.Fatalf("catalog topic %q did not become visible after reconciliation: %#v", topicID, nodes)
77 return nil
78 }
79
80 func waitForCatalogTreeCondition(t *testing.T, app *App, description string, matches func([]ProjectNode) bool) []ProjectNode {
81 t.Helper()
82 alreadyStarted := waitForInitialCatalogReconcile(t, app)
83 if alreadyStarted {
84 waitForCatalogReconcileJobs(t, app)
85 }
86 nodes := app.ListProjectTree()
87 if matches(nodes) {
88 return nodes
89 }
90 t.Fatalf("catalog did not reach %s: %#v", description, nodes)
91 return nil
92 }
93
93 lines GO