diff --git a/internal/humanfmt/humanfmt.go b/internal/humanfmt/humanfmt.go index 212f0d9..b193c02 100644 --- a/internal/humanfmt/humanfmt.go +++ b/internal/humanfmt/humanfmt.go @@ -11,6 +11,7 @@ import ( "path/filepath" "strconv" "strings" + "time" "github.com/fatih/color" "go.opencensus.io/trace" @@ -20,6 +21,15 @@ import ( "cdr.dev/slog" ) +// StripTimestamp strips the timestamp from entry and returns +// it and the rest of the entry. +func StripTimestamp(ent string) (time.Time, string, error) { + ts := ent[:len(TimeFormat)] + rest := ent[len(TimeFormat):] + et, err := time.Parse(TimeFormat, ts) + return et, rest, err +} + // TimeFormat is a simplified RFC3339 format. const TimeFormat = "2006-01-02 15:04:05.000" diff --git a/map_test.go b/map_test.go index f6aec75..d8241c7 100644 --- a/map_test.go +++ b/map_test.go @@ -153,6 +153,24 @@ func TestMap(t *testing.T) { "error": {} }`) }) + + t.Run("value", func(t *testing.T) { + t.Parallel() + + test(t, slog.M( + slog.F("error", meow{1}), + ), `{ + "error": "xdxd" + }`) + }) +} + +type meow struct { + a int +} + +func (m meow) LogValue() interface{} { + return "xdxd" } func indentJSON(t *testing.T, j string) string { diff --git a/s_test.go b/s_test.go new file mode 100644 index 0000000..888d48f --- /dev/null +++ b/s_test.go @@ -0,0 +1,27 @@ +package slog_test + +import ( + "bytes" + "testing" + + "cdr.dev/slog" + "cdr.dev/slog/internal/assert" + "cdr.dev/slog/internal/humanfmt" + "cdr.dev/slog/sloggers/sloghuman" +) + +func TestStdlib(t *testing.T) { + t.Parallel() + + b := &bytes.Buffer{} + l := sloghuman.Make(b).With( + slog.F("hi", "we"), + ) + stdlibLog := slog.Stdlib(bg, l) + stdlibLog.Println("stdlib") + + et, rest, err := humanfmt.StripTimestamp(b.String()) + assert.Success(t, err, "strip timestamp") + assert.False(t, et.IsZero(), "timestamp") + assert.Equal(t, " [INFO]\t(stdlib)\t\tstdlib\t{\"hi\": \"we\"}\n", rest, "entry") +} diff --git a/sloggers/sloghuman/sloghuman_test.go b/sloggers/sloghuman/sloghuman_test.go index 9cee832..0ce49e4 100644 --- a/sloggers/sloghuman/sloghuman_test.go +++ b/sloggers/sloghuman/sloghuman_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "testing" - "time" "cdr.dev/slog" "cdr.dev/slog/internal/assert" @@ -22,12 +21,8 @@ func TestMake(t *testing.T) { l.Info(bg, "line1\n\nline2", slog.F("wowow", "me\nyou")) l.Sync() - s := b.String() - ts := s[:len(humanfmt.TimeFormat)] - rest := s[len(humanfmt.TimeFormat):] - - et, err := time.Parse(humanfmt.TimeFormat, ts) - assert.Success(t, err, "time.Parse") + et, rest, err := humanfmt.StripTimestamp(b.String()) + assert.Success(t, err, "strip timestamp") assert.False(t, et.IsZero(), "timestamp") - assert.Equal(t, " [INFO]\t\t...\t{\"wowow\": \"me\\nyou\"}\n \"msg\": line1\n\n line2\n", rest, "entry") + assert.Equal(t, " [INFO]\t\t...\t{\"wowow\": \"me\\nyou\"}\n \"msg\": line1\n\n line2\n", rest, "entry") } diff --git a/sloggers/slogjson/slogjson_test.go b/sloggers/slogjson/slogjson_test.go index 17696ae..ef1d97e 100644 --- a/sloggers/slogjson/slogjson_test.go +++ b/sloggers/slogjson/slogjson_test.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "regexp" + "runtime" "testing" "go.opencensus.io/trace" @@ -14,6 +15,8 @@ import ( "cdr.dev/slog/sloggers/slogjson" ) +var _, slogjsonTestFile, _, _ = runtime.Caller(0) + var bg = context.Background() func TestMake(t *testing.T) { @@ -26,7 +29,7 @@ func TestMake(t *testing.T) { l.Error(ctx, "line1\n\nline2", slog.F("wowow", "me\nyou")) j := filterJSONTimestamp(b.String()) - exp := fmt.Sprintf(`{"level":"ERROR","component":"","msg":"line1\n\nline2","caller":"/Users/nhooyr/src/cdr/slog/sloggers/slogjson/slogjson_test.go:26","func":"cdr.dev/slog/sloggers/slogjson_test.TestMake","trace":"%v","span":"%v","fields":{"wowow":"me\nyou"}} + exp := fmt.Sprintf(`{"level":"ERROR","component":"","msg":"line1\n\nline2","caller":"`+slogjsonTestFile+`:29","func":"cdr.dev/slog/sloggers/slogjson_test.TestMake","trace":"%v","span":"%v","fields":{"wowow":"me\nyou"}} `, s.SpanContext().TraceID, s.SpanContext().SpanID) assert.Equal(t, exp, j, "entry") } diff --git a/sloggers/slogtest/t_test.go b/sloggers/slogtest/t_test.go index ee96164..2b624e4 100644 --- a/sloggers/slogtest/t_test.go +++ b/sloggers/slogtest/t_test.go @@ -2,46 +2,67 @@ package slogtest_test import ( "context" - "io" "testing" - "golang.org/x/xerrors" - - "cdr.dev/slog" + "cdr.dev/slog/internal/assert" "cdr.dev/slog/sloggers/slogtest" ) -type meow struct { - a int -} +func TestStateless(t *testing.T) { + t.Parallel() + + tb := &fakeTB{} + slogtest.Debug(tb, "hello") + slogtest.Info(tb, "hello") + + slogtest.Error(tb, "hello") + assert.Equal(t, 1, tb.errors, "errors") -func (m meow) LogValue() interface{} { - return "xdxd" + defer func() { + recover() + assert.Equal(t, 1, tb.fatals, "fatals") + }() + + slogtest.Fatal(tb, "hello") } -func TestExampleTest(t *testing.T) { +func TestIgnoreErrors(t *testing.T) { t.Parallel() - slogtest.Info(t, "my message here", - slog.F("field_name", "something or the other"), - slog.F("some_map", slog.M( - slog.F("nested_fields", "wowow"), - )), - slog.Error(xerrors.Errorf("wrap2: %w", - xerrors.Errorf("wrap1: %w", - io.EOF, - ), - )), - slog.F("hi3", slog.M( - slog.F("meow", meow{1}), - slog.F("meow", meow{2}), - slog.F("meow", meow{3}), - )), - ) - - l := slogtest.Make(t, nil).With( - slog.F("hi", "anmol"), - ) - stdlibLog := slog.Stdlib(context.Background(), l) - stdlibLog.Println("stdlib") + tb := &fakeTB{} + l := slogtest.Make(tb, &slogtest.Options{ + IgnoreErrors: true, + }) + + l.Error(bg, "hello") + assert.Equal(t, 0, tb.errors, "errors") + + defer func() { + recover() + assert.Equal(t, 0, tb.fatals, "fatals") + }() + + l.Fatal(bg, "hello") +} + +var bg = context.Background() + +type fakeTB struct { + testing.TB + + errors int + fatals int +} + +func (tb *fakeTB) Helper() {} + +func (tb *fakeTB) Log(v ...interface{}) {} + +func (tb *fakeTB) Error(v ...interface{}) { + tb.errors++ +} + +func (tb *fakeTB) Fatal(v ...interface{}) { + tb.fatals++ + panic("") }