233 lines
4.4 KiB
Go
233 lines
4.4 KiB
Go
package colog
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math/rand"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
type outputTest struct {
|
|
in string
|
|
out string
|
|
}
|
|
|
|
var outputTests = []outputTest{
|
|
{"Info should be green %s", "[INF] Info should be green %s\n"},
|
|
}
|
|
|
|
func TestColors(t *testing.T) {
|
|
|
|
log.SetFlags(log.LstdFlags)
|
|
Register()
|
|
|
|
Get().SetMinLevel(LDebug)
|
|
Get().SetDefaultLevel(LDebug)
|
|
|
|
for _, tt := range outputTests {
|
|
tt.in = fmt.Sprintf(tt.in, "")
|
|
log.Println(tt.in)
|
|
}
|
|
}
|
|
|
|
func TestDefaultLevel(t *testing.T) {
|
|
|
|
tw := new(mockWriter)
|
|
log.SetFlags(0)
|
|
Register()
|
|
Get().SetOutput(tw)
|
|
Get().SetFormatter(&StdFormatter{Colors: false})
|
|
Get().SetDefaultLevel(LDebug)
|
|
|
|
log.Println("no prefix text")
|
|
if "[INF] no prefix text\n" != tw.String() {
|
|
t.Fatalf("Default level failed: %s", tw.String())
|
|
}
|
|
}
|
|
|
|
func TestMinDefaultLevel(t *testing.T) {
|
|
|
|
tw := new(mockWriter)
|
|
log.SetFlags(0)
|
|
Register()
|
|
Get().SetOutput(tw)
|
|
Get().SetFormatter(&StdFormatter{Colors: false})
|
|
|
|
Get().SetMinLevel(LDebug)
|
|
Get().SetDefaultLevel(LDebug)
|
|
log.Println("no prefix text")
|
|
if "[INF] no prefix text\n" != tw.String() {
|
|
t.Fatalf("Default level failed: %s", tw.String())
|
|
}
|
|
|
|
Get().SetMinLevel(LError)
|
|
log.Println("should not print")
|
|
if "[INF] no prefix text\n" != tw.String() {
|
|
t.Fatalf("Default level failed: %s", tw.String())
|
|
}
|
|
}
|
|
|
|
func TestPrefix(t *testing.T) {
|
|
|
|
tw := new(mockWriter)
|
|
cl := NewCoLog(tw, "abc ", 0)
|
|
cl.SetFormatter(&StdFormatter{Colors: false})
|
|
|
|
logger := cl.NewLogger()
|
|
logger.Println("some text")
|
|
if "[INF] abc some text\n" != tw.String() {
|
|
t.Fatalf("Prefix output failed: %s", tw.String())
|
|
}
|
|
}
|
|
|
|
func TestSimpleOutput(t *testing.T) {
|
|
|
|
tw := new(mockWriter)
|
|
cl := NewCoLog(tw, "", 0)
|
|
cl.SetFormatter(&StdFormatter{Colors: false})
|
|
logger := cl.NewLogger()
|
|
for k, tt := range outputTests {
|
|
|
|
seq := randSeq(k)
|
|
tt.in = fmt.Sprintf(tt.in, seq)
|
|
tt.out = fmt.Sprintf(tt.out, seq)
|
|
|
|
logger.Println(tt.in)
|
|
if tt.out != tw.String() {
|
|
t.Fatalf("Simple output not found:\n %s\n %s", tt.out, string(tw.Data))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOutputRace(t *testing.T) {
|
|
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(1)
|
|
|
|
go testStdLoggerOutput(t, &wg)
|
|
for i := 0; i < 100; i++ {
|
|
wg.Add(1)
|
|
go testNewLoggerOutput(t, &wg)
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|
|
|
|
func testStdLoggerOutput(t *testing.T, wg *sync.WaitGroup) {
|
|
|
|
tb := new(mockBufferWriter)
|
|
tb.Data = make(map[string][]byte, len(outputTests))
|
|
log.SetFlags(0)
|
|
Register()
|
|
Get().SetOutput(tb)
|
|
Get().SetMinLevel(LDebug)
|
|
Get().SetDefaultLevel(LDebug)
|
|
Get().SetFormatter(&StdFormatter{Colors: false})
|
|
|
|
for k, tt := range outputTests {
|
|
wg.Add(1)
|
|
go func(tt outputTest, k int) {
|
|
|
|
seq := randSeq(k)
|
|
tt.in = fmt.Sprintf(tt.in, seq)
|
|
tt.out = fmt.Sprintf(tt.out, seq)
|
|
|
|
log.Println(tt.in)
|
|
if !tb.IsWritten(tt.out) {
|
|
t.Errorf("Raced std output not found: %s", tt.out)
|
|
}
|
|
wg.Done()
|
|
}(tt, k)
|
|
}
|
|
|
|
wg.Done()
|
|
}
|
|
|
|
func testNewLoggerOutput(t *testing.T, wg *sync.WaitGroup) {
|
|
|
|
tb := new(mockBufferWriter)
|
|
tb.Data = make(map[string][]byte, len(outputTests))
|
|
cl := NewCoLog(tb, "", 0)
|
|
cl.SetFormatter(&StdFormatter{Colors: false})
|
|
logger := cl.NewLogger()
|
|
|
|
for k, tt := range outputTests {
|
|
wg.Add(1)
|
|
go func(tt outputTest, k int) {
|
|
|
|
seq := randSeq(k)
|
|
tt.in = fmt.Sprintf(tt.in, seq)
|
|
tt.out = fmt.Sprintf(tt.out, seq)
|
|
|
|
logger.Println(tt.in)
|
|
if !tb.IsWritten(tt.out) {
|
|
t.Errorf("Raced logger output not found: %s", tt.out)
|
|
}
|
|
wg.Done()
|
|
}(tt, k)
|
|
}
|
|
|
|
wg.Done()
|
|
}
|
|
|
|
type mockWriter struct {
|
|
mux sync.Mutex
|
|
Data []byte
|
|
}
|
|
|
|
func (tw *mockWriter) Write(p []byte) (n int, err error) {
|
|
tw.mux.Lock()
|
|
defer tw.mux.Unlock()
|
|
tw.Data = p
|
|
return len(p), nil
|
|
}
|
|
|
|
func (tw *mockWriter) String() string {
|
|
tw.mux.Lock()
|
|
defer tw.mux.Unlock()
|
|
return string(tw.Data)
|
|
}
|
|
|
|
type mockBufferWriter struct {
|
|
mux sync.Mutex
|
|
Data map[string][]byte
|
|
}
|
|
|
|
func (tb *mockBufferWriter) Write(p []byte) (n int, err error) {
|
|
tb.mux.Lock()
|
|
defer tb.mux.Unlock()
|
|
tb.Data[string(p)] = p
|
|
return len(p), nil
|
|
}
|
|
|
|
func (tb *mockBufferWriter) IsWritten(s string) bool {
|
|
tb.mux.Lock()
|
|
defer tb.mux.Unlock()
|
|
_, ok := tb.Data[s]
|
|
return ok
|
|
}
|
|
|
|
type mockHook struct {
|
|
entry *Entry
|
|
levels []Level
|
|
}
|
|
|
|
func (h *mockHook) Levels() []Level {
|
|
return h.levels
|
|
}
|
|
|
|
func (h *mockHook) Fire(e *Entry) error {
|
|
h.entry = e
|
|
return nil
|
|
}
|
|
|
|
func randSeq(n int) string {
|
|
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
b := make([]rune, n)
|
|
for i := range b {
|
|
b[i] = letters[rand.Intn(len(letters))]
|
|
}
|
|
return string(b)
|
|
}
|