package zerolog import ( "bytes" "errors" "reflect" "testing" "time" ) func TestLog(t *testing.T) { t.Run("empty", func(t *testing.T) { out := &bytes.Buffer{} log := New(out) log.Log().Msg("") if got, want := out.String(), "{}\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } }) t.Run("one-field", func(t *testing.T) { out := &bytes.Buffer{} log := New(out) log.Log().Str("foo", "bar").Msg("") if got, want := out.String(), `{"foo":"bar"}`+"\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } }) t.Run("two-field", func(t *testing.T) { out := &bytes.Buffer{} log := New(out) log.Log(). Str("foo", "bar"). Int("n", 123). Msg("") if got, want := out.String(), `{"foo":"bar","n":123}`+"\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } }) } func TestInfo(t *testing.T) { t.Run("empty", func(t *testing.T) { out := &bytes.Buffer{} log := New(out) log.Info().Msg("") if got, want := out.String(), `{"level":"info"}`+"\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } }) t.Run("one-field", func(t *testing.T) { out := &bytes.Buffer{} log := New(out) log.Info().Str("foo", "bar").Msg("") if got, want := out.String(), `{"level":"info","foo":"bar"}`+"\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } }) t.Run("two-field", func(t *testing.T) { out := &bytes.Buffer{} log := New(out) log.Info(). Str("foo", "bar"). Int("n", 123). Msg("") if got, want := out.String(), `{"level":"info","foo":"bar","n":123}`+"\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } }) } func TestWith(t *testing.T) { out := &bytes.Buffer{} log := New(out).With(). Str("foo", "bar"). Err(errors.New("some error")). Bool("bool", true). Int("int", 1). Int8("int8", 2). Int16("int16", 3). Int32("int32", 4). Int64("int64", 5). Uint("uint", 6). Uint8("uint8", 7). Uint16("uint16", 8). Uint32("uint32", 9). Uint64("uint64", 10). Float32("float32", 11). Float64("float64", 12). Time("time", time.Time{}). Logger() log.Log().Msg("") if got, want := out.String(), `{"foo":"bar","error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"time":"0001-01-01T00:00:00Z"}`+"\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } } func TestFields(t *testing.T) { out := &bytes.Buffer{} log := New(out) log.Log(). Str("foo", "bar"). Err(errors.New("some error")). Bool("bool", true). Int("int", 1). Int8("int8", 2). Int16("int16", 3). Int32("int32", 4). Int64("int64", 5). Uint("uint", 6). Uint8("uint8", 7). Uint16("uint16", 8). Uint32("uint32", 9). Uint64("uint64", 10). Float32("float32", 11). Float64("float64", 12). Time("time", time.Time{}). Msg("") if got, want := out.String(), `{"foo":"bar","error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"time":"0001-01-01T00:00:00Z"}`+"\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } } func TestFieldsDisabled(t *testing.T) { out := &bytes.Buffer{} log := New(out).Level(InfoLevel) log.Debug(). Str("foo", "bar"). Err(errors.New("some error")). Bool("bool", true). Int("int", 1). Int8("int8", 2). Int16("int16", 3). Int32("int32", 4). Int64("int64", 5). Uint("uint", 6). Uint8("uint8", 7). Uint16("uint16", 8). Uint32("uint32", 9). Uint64("uint64", 10). Float32("float32", 11). Float64("float64", 12). Time("time", time.Time{}). Msg("") if got, want := out.String(), ""; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } } func TestWithAndFieldsCombined(t *testing.T) { out := &bytes.Buffer{} log := New(out).With().Str("f1", "val").Str("f2", "val").Logger() log.Log().Str("f3", "val").Msg("") if got, want := out.String(), `{"f1":"val","f2":"val","f3":"val"}`+"\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } } func TestLevel(t *testing.T) { t.Run("Disabled", func(t *testing.T) { out := &bytes.Buffer{} log := New(out).Level(Disabled) log.Info().Msg("test") if got, want := out.String(), ""; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } }) t.Run("Info", func(t *testing.T) { out := &bytes.Buffer{} log := New(out).Level(InfoLevel) log.Info().Msg("test") if got, want := out.String(), `{"level":"info","message":"test"}`+"\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } }) } func TestSampling(t *testing.T) { out := &bytes.Buffer{} log := New(out).Sample(2) log.Log().Int("i", 1).Msg("") log.Log().Int("i", 2).Msg("") log.Log().Int("i", 3).Msg("") log.Log().Int("i", 4).Msg("") if got, want := out.String(), "{\"sample\":2,\"i\":2}\n{\"sample\":2,\"i\":4}\n"; got != want { t.Errorf("invalid log output: got %q, want %q", got, want) } } type levelWriter struct { ops []struct { l Level p string } } func (lw *levelWriter) Write(p []byte) (int, error) { return len(p), nil } func (lw *levelWriter) WriteLevel(lvl Level, p []byte) (int, error) { lw.ops = append(lw.ops, struct { l Level p string }{lvl, string(p)}) return len(p), nil } func TestLevelWriter(t *testing.T) { lw := &levelWriter{ ops: []struct { l Level p string }{}, } log := New(lw) log.Debug().Msg("1") log.Info().Msg("2") log.Warn().Msg("3") log.Error().Msg("4") want := []struct { l Level p string }{ {DebugLevel, `{"level":"debug","message":"1"}` + "\n"}, {InfoLevel, `{"level":"info","message":"2"}` + "\n"}, {WarnLevel, `{"level":"warning","message":"3"}` + "\n"}, {ErrorLevel, `{"level":"error","message":"4"}` + "\n"}, } if got := lw.ops; !reflect.DeepEqual(got, want) { t.Errorf("invalid ops:\ngot:\n%v\nwant:\n%v", got, want) } }