testing.go

 1package backend
 2
 3import "context"
 4
 5// InsertWorkspaceForTest registers ws with b under its current ID and
 6// path. It is intended for tests in other packages that need to drive
 7// HTTP handlers against a synthetic workspace without booting a real
 8// app.App. Production code should go through CreateWorkspace.
 9//
10// If the workspace has no run context yet it is derived from the
11// backend context (falling back to context.Background), mirroring the
12// initialization CreateWorkspace performs, so dispatched agent runs
13// have a non-nil ws.ctx.
14func InsertWorkspaceForTest(b *Backend, ws *Workspace) {
15	if ws.resolvedPath == "" {
16		ws.resolvedPath = ws.Path
17	}
18	if ws.clients == nil {
19		ws.clients = make(map[string]*clientState)
20	}
21	if ws.ctx == nil {
22		parent := b.ctx
23		if parent == nil {
24			parent = context.Background()
25		}
26		ws.ctx, ws.cancel = context.WithCancel(parent)
27	}
28	b.mu.Lock()
29	defer b.mu.Unlock()
30	b.workspaces.Set(ws.ID, ws)
31	if ws.resolvedPath != "" {
32		b.pathIndex[ws.resolvedPath] = ws.ID
33	}
34}
35
36// RegisterClientForTesting installs a creation hold for clientID on
37// ws using the backend's normal registerClient path. Intended for
38// tests in other packages that need to drive a hold-only client
39// (streams == 0) without booting a real CreateWorkspace flow.
40func RegisterClientForTesting(b *Backend, ws *Workspace, clientID string) error {
41	if _, err := validateClientID(clientID); err != nil {
42		return err
43	}
44	b.registerClient(ws, clientID)
45	return nil
46}
47
48// SetWorkspaceShutdownFnForTest overrides the workspace teardown
49// callback. Useful for tests in other packages that drive synthetic
50// workspaces (where the embedded [app.App] is incomplete) through
51// detach paths that would otherwise crash inside App.Shutdown.
52func SetWorkspaceShutdownFnForTest(ws *Workspace, fn func()) {
53	ws.shutdownFn = fn
54}
55
56// WorkspaceLiveStreamCountForTest returns the number of clients on ws
57// that have at least one live SSE stream. Used by integration tests
58// in other packages to wait for SSE attaches before publishing events.
59func WorkspaceLiveStreamCountForTest(ws *Workspace) int {
60	ws.clientsMu.Lock()
61	defer ws.clientsMu.Unlock()
62	n := 0
63	for _, cs := range ws.clients {
64		if cs.streams > 0 {
65			n++
66		}
67	}
68	return n
69}