diff --git a/logbuffer_test.go b/logbuffer_test.go new file mode 100644 index 00000000..efd71031 --- /dev/null +++ b/logbuffer_test.go @@ -0,0 +1,36 @@ +package goss + +import ( + "bytes" + "sync" +) + +// syncBuffer is a bytes.Buffer that is safe to write and read concurrently. +// +// The serve tests capture log output by pointing the process-wide logger at a +// buffer with log.SetOutput. That destination is global, so a parallel test +// still writes into whichever buffer was installed last while its owner reads +// it — a data race on the buffer even though each test declares its own. +// Guarding the buffer removes the race without giving up the shared logger. +type syncBuffer struct { + mu sync.Mutex + buf bytes.Buffer +} + +func (b *syncBuffer) Write(p []byte) (int, error) { + b.mu.Lock() + defer b.mu.Unlock() + return b.buf.Write(p) +} + +func (b *syncBuffer) String() string { + b.mu.Lock() + defer b.mu.Unlock() + return b.buf.String() +} + +func (b *syncBuffer) Reset() { + b.mu.Lock() + defer b.mu.Unlock() + b.buf.Reset() +} diff --git a/serve_test.go b/serve_test.go index c7f64a26..90042c03 100644 --- a/serve_test.go +++ b/serve_test.go @@ -1,7 +1,6 @@ package goss import ( - "bytes" "log" "net/http" "net/http/httptest" @@ -44,7 +43,7 @@ func TestServeWithNoContentNegotiation(t *testing.T) { for testName := range tests { tc := tests[testName] t.Run(testName, func(t *testing.T) { - var logOutput bytes.Buffer + var logOutput syncBuffer log.SetOutput(&logOutput) config, err := util.NewConfig( @@ -158,7 +157,7 @@ func TestServeNegotiatingContent(t *testing.T) { for testName := range tests { tc := tests[testName] t.Run(testName, func(t *testing.T) { - var logOutput bytes.Buffer + var logOutput syncBuffer log.SetOutput(&logOutput) config, err := util.NewConfig( @@ -189,7 +188,7 @@ func TestServeNegotiatingContent(t *testing.T) { } func TestServeCacheWithNoContentNegotiation(t *testing.T) { - var logOutput bytes.Buffer + var logOutput syncBuffer log.SetOutput(&logOutput) const cache = time.Duration(time.Millisecond * 100) config, err := util.NewConfig( @@ -236,7 +235,7 @@ func TestServeCacheWithNoContentNegotiation(t *testing.T) { } func TestServeCacheNegotiatingContent(t *testing.T) { - var logOutput bytes.Buffer + var logOutput syncBuffer log.SetOutput(&logOutput) const cache = time.Duration(time.Millisecond * 100) config, err := util.NewConfig(