From a383f398152d4646ba6c4d667f3e65772e04bd7c Mon Sep 17 00:00:00 2001 From: Dominik Menke Date: Thu, 31 Oct 2024 01:23:12 +0100 Subject: [PATCH] add tests for xlog [wip] --- xlog/attrs.go | 4 +- xlog/options.go | 7 +++ xlog/options_test.go | 114 +++++++++++++++++++++++++++++++++++++++++++ xlog/xlog.go | 4 +- 4 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 xlog/options_test.go diff --git a/xlog/attrs.go b/xlog/attrs.go index 481a61e..84ca5a2 100644 --- a/xlog/attrs.go +++ b/xlog/attrs.go @@ -32,7 +32,7 @@ func (err ErrorValue) Value() slog.Value { // LogValue implements [slog.LogValuer]. func (err ErrorValue) LogValue() slog.Value { - return slog.StringValue(err.Error()) + return err.Value() } // Error constructs a first-class error log attribute. @@ -40,5 +40,5 @@ func (err ErrorValue) LogValue() slog.Value { // Not to be confused with (xlog.Logger).Error() or (log/slog).Error(), // which produce an error-level log message. func Error(err error) slog.Attr { - return slog.Any(ErrorKey, ErrorValue{err}) + return Any(ErrorKey, ErrorValue{err}) } diff --git a/xlog/options.go b/xlog/options.go index 25cfe14..b5110c2 100644 --- a/xlog/options.go +++ b/xlog/options.go @@ -1,6 +1,7 @@ package xlog import ( + "errors" "io" "log/slog" "os" @@ -47,9 +48,15 @@ func LeveledString(s string) Option { } } +var ErrNilWriter = errors.New("invalid writer: nil") + // WriteTo sets the output. func WriteTo(w io.Writer) Option { return func(o *options) error { + if w == nil { + return ErrNilWriter + } + o.output = w return nil } diff --git a/xlog/options_test.go b/xlog/options_test.go new file mode 100644 index 0000000..8be9b10 --- /dev/null +++ b/xlog/options_test.go @@ -0,0 +1,114 @@ +package xlog + +import ( + "bytes" + "log/slog" + "testing" + "time" + + "github.com/stretchr/testify/suite" +) + +func TestOptionSuite(t *testing.T) { + suite.Run(t, new(OptionSuite)) +} + +type OptionSuite struct { + suite.Suite + options +} + +func (o *OptionSuite) SetupTest() { + o.level = slog.LevelDebug +} + +func (o *OptionSuite) TestLeveled() { + err := Leveled(slog.LevelError)(&o.options) + o.Require().NoError(err) + o.Assert().Equal(slog.LevelError, o.level) + + err = Leveled(slog.Level(999))(&o.options) + o.Require().NoError(err) + o.Assert().Equal(slog.Level(999), o.level) +} + +func (o *OptionSuite) TestLeveledString_valid() { + for i, tt := range []struct { + input string + expected slog.Level + }{ + {"dbg", slog.LevelDebug}, + {"debug", slog.LevelDebug}, + + {"", slog.LevelInfo}, + {"info", slog.LevelInfo}, + {"INFO", slog.LevelInfo}, + + {"WARN", slog.LevelWarn}, + {"WARNING", slog.LevelWarn}, + + {"ERR", slog.LevelError}, + {"ERROR", slog.LevelError}, + {"FaTaL", slog.LevelError}, + } { + o.level = slog.Level(100 + i) + err := LeveledString(tt.input)(&o.options) + o.Require().NoError(err) + o.Assert().Equal(tt.expected, o.level) + } +} + +func (o *OptionSuite) TestLeveledString_invalid() { + o.level = slog.Level(100) + err := LeveledString("ifno")(&o.options) + o.Require().Equal(slog.Level(100), o.level) + o.Assert().EqualError(err, `unknown log level: "ifno"`) +} + +func (o *OptionSuite) TestWriteTo() { + var buf bytes.Buffer + err := WriteTo(&buf)(&o.options) + o.Require().NoError(err) + o.Assert().Equal(&buf, o.output) + + err = WriteTo(nil)(&o.options) + o.Assert().EqualError(err, "invalid writer: nil") +} + +func (o *OptionSuite) TestMockClock() { + t := time.Now() + err := MockClock(t)(&o.options) + o.Require().NoError(err) + o.Require().NotNil(o.clock) + o.Assert().EqualValues(t, o.clock.Now()) +} + +func (o *OptionSuite) TestWithSource() { + err := WithSource()(&o.options) + o.Require().NoError(err) + o.Assert().True(o.source) +} + +func (o *OptionSuite) TestColor() { + err := Color()(&o.options) + o.Require().NoError(err) + o.Assert().True(o.color) +} + +func (o *OptionSuite) TestAsJSON() { + err := AsJSON()(&o.options) + o.Require().NoError(err) + o.Assert().NotNil(o.buildHandler) +} + +func (o *OptionSuite) TestAsText() { + err := AsText()(&o.options) + o.Require().NoError(err) + o.Assert().NotNil(o.buildHandler) +} + +func (o *OptionSuite) TestDiscard() { + err := Discard()(&o.options) + o.Require().NoError(err) + o.Assert().True(o.discard) +} diff --git a/xlog/xlog.go b/xlog/xlog.go index 8f5cf2a..4986073 100644 --- a/xlog/xlog.go +++ b/xlog/xlog.go @@ -111,13 +111,13 @@ func (log *logger) With(a ...slog.Attr) Logger { // "error" and "fatal". Other input will result in err not being nil. func ParseLevel(s string) (l slog.Level, err error) { switch strings.ToLower(s) { - case "debug": + case "dbg", "debug": l = slog.LevelDebug case "info", "": // make the zero value useful l = slog.LevelInfo case "warn", "warning": l = slog.LevelWarn - case "error", "fatal": + case "err", "error", "fatal": l = slog.LevelError default: err = fmt.Errorf("unknown log level: %q", s)