test: lock-protect fakeSender so -race CI passes
The CI runs go test with -race; the agent runner has two pump goroutines (pumpStdout + pumpStderr) writing through the sender concurrently, and the unprotected fakeSender slice append raced. The cancel_test had a local 'safeSender' workaround for the same issue; promote that mutex onto fakeSender itself so every test in the package is race-clean without per-test variants. - fakeSender grows mu sync.Mutex; Send takes/releases. New snapshot() helper for tests that want a stable copy. - cancel_test drops its local safeSender + sync import; uses fakeSender. Verified: go test -race ./... passes across all packages.
This commit is contained in:
@@ -4,20 +4,42 @@ import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"gitea.dcglab.co.uk/steve/restic-manager/internal/api"
|
||||
"gitea.dcglab.co.uk/steve/restic-manager/internal/restic"
|
||||
)
|
||||
|
||||
// fakeSender collects sent envelopes for assertions.
|
||||
type fakeSender struct{ envs []api.Envelope }
|
||||
// fakeSender collects sent envelopes for assertions. Lock-protected
|
||||
// because the runner's pumpStdout / pumpStderr goroutines call Send
|
||||
// concurrently — without the mutex, -race in CI flags every test
|
||||
// that exercises a Run* method with both pumps active.
|
||||
type fakeSender struct {
|
||||
mu sync.Mutex
|
||||
envs []api.Envelope
|
||||
}
|
||||
|
||||
func (s *fakeSender) Send(e api.Envelope) error {
|
||||
s.mu.Lock()
|
||||
s.envs = append(s.envs, e)
|
||||
s.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// snapshot returns a copy of the captured envelopes safe to read
|
||||
// without holding the lock. Tests use this when iterating envs while
|
||||
// other goroutines may still be writing — though in practice all
|
||||
// runner Run* methods join their pumps before returning, so callers
|
||||
// can also read .envs directly post-return.
|
||||
func (s *fakeSender) snapshot() []api.Envelope {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
out := make([]api.Envelope, len(s.envs))
|
||||
copy(out, s.envs)
|
||||
return out
|
||||
}
|
||||
|
||||
// setupScript writes a shell script (without shebang) to a temp dir,
|
||||
// names it "restic", makes it executable, and returns the path.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user