diff options
Diffstat (limited to 'logger/loggers_test.go')
-rw-r--r-- | logger/loggers_test.go | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/logger/loggers_test.go b/logger/loggers_test.go new file mode 100644 index 000000000..adc4df016 --- /dev/null +++ b/logger/loggers_test.go @@ -0,0 +1,174 @@ +package logger + +import ( + "io/ioutil" + "math/rand" + "os" + "sync" + "testing" + "time" +) + +type TestLogSystem struct { + mutex sync.Mutex + output string + level LogLevel +} + +func (ls *TestLogSystem) LogPrint(level LogLevel, msg string) { + ls.mutex.Lock() + ls.output += msg + ls.mutex.Unlock() +} + +func (ls *TestLogSystem) SetLogLevel(i LogLevel) { + ls.mutex.Lock() + ls.level = i + ls.mutex.Unlock() +} + +func (ls *TestLogSystem) GetLogLevel() LogLevel { + ls.mutex.Lock() + defer ls.mutex.Unlock() + return ls.level +} + +func (ls *TestLogSystem) CheckOutput(t *testing.T, expected string) { + ls.mutex.Lock() + output := ls.output + ls.mutex.Unlock() + if output != expected { + t.Errorf("log output mismatch:\n got: %q\n want: %q\n", output, expected) + } +} + +type blockedLogSystem struct { + LogSystem + unblock chan struct{} +} + +func (ls blockedLogSystem) LogPrint(level LogLevel, msg string) { + <-ls.unblock + ls.LogSystem.LogPrint(level, msg) +} + +func TestLoggerFlush(t *testing.T) { + Reset() + + logger := NewLogger("TEST") + ls := blockedLogSystem{&TestLogSystem{level: WarnLevel}, make(chan struct{})} + AddLogSystem(ls) + for i := 0; i < 5; i++ { + // these writes shouldn't hang even though ls is blocked + logger.Errorf(".") + } + + beforeFlush := time.Now() + time.AfterFunc(80*time.Millisecond, func() { close(ls.unblock) }) + Flush() // this should hang for approx. 80ms + if blockd := time.Now().Sub(beforeFlush); blockd < 80*time.Millisecond { + t.Errorf("Flush didn't block long enough, blocked for %v, should've been >= 80ms", blockd) + } + + ls.LogSystem.(*TestLogSystem).CheckOutput(t, "[TEST] .[TEST] .[TEST] .[TEST] .[TEST] .") +} + +func TestLoggerPrintln(t *testing.T) { + Reset() + + logger := NewLogger("TEST") + testLogSystem := &TestLogSystem{level: WarnLevel} + AddLogSystem(testLogSystem) + logger.Errorln("error") + logger.Warnln("warn") + logger.Infoln("info") + logger.Debugln("debug") + Flush() + + testLogSystem.CheckOutput(t, "[TEST] error\n[TEST] warn\n") +} + +func TestLoggerPrintf(t *testing.T) { + Reset() + + logger := NewLogger("TEST") + testLogSystem := &TestLogSystem{level: WarnLevel} + AddLogSystem(testLogSystem) + logger.Errorf("error to %v\n", []int{1, 2, 3}) + logger.Warnf("warn %%d %d", 5) + logger.Infof("info") + logger.Debugf("debug") + Flush() + testLogSystem.CheckOutput(t, "[TEST] error to [1 2 3]\n[TEST] warn %d 5") +} + +func TestMultipleLogSystems(t *testing.T) { + Reset() + + logger := NewLogger("TEST") + testLogSystem0 := &TestLogSystem{level: ErrorLevel} + testLogSystem1 := &TestLogSystem{level: WarnLevel} + AddLogSystem(testLogSystem0) + AddLogSystem(testLogSystem1) + logger.Errorln("error") + logger.Warnln("warn") + Flush() + + testLogSystem0.CheckOutput(t, "[TEST] error\n") + testLogSystem1.CheckOutput(t, "[TEST] error\n[TEST] warn\n") +} + +func TestFileLogSystem(t *testing.T) { + Reset() + + logger := NewLogger("TEST") + filename := "test.log" + file, _ := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm) + testLogSystem := NewStdLogSystem(file, 0, WarnLevel) + AddLogSystem(testLogSystem) + logger.Errorf("error to %s\n", filename) + logger.Warnln("warn") + Flush() + contents, _ := ioutil.ReadFile(filename) + output := string(contents) + if output != "[TEST] error to test.log\n[TEST] warn\n" { + t.Error("Expected contents of file 'test.log': '[TEST] error to test.log\\n[TEST] warn\\n', got ", output) + } else { + os.Remove(filename) + } +} + +func TestNoLogSystem(t *testing.T) { + Reset() + + logger := NewLogger("TEST") + logger.Warnln("warn") + Flush() +} + +func TestConcurrentAddSystem(t *testing.T) { + rand.Seed(time.Now().Unix()) + Reset() + + logger := NewLogger("TEST") + stop := make(chan struct{}) + writer := func() { + select { + case <-stop: + return + default: + logger.Infoln("foo") + Flush() + } + } + + go writer() + go writer() + + stopTime := time.Now().Add(100 * time.Millisecond) + for time.Now().Before(stopTime) { + time.Sleep(time.Duration(rand.Intn(20)) * time.Millisecond) + AddLogSystem(NewStdLogSystem(ioutil.Discard, 0, InfoLevel)) + } + close(stop) +} |