Move logger mocks to a non-test file so they can be used elsewhere.

This commit is contained in:
Alex Bramley 2011-10-22 16:15:46 +01:00
parent 2467e5cc93
commit dee808a263
2 changed files with 86 additions and 78 deletions

View File

@ -1,95 +1,21 @@
package logging package logging
import ( import (
"os"
"strings"
"testing" "testing"
) )
// Note: the below is deliberately PLACED AT THE TOP OF THIS FILE because // Note: the below is deliberately PLACED AT THE TOP OF THIS FILE because
// it is fragile. It ensures the right file:line is logged. Sorry! // it is fragile. It ensures the right file:line is logged. Sorry!
func TestLogCorrectLineNumbers(t *testing.T) { func TestLogCorrectLineNumbers(t *testing.T) {
l, m := SetUp() l, m := NewMock()
l.Log(Error, "Error!") l.Log(Error, "Error!")
if s := string(m[Error].written); s[20:] != "log_test.go:13: ERROR Error!\n" { if s := string(m[Error].written); s[20:] != "log_test.go:11: ERROR Error!\n" {
t.Errorf("Error incorrectly logged (check line numbers!)") t.Errorf("Error incorrectly logged (check line numbers!)")
} }
} }
type writerMap map[LogLevel]*mockWriter
type mockWriter struct {
written []byte
}
func (w *mockWriter) Write(p []byte) (n int, err os.Error) {
w.written = append(w.written, p...)
return len(p), nil
}
func (w *mockWriter) reset() {
w.written = w.written[:0]
}
// Make these accessible for other packages doing logging testing
func SetUp() (*logger, writerMap) {
wMap := writerMap{
Debug: &mockWriter{make([]byte, 0)},
Info: &mockWriter{make([]byte, 0)},
Warn: &mockWriter{make([]byte, 0)},
Error: &mockWriter{make([]byte, 0)},
Fatal: &mockWriter{make([]byte, 0)},
}
logMap := make(LogMap)
for lv, w := range wMap {
logMap[lv] = makeLogger(w)
}
return New(logMap, Error, false), wMap
}
func (m writerMap) CheckNothingWritten(t *testing.T) {
for lv, w := range m {
if len(w.written) > 0 {
t.Errorf("%d bytes logged at level %s, expected none:",
len(w.written), logString[lv])
t.Errorf("\t%s", w.written)
w.reset()
}
}
}
func (m writerMap) CheckWrittenAtLevel(t *testing.T, lv LogLevel, exp string) {
var w *mockWriter
if _, ok := m[lv]; !ok {
w = m[Debug]
} else {
w = m[lv]
}
if len(w.written) == 0 {
t.Errorf("No bytes logged at level %s, expected:", LogString(lv))
t.Errorf("\t%s", exp)
}
// 32 bytes covers the date, time and filename up to the colon in
// 2011/10/22 10:22:57 log_test.go:<line no>: <level> <log message>
s := string(w.written[32:])
// 2 covers the : itself and the extra space
idx := strings.Index(s, ":") + 2
// s will end in "\n", so -1 to chop that off too
s = s[idx:len(s)-1]
// expected won't contain the log level prefix, so prepend that
exp = LogString(lv) + " " + exp
if s != exp {
t.Errorf("Log message at level %s differed.", LogString(lv))
t.Errorf("\texp: %s\n\tgot: %s", exp, s)
}
w.reset()
// Calling checkNothingWritten here both tests that w.reset() works
// and verifies that nothing was written at any other levels.
m.CheckNothingWritten(t)
}
func TestStandardLogging(t *testing.T) { func TestStandardLogging(t *testing.T) {
l, m := SetUp() l, m := NewMock()
l.Log(4, "Nothing should be logged yet") l.Log(4, "Nothing should be logged yet")
m.CheckNothingWritten(t) m.CheckNothingWritten(t)
@ -108,7 +34,7 @@ func TestStandardLogging(t *testing.T) {
} }
func TestAllLoggingLevels(t *testing.T) { func TestAllLoggingLevels(t *testing.T) {
l, m := SetUp() l, m := NewMock()
l.SetLogLevel(5) l.SetLogLevel(5)
l.Log(4, "Log to level 4.") l.Log(4, "Log to level 4.")

82
logging/mock.go Normal file
View File

@ -0,0 +1,82 @@
package logging
import (
"os"
"strings"
"testing"
)
// These are provided to ease testing code that uses the logging pkg
type mockWriter struct {
written []byte
}
func (w *mockWriter) Write(p []byte) (n int, err os.Error) {
w.written = append(w.written, p...)
return len(p), nil
}
func (w *mockWriter) reset() {
w.written = w.written[:0]
}
type writerMap map[LogLevel]*mockWriter
// This doesn't create a mock Logger but a Logger that writes to mock outputs
func NewMock() (*logger, writerMap) {
wMap := writerMap{
Debug: &mockWriter{make([]byte, 0)},
Info: &mockWriter{make([]byte, 0)},
Warn: &mockWriter{make([]byte, 0)},
Error: &mockWriter{make([]byte, 0)},
Fatal: &mockWriter{make([]byte, 0)},
}
logMap := make(LogMap)
for lv, w := range wMap {
logMap[lv] = makeLogger(w)
}
return New(logMap, Error, false), wMap
}
func (m writerMap) CheckNothingWritten(t *testing.T) {
for lv, w := range m {
if len(w.written) > 0 {
t.Errorf("%d bytes logged at level %s, expected none:",
len(w.written), logString[lv])
t.Errorf("\t%s", w.written)
w.reset()
}
}
}
func (m writerMap) CheckWrittenAtLevel(t *testing.T, lv LogLevel, exp string) {
var w *mockWriter
if _, ok := m[lv]; !ok {
w = m[Debug]
} else {
w = m[lv]
}
if len(w.written) == 0 {
t.Errorf("No bytes logged at level %s, expected:", LogString(lv))
t.Errorf("\t%s", exp)
}
// 32 bytes covers the date, time and filename up to the colon in
// 2011/10/22 10:22:57 log_test.go:<line no>: <level> <log message>
s := string(w.written[32:])
// 2 covers the : itself and the extra space
idx := strings.Index(s, ":") + 2
// s will end in "\n", so -1 to chop that off too
s = s[idx:len(s)-1]
// expected won't contain the log level prefix, so prepend that
exp = LogString(lv) + " " + exp
if s != exp {
t.Errorf("Log message at level %s differed.", LogString(lv))
t.Errorf("\texp: %s\n\tgot: %s", exp, s)
}
w.reset()
// Calling checkNothingWritten here both tests that w.reset() works
// and verifies that nothing was written at any other levels.
m.CheckNothingWritten(t)
}