@@ -642,17 +642,36 @@ func protoWS(path, dataDir, clientID string) proto.Workspace {
642 return proto.Workspace{Path: path, DataDir: dataDir, ClientID: clientID}
642 return proto.Workspace{Path: path, DataDir: dataDir, ClientID: clientID}
645+// syncBuffer is a thread-safe buffer that can be safely read and written
646+// from multiple goroutines.
647+type syncBuffer struct {
652+func (sb *syncBuffer) Write(p []byte) (n int, err error) {
654+ defer sb.mu.Unlock()
655+ return sb.buf.Write(p)
658+func (sb *syncBuffer) String() string {
660+ defer sb.mu.Unlock()
661+ return sb.buf.String()
645// captureDebugLogs installs a buffer-backed slog handler at Debug
664// captureDebugLogs installs a buffer-backed slog handler at Debug
646// level for the duration of the test, returning the buffer. The
665// level for the duration of the test, returning the buffer. The
647// previous default handler is restored via t.Cleanup.
666// previous default handler is restored via t.Cleanup.
648−func captureDebugLogs(t *testing.T) *bytes.Buffer {
667+func captureDebugLogs(t *testing.T) *syncBuffer {
649 t.Helper()
668 t.Helper()
650− var buf bytes.Buffer
669+ var sb syncBuffer
651 prev := slog.Default()
670 prev := slog.Default()
652− handler := slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelDebug})
671+ handler := slog.NewTextHandler(&sb, &slog.HandlerOptions{Level: slog.LevelDebug})
653 slog.SetDefault(slog.New(handler))
672 slog.SetDefault(slog.New(handler))
654 t.Cleanup(func() { slog.SetDefault(prev) })
673 t.Cleanup(func() { slog.SetDefault(prev) })
655− return &buf
674+ return &sb
658// xdgIsolated points HOME and XDG_* variables at fresh tempdirs so
677// xdgIsolated points HOME and XDG_* variables at fresh tempdirs so