diff options
author | Jeffrey Wilcke <obscuren@users.noreply.github.com> | 2014-10-17 23:24:44 +0800 |
---|---|---|
committer | Jeffrey Wilcke <obscuren@users.noreply.github.com> | 2014-10-17 23:24:44 +0800 |
commit | fc308b842eafe6f6703dd21a003a8abaf3538aa4 (patch) | |
tree | 6a318065065568d7f0bad6d3dcd3e8a7ed3136b9 /ethlog/loggers_test.go | |
parent | e183880d8b02d4a9713b903acb41dd4381957f81 (diff) | |
parent | 35f339e9423bb3f3b5130e954e4a03937971b0ac (diff) | |
download | dexon-fc308b842eafe6f6703dd21a003a8abaf3538aa4.tar dexon-fc308b842eafe6f6703dd21a003a8abaf3538aa4.tar.gz dexon-fc308b842eafe6f6703dd21a003a8abaf3538aa4.tar.bz2 dexon-fc308b842eafe6f6703dd21a003a8abaf3538aa4.tar.lz dexon-fc308b842eafe6f6703dd21a003a8abaf3538aa4.tar.xz dexon-fc308b842eafe6f6703dd21a003a8abaf3538aa4.tar.zst dexon-fc308b842eafe6f6703dd21a003a8abaf3538aa4.zip |
Merge pull request #59 from fjl/feature/raceless-ethlog
Improve package ethlog
Diffstat (limited to 'ethlog/loggers_test.go')
-rw-r--r-- | ethlog/loggers_test.go | 131 |
1 files changed, 92 insertions, 39 deletions
diff --git a/ethlog/loggers_test.go b/ethlog/loggers_test.go index a9b1463e7..cf92e3cc6 100644 --- a/ethlog/loggers_test.go +++ b/ethlog/loggers_test.go @@ -1,49 +1,81 @@ package ethlog import ( - "fmt" "io/ioutil" + "math/rand" "os" + "sync" "testing" + "time" ) type TestLogSystem struct { - Output string + mutex sync.Mutex + output string level LogLevel } -func (t *TestLogSystem) Println(v ...interface{}) { - t.Output += fmt.Sprintln(v...) +func (ls *TestLogSystem) LogPrint(level LogLevel, msg string) { + ls.mutex.Lock() + ls.output += msg + ls.mutex.Unlock() } -func (t *TestLogSystem) Printf(format string, v ...interface{}) { - t.Output += fmt.Sprintf(format, v...) +func (ls *TestLogSystem) SetLogLevel(i LogLevel) { + ls.mutex.Lock() + ls.level = i + ls.mutex.Unlock() } -func (t *TestLogSystem) SetLogLevel(i LogLevel) { - t.level = i +func (ls *TestLogSystem) GetLogLevel() LogLevel { + ls.mutex.Lock() + defer ls.mutex.Unlock() + return ls.level } -func (t *TestLogSystem) GetLogLevel() LogLevel { - return t.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") - testLogSystem := &TestLogSystem{level: WarnLevel} - AddLogSystem(testLogSystem) + 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(".") } - Flush() - Reset() - output := testLogSystem.Output - if output != "[TEST] .[TEST] .[TEST] .[TEST] .[TEST] ." { - t.Error("Expected complete logger output '[TEST] .[TEST] .[TEST] .[TEST] .[TEST] .', got ", output) + + 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) @@ -52,31 +84,27 @@ func TestLoggerPrintln(t *testing.T) { logger.Infoln("info") logger.Debugln("debug") Flush() - Reset() - output := testLogSystem.Output - fmt.Println(quote(output)) - if output != "[TEST] error\n[TEST] warn\n" { - t.Error("Expected logger output '[TEST] error\\n[TEST] warn\\n', got ", output) - } + + 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", *testLogSystem) - logger.Warnf("warn") + logger.Errorf("error to %v\n", []int{1, 2, 3}) + logger.Warnf("warn %%d %d", 5) logger.Infof("info") logger.Debugf("debug") Flush() - Reset() - output := testLogSystem.Output - if output != "[TEST] error to { 2}\n[TEST] warn" { - t.Error("Expected logger output '[TEST] error to { 2}\\n[TEST] warn', got ", output) - } + 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} @@ -85,18 +113,14 @@ func TestMultipleLogSystems(t *testing.T) { logger.Errorln("error") logger.Warnln("warn") Flush() - Reset() - output0 := testLogSystem0.Output - output1 := testLogSystem1.Output - if output0 != "[TEST] error\n" { - t.Error("Expected logger 0 output '[TEST] error\\n', got ", output0) - } - if output1 != "[TEST] error\n[TEST] warn\n" { - t.Error("Expected logger 1 output '[TEST] error\\n[TEST] warn\\n', got ", output1) - } + + 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) @@ -115,7 +139,36 @@ func TestFileLogSystem(t *testing.T) { } 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) +} |