Skip to content

Commit

Permalink
完善单测
Browse files Browse the repository at this point in the history
  • Loading branch information
FishGoddess committed Nov 29, 2023
1 parent c4baef7 commit f3fa1aa
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 23 deletions.
18 changes: 15 additions & 3 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package logit

import (
"errors"
"io"
"log/slog"
"os"
Expand Down Expand Up @@ -72,7 +73,7 @@ func newDefaultConfig() *config {

func (c *config) handlerOptions() *slog.HandlerOptions {
opts := &slog.HandlerOptions{
Level: c.level,
Level: c.level.Peel(),
AddSource: c.withSource,
ReplaceAttr: c.replaceAttr,
}
Expand All @@ -81,14 +82,25 @@ func (c *config) handlerOptions() *slog.HandlerOptions {
}

func (c *config) handler() (slog.Handler, error) {
if c.newWriter == nil {
return nil, errors.New("logit: newWriter in config is nil")
}

if c.newHandler == nil {
return nil, errors.New("logit: newHandler in config is nil")
}

w, err := c.newWriter()
if err != nil {
return nil, err
}

ww := c.wrapWriter(w)
if c.wrapWriter != nil {
w = c.wrapWriter(w)
}

opts := c.handlerOptions()
handler := c.newHandler(ww, opts)
handler := c.newHandler(w, opts)

return handler, nil
}
59 changes: 57 additions & 2 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,18 @@ package logit

import (
"fmt"
"io"
"log/slog"
"os"
"testing"
)

type testConfigHandler struct {
slog.TextHandler
w io.Writer
opts slog.HandlerOptions
}

// go test -v -cover -run=^TestConfigHandlerOptions$
func TestConfigHandlerOptions(t *testing.T) {
replaceAttr := func(groups []string, attr slog.Attr) slog.Attr { return attr }
Expand All @@ -32,8 +40,8 @@ func TestConfigHandlerOptions(t *testing.T) {

opts := conf.handlerOptions()

if opts.Level != conf.level {
t.Errorf("opts.Level %v != conf.level %v", opts.Level, conf.level)
if opts.Level != conf.level.Peel() {
t.Errorf("opts.Level %v != conf.level %v", opts.Level, conf.level.Peel())
}

if opts.AddSource != conf.withSource {
Expand All @@ -44,3 +52,50 @@ func TestConfigHandlerOptions(t *testing.T) {
t.Errorf("opts.ReplaceAttr %p != conf.replaceAttr %p", opts.ReplaceAttr, conf.replaceAttr)
}
}

// go test -v -cover -run=^TestConfigHandler$
func TestConfigHandler(t *testing.T) {
replaceAttr := func(groups []string, attr slog.Attr) slog.Attr { return attr }

conf := &config{
level: levelWarn,
withSource: true,
replaceAttr: replaceAttr,

newWriter: func() (io.Writer, error) {
return os.Stderr, nil
},
newHandler: func(w io.Writer, opts *slog.HandlerOptions) slog.Handler {
return &testConfigHandler{
w: w,
opts: *opts,
}
},
}

handler, err := conf.handler()
if err != nil {
t.Error(err)
}

tcHandler, ok := handler.(*testConfigHandler)
if !ok {
t.Errorf("handler type %T is wrong", handler)
}

if tcHandler.w != os.Stderr {
t.Errorf("tcHandler.w %p != os.Stderr %p", tcHandler.w, os.Stderr)
}

if tcHandler.opts.Level != conf.level.Peel() {
t.Errorf("tcHandler.opts.Level %v != conf.level %v", tcHandler.opts.Level, conf.level.Peel())
}

if tcHandler.opts.AddSource != conf.withSource {
t.Errorf("tcHandler.opts.AddSource %v != conf.withSource %v", tcHandler.opts.AddSource, conf.withSource)
}

if fmt.Sprintf("%p", tcHandler.opts.ReplaceAttr) != fmt.Sprintf("%p", conf.replaceAttr) {
t.Errorf("tcHandler.opts.ReplaceAttr %p != conf.replaceAttr %p", tcHandler.opts.ReplaceAttr, conf.replaceAttr)
}
}
5 changes: 2 additions & 3 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ import (
"context"
)

// contextKey is the type of context key.
type contextKey struct{}

// NewContextWithKey wraps context with logger of key and returns a new context.
func NewContextWithKey(ctx context.Context, key interface{}, logger *Logger) context.Context {
return context.WithValue(ctx, key, logger)
}

// FromContextWithKey gets logger from context with key and returns a discard logger if missing.
// FromContextWithKey gets logger from context of key and returns the default logger if missed.
func FromContextWithKey(ctx context.Context, key interface{}) *Logger {
if logger, ok := ctx.Value(key).(*Logger); ok {
return logger
Expand All @@ -41,7 +40,7 @@ func NewContext(ctx context.Context, logger *Logger) context.Context {
return NewContextWithKey(ctx, contextKey{}, logger)
}

// FromContext gets logger from context and returns a discard logger if missing.
// FromContext gets logger from context and returns the default logger if missed.
func FromContext(ctx context.Context) *Logger {
return FromContextWithKey(ctx, contextKey{})
}
12 changes: 6 additions & 6 deletions context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ func TestNewContextWithKey(t *testing.T) {

value := ctx.Value(key)
if value == nil {
t.Error("ctx.Value returns nil")
t.Error("value == nil")
}

contextLogger, ok := value.(*Logger)
if !ok {
t.Errorf("value %T isn't *Logger", value)
t.Errorf("value type %T is wrong", value)
}

if contextLogger != logger {
Expand All @@ -48,7 +48,7 @@ func TestFromContextWithKey(t *testing.T) {
logger := FromContextWithKey(ctx, key)

if logger == nil {
t.Error("logger shouldn't be nil")
t.Error("logger == nil")
}

logger = New()
Expand All @@ -66,12 +66,12 @@ func TestNewContext(t *testing.T) {

value := ctx.Value(contextKey{})
if value == nil {
t.Error("ctx.Value returns nil")
t.Error("value == nil")
}

contextLogger, ok := value.(*Logger)
if !ok {
t.Errorf("value %T isn't *Logger", value)
t.Errorf("value type %T is wrong", value)
}

if contextLogger != logger {
Expand All @@ -85,7 +85,7 @@ func TestFromContext(t *testing.T) {
logger := FromContext(ctx)

if logger == nil {
t.Error("logger shouldn't be nil")
t.Error("logger == nil")
}

logger = New()
Expand Down
58 changes: 52 additions & 6 deletions level.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,62 @@
package logit

import (
"fmt"
"log/slog"
"strings"
)

const (
levelDebug Level = slog.LevelDebug
levelInfo Level = slog.LevelInfo
levelWarn Level = slog.LevelWarn
levelError Level = slog.LevelError
levelDebug = Level(slog.LevelDebug)
levelInfo = Level(slog.LevelInfo)
levelWarn = Level(slog.LevelWarn)
levelError = Level(slog.LevelError)

// levelPrint is for some logging methods which are compatible with log package in Go.
levelPrint Level = levelError + 1
levelOff Level = levelError + 2

// levelOff is for disabling logging.
levelOff Level = levelError + 2
)

type Level = slog.Level
var (
levels = map[Level]string{
levelDebug: "debug",
levelInfo: "info",
levelWarn: "warn",
levelError: "error",
levelPrint: "print",
levelOff: "off",
}
)

// Level is an alias to slog.Level.
// We extends level in order to fit our logging methods.
type Level slog.Level

// Peel returns the level in slog.Level form.
func (l Level) Peel() slog.Level {
return slog.Level(l)
}

// String returns the string form of level.
func (l Level) String() string {
if name, ok := levels[l]; ok {
return name
}

return "unknown"
}

// ParseLevel parses str to level and returns an error if failed.
func ParseLevel(str string) (Level, error) {
str = strings.ToLower(str)

for level, name := range levels {
if str == name {
return level, nil
}
}

return 0, fmt.Errorf("logit: unknown level %s", str)
}
88 changes: 88 additions & 0 deletions level_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,91 @@
// limitations under the License.

package logit

import (
"log/slog"
"reflect"
"testing"
)

// go test -v -cover -run=^TestLevelPeel$
func TestLevelPeel(t *testing.T) {
tests := []struct {
name string
level Level
want slog.Level
}{
{name: "debug", level: levelDebug, want: slog.LevelDebug},
{name: "info", level: levelInfo, want: slog.LevelInfo},
{name: "warn", level: levelWarn, want: slog.LevelWarn},
{name: "error", level: levelError, want: slog.LevelError},
{name: "print", level: levelPrint, want: slog.Level(levelPrint)},
{name: "off", level: levelOff, want: slog.Level(levelOff)},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.level.Peel(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Level.Peel() = %v, want %v", got, tt.want)
}
})
}
}

// go test -v -cover -run=^TestLevelString$
func TestLevelString(t *testing.T) {
tests := []struct {
name string
level Level
want string
}{
{name: "debug", level: levelDebug, want: "debug"},
{name: "info", level: levelInfo, want: "info"},
{name: "warn", level: levelWarn, want: "warn"},
{name: "error", level: levelError, want: "error"},
{name: "print", level: levelPrint, want: "print"},
{name: "off", level: levelOff, want: "off"},
{name: "unknown", level: 1997, want: "unknown"},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.level.String(); got != tt.want {
t.Errorf("Level.String() = %v, want %v", got, tt.want)
}
})
}
}

// go test -v -cover -run=^TestParseLevel$
func TestParseLevel(t *testing.T) {
tests := []struct {
name string
str string
want Level
wantErr bool
}{
{name: "debug", str: "debug", want: levelDebug, wantErr: false},
{name: "info", str: "info", want: levelInfo, wantErr: false},
{name: "warn", str: "warn", want: levelWarn, wantErr: false},
{name: "error", str: "error", want: levelError, wantErr: false},
{name: "print", str: "print", want: levelPrint, wantErr: false},
{name: "off", str: "off", want: levelOff, wantErr: false},
{name: "unknown", str: "unknown", want: 0, wantErr: true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseLevel(tt.str)

if (err != nil) != tt.wantErr {
t.Errorf("ParseLevel() error = %v, wantErr %v", err, tt.wantErr)
return
}

if got != tt.want {
t.Errorf("ParseLevel() = %v, want %v", got, tt.want)
}
})
}
}
8 changes: 5 additions & 3 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,10 @@ func (l *Logger) newRecord(level slog.Level, msg string, args []any) slog.Record
return record
}

func (l *Logger) log(ctx context.Context, level slog.Level, msg string, args ...any) {
if !l.Enabled(ctx, level) {
func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) {
slogLevel := level.Peel()

if !l.Enabled(ctx, slogLevel) {
return
}

Expand All @@ -205,7 +207,7 @@ func (l *Logger) log(ctx context.Context, level slog.Level, msg string, args ...
}

// TODO 尝试用对象池优化
record := l.newRecord(level, msg, args)
record := l.newRecord(slogLevel, msg, args)

if err := l.handler.Handle(ctx, record); err != nil {
defaults.HandleError("Logger.handler.Handle", err)
Expand Down

0 comments on commit f3fa1aa

Please sign in to comment.