|
|
package logrus
import ( "bytes" "encoding/json" "strconv" "strings" "sync" "testing"
"github.com/stretchr/testify/assert" )
func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) { var buffer bytes.Buffer var fields Fields
logger := New() logger.Out = &buffer logger.Formatter = new(JSONFormatter)
log(logger)
err := json.Unmarshal(buffer.Bytes(), &fields) assert.Nil(t, err)
assertions(fields) }
func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) { var buffer bytes.Buffer
logger := New() logger.Out = &buffer logger.Formatter = &TextFormatter{ DisableColors: true, }
log(logger)
fields := make(map[string]string) for _, kv := range strings.Split(buffer.String(), " ") { if !strings.Contains(kv, "=") { continue } kvArr := strings.Split(kv, "=") key := strings.TrimSpace(kvArr[0]) val := kvArr[1] if kvArr[1][0] == '"' { var err error val, err = strconv.Unquote(val) assert.NoError(t, err) } fields[key] = val } assertions(fields) }
func TestPrint(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.Print("test") }, func(fields Fields) { assert.Equal(t, fields["msg"], "test") assert.Equal(t, fields["level"], "info") }) }
func TestInfo(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.Info("test") }, func(fields Fields) { assert.Equal(t, fields["msg"], "test") assert.Equal(t, fields["level"], "info") }) }
func TestWarn(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.Warn("test") }, func(fields Fields) { assert.Equal(t, fields["msg"], "test") assert.Equal(t, fields["level"], "warning") }) }
func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.Infoln("test", "test") }, func(fields Fields) { assert.Equal(t, fields["msg"], "test test") }) }
func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.Infoln("test", 10) }, func(fields Fields) { assert.Equal(t, fields["msg"], "test 10") }) }
func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.Infoln(10, 10) }, func(fields Fields) { assert.Equal(t, fields["msg"], "10 10") }) }
func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.Infoln(10, 10) }, func(fields Fields) { assert.Equal(t, fields["msg"], "10 10") }) }
func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.Info("test", 10) }, func(fields Fields) { assert.Equal(t, fields["msg"], "test10") }) }
func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.Info("test", "test") }, func(fields Fields) { assert.Equal(t, fields["msg"], "testtest") }) }
func TestWithFieldsShouldAllowAssignments(t *testing.T) { var buffer bytes.Buffer var fields Fields
logger := New() logger.Out = &buffer logger.Formatter = new(JSONFormatter)
localLog := logger.WithFields(Fields{ "key1": "value1", })
localLog.WithField("key2", "value2").Info("test") err := json.Unmarshal(buffer.Bytes(), &fields) assert.Nil(t, err)
assert.Equal(t, "value2", fields["key2"]) assert.Equal(t, "value1", fields["key1"])
buffer = bytes.Buffer{} fields = Fields{} localLog.Info("test") err = json.Unmarshal(buffer.Bytes(), &fields) assert.Nil(t, err)
_, ok := fields["key2"] assert.Equal(t, false, ok) assert.Equal(t, "value1", fields["key1"]) }
func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.WithField("msg", "hello").Info("test") }, func(fields Fields) { assert.Equal(t, fields["msg"], "test") }) }
func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.WithField("msg", "hello").Info("test") }, func(fields Fields) { assert.Equal(t, fields["msg"], "test") assert.Equal(t, fields["fields.msg"], "hello") }) }
func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.WithField("time", "hello").Info("test") }, func(fields Fields) { assert.Equal(t, fields["fields.time"], "hello") }) }
func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) { LogAndAssertJSON(t, func(log *Logger) { log.WithField("level", 1).Info("test") }, func(fields Fields) { assert.Equal(t, fields["level"], "info") assert.Equal(t, fields["fields.level"], 1.0) // JSON has floats only
}) }
func TestDefaultFieldsAreNotPrefixed(t *testing.T) { LogAndAssertText(t, func(log *Logger) { ll := log.WithField("herp", "derp") ll.Info("hello") ll.Info("bye") }, func(fields map[string]string) { for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} { if _, ok := fields[fieldName]; ok { t.Fatalf("should not have prefixed %q: %v", fieldName, fields) } } }) }
func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
var buffer bytes.Buffer var fields Fields
logger := New() logger.Out = &buffer logger.Formatter = new(JSONFormatter)
llog := logger.WithField("context", "eating raw fish")
llog.Info("looks delicious")
err := json.Unmarshal(buffer.Bytes(), &fields) assert.NoError(t, err, "should have decoded first message") assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields") assert.Equal(t, fields["msg"], "looks delicious") assert.Equal(t, fields["context"], "eating raw fish")
buffer.Reset()
llog.Warn("omg it is!")
err = json.Unmarshal(buffer.Bytes(), &fields) assert.NoError(t, err, "should have decoded second message") assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields") assert.Equal(t, fields["msg"], "omg it is!") assert.Equal(t, fields["context"], "eating raw fish") assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
}
func TestConvertLevelToString(t *testing.T) { assert.Equal(t, "debug", DebugLevel.String()) assert.Equal(t, "info", InfoLevel.String()) assert.Equal(t, "warning", WarnLevel.String()) assert.Equal(t, "error", ErrorLevel.String()) assert.Equal(t, "fatal", FatalLevel.String()) assert.Equal(t, "panic", PanicLevel.String()) }
func TestParseLevel(t *testing.T) { l, err := ParseLevel("panic") assert.Nil(t, err) assert.Equal(t, PanicLevel, l)
l, err = ParseLevel("PANIC") assert.Nil(t, err) assert.Equal(t, PanicLevel, l)
l, err = ParseLevel("fatal") assert.Nil(t, err) assert.Equal(t, FatalLevel, l)
l, err = ParseLevel("FATAL") assert.Nil(t, err) assert.Equal(t, FatalLevel, l)
l, err = ParseLevel("error") assert.Nil(t, err) assert.Equal(t, ErrorLevel, l)
l, err = ParseLevel("ERROR") assert.Nil(t, err) assert.Equal(t, ErrorLevel, l)
l, err = ParseLevel("warn") assert.Nil(t, err) assert.Equal(t, WarnLevel, l)
l, err = ParseLevel("WARN") assert.Nil(t, err) assert.Equal(t, WarnLevel, l)
l, err = ParseLevel("warning") assert.Nil(t, err) assert.Equal(t, WarnLevel, l)
l, err = ParseLevel("WARNING") assert.Nil(t, err) assert.Equal(t, WarnLevel, l)
l, err = ParseLevel("info") assert.Nil(t, err) assert.Equal(t, InfoLevel, l)
l, err = ParseLevel("INFO") assert.Nil(t, err) assert.Equal(t, InfoLevel, l)
l, err = ParseLevel("debug") assert.Nil(t, err) assert.Equal(t, DebugLevel, l)
l, err = ParseLevel("DEBUG") assert.Nil(t, err) assert.Equal(t, DebugLevel, l)
l, err = ParseLevel("invalid") assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error()) }
func TestGetSetLevelRace(t *testing.T) { wg := sync.WaitGroup{} for i := 0; i < 100; i++ { wg.Add(1) go func(i int) { defer wg.Done() if i%2 == 0 { SetLevel(InfoLevel) } else { GetLevel() } }(i)
} wg.Wait() }
func TestLoggingRace(t *testing.T) { logger := New()
var wg sync.WaitGroup wg.Add(100)
for i := 0; i < 100; i++ { go func() { logger.Info("info") wg.Done() }() } wg.Wait() }
// Compile test
func TestLogrusInterface(t *testing.T) { var buffer bytes.Buffer fn := func(l FieldLogger) { b := l.WithField("key", "value") b.Debug("Test") } // test logger
logger := New() logger.Out = &buffer fn(logger)
// test Entry
e := logger.WithField("another", "value") fn(e) }
// Implements io.Writer using channels for synchronization, so we can wait on
// the Entry.Writer goroutine to write in a non-racey way. This does assume that
// there is a single call to Logger.Out for each message.
type channelWriter chan []byte
func (cw channelWriter) Write(p []byte) (int, error) { cw <- p return len(p), nil }
func TestEntryWriter(t *testing.T) { cw := channelWriter(make(chan []byte, 1)) log := New() log.Out = cw log.Formatter = new(JSONFormatter) log.WithField("foo", "bar").WriterLevel(WarnLevel).Write([]byte("hello\n"))
bs := <-cw var fields Fields err := json.Unmarshal(bs, &fields) assert.Nil(t, err) assert.Equal(t, fields["foo"], "bar") assert.Equal(t, fields["level"], "warning") }
|