diff --git a/internals/logger/logger.go b/internals/logger/logger.go index a4fa8e61e..15ae40574 100644 --- a/internals/logger/logger.go +++ b/internals/logger/logger.go @@ -73,10 +73,27 @@ func Debugf(format string, v ...interface{}) { logger.Debug(msg) } +type lockedBytesBuffer struct { + buffer bytes.Buffer + mutex sync.Mutex +} + +func (b *lockedBytesBuffer) Write(p []byte) (int, error) { + b.mutex.Lock() + defer b.mutex.Unlock() + return b.buffer.Write(p) +} + +func (b *lockedBytesBuffer) String() string { + b.mutex.Lock() + defer b.mutex.Unlock() + return b.buffer.String() +} + // MockLogger replaces the existing logger with a buffer and returns -// the log buffer and a restore function. -func MockLogger(prefix string) (buf *bytes.Buffer, restore func()) { - buf = &bytes.Buffer{} +// a Stringer returning the log buffer content and a restore function. +func MockLogger(prefix string) (fmt.Stringer, func()) { + buf := &lockedBytesBuffer{} oldLogger := SetLogger(New(buf, prefix)) return buf, func() { SetLogger(oldLogger) diff --git a/internals/logger/logger_test.go b/internals/logger/logger_test.go index e6d63c21f..cd4d9f476 100644 --- a/internals/logger/logger_test.go +++ b/internals/logger/logger_test.go @@ -16,10 +16,12 @@ package logger_test import ( "bytes" + "fmt" "os" "testing" . "gopkg.in/check.v1" + "gopkg.in/tomb.v2" "github.com/canonical/pebble/internals/logger" ) @@ -30,7 +32,7 @@ func Test(t *testing.T) { TestingT(t) } var _ = Suite(&LogSuite{}) type LogSuite struct { - logbuf *bytes.Buffer + logbuf fmt.Stringer restoreLogger func() } @@ -75,3 +77,19 @@ func (s *LogSuite) TestPanicf(c *C) { c.Check(func() { logger.Panicf("xyzzy") }, Panics, "xyzzy") c.Check(s.logbuf.String(), Matches, `20\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ PREFIX: PANIC xyzzy\n`) } + +func (s *LogSuite) TestMockLoggerReadWriteThreadsafe(c *C) { + var t tomb.Tomb + t.Go(func() error { + for i := 0; i < 100; i++ { + logger.Noticef("foo") + logger.Noticef("bar") + } + return nil + }) + for i := 0; i < 10; i++ { + logger.Noticef(s.logbuf.String()) + } + err := t.Wait() + c.Check(err, IsNil) +}