go_study/fabric-main/common/flogging/fabenc/formatter_test.go

319 lines
9.8 KiB
Go

/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package fabenc_test
import (
"bytes"
"fmt"
"runtime"
"strconv"
"sync"
"testing"
"time"
"github.com/hyperledger/fabric/common/flogging/fabenc"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func TestParseFormat(t *testing.T) {
tests := []struct {
desc string
spec string
formatters []fabenc.Formatter
}{
{
desc: "empty spec",
spec: "",
formatters: []fabenc.Formatter{},
},
{
desc: "simple verb",
spec: "%{color}",
formatters: []fabenc.Formatter{
fabenc.ColorFormatter{},
},
},
{
desc: "with prefix",
spec: "prefix %{color}",
formatters: []fabenc.Formatter{
fabenc.StringFormatter{Value: "prefix "},
fabenc.ColorFormatter{},
},
},
{
desc: "with suffix",
spec: "%{color} suffix",
formatters: []fabenc.Formatter{
fabenc.ColorFormatter{},
fabenc.StringFormatter{Value: " suffix"},
},
},
{
desc: "with prefix and suffix",
spec: "prefix %{color} suffix",
formatters: []fabenc.Formatter{
fabenc.StringFormatter{Value: "prefix "},
fabenc.ColorFormatter{},
fabenc.StringFormatter{Value: " suffix"},
},
},
{
desc: "with format",
spec: "%{level:.4s} suffix",
formatters: []fabenc.Formatter{
fabenc.LevelFormatter{FormatVerb: "%.4s"},
fabenc.StringFormatter{Value: " suffix"},
},
},
}
for _, tc := range tests {
t.Run(fmt.Sprintf(tc.desc), func(t *testing.T) {
formatters, err := fabenc.ParseFormat(tc.spec)
require.NoError(t, err)
require.Equal(t, tc.formatters, formatters)
})
}
}
func TestParseFormatError(t *testing.T) {
_, err := fabenc.ParseFormat("%{color:bad}")
require.EqualError(t, err, "invalid color option: bad")
}
func TestNewFormatter(t *testing.T) {
tests := []struct {
verb string
format string
formatter fabenc.Formatter
errorMsg string
}{
{verb: "color", format: "", formatter: fabenc.ColorFormatter{}},
{verb: "color", format: "bold", formatter: fabenc.ColorFormatter{Bold: true}},
{verb: "color", format: "reset", formatter: fabenc.ColorFormatter{Reset: true}},
{verb: "color", format: "unknown", errorMsg: "invalid color option: unknown"},
{verb: "id", format: "", formatter: fabenc.SequenceFormatter{FormatVerb: "%d"}},
{verb: "id", format: "04x", formatter: fabenc.SequenceFormatter{FormatVerb: "%04x"}},
{verb: "level", format: "", formatter: fabenc.LevelFormatter{FormatVerb: "%s"}},
{verb: "level", format: ".4s", formatter: fabenc.LevelFormatter{FormatVerb: "%.4s"}},
{verb: "message", format: "", formatter: fabenc.MessageFormatter{FormatVerb: "%s"}},
{verb: "message", format: "#30s", formatter: fabenc.MessageFormatter{FormatVerb: "%#30s"}},
{verb: "module", format: "", formatter: fabenc.ModuleFormatter{FormatVerb: "%s"}},
{verb: "module", format: "ok", formatter: fabenc.ModuleFormatter{FormatVerb: "%ok"}},
{verb: "shortfunc", format: "", formatter: fabenc.ShortFuncFormatter{FormatVerb: "%s"}},
{verb: "shortfunc", format: "U", formatter: fabenc.ShortFuncFormatter{FormatVerb: "%U"}},
{verb: "time", format: "", formatter: fabenc.TimeFormatter{Layout: "2006-01-02T15:04:05.999Z07:00"}},
{verb: "time", format: "04:05.999999Z05:00", formatter: fabenc.TimeFormatter{Layout: "04:05.999999Z05:00"}},
{verb: "unknown", format: "", errorMsg: "unknown verb: unknown"},
}
for i, tc := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
f, err := fabenc.NewFormatter(tc.verb, tc.format)
if tc.errorMsg == "" {
require.NoError(t, err)
require.Equal(t, tc.formatter, f)
} else {
require.EqualError(t, err, tc.errorMsg)
}
})
}
}
func TestColorFormatter(t *testing.T) {
tests := []struct {
f fabenc.ColorFormatter
level zapcore.Level
formatted string
}{
{f: fabenc.ColorFormatter{Reset: true}, level: zapcore.DebugLevel, formatted: fabenc.ResetColor()},
{f: fabenc.ColorFormatter{}, level: zapcore.DebugLevel, formatted: fabenc.ColorCyan.Normal()},
{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.DebugLevel, formatted: fabenc.ColorCyan.Bold()},
{f: fabenc.ColorFormatter{}, level: zapcore.InfoLevel, formatted: fabenc.ColorBlue.Normal()},
{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.InfoLevel, formatted: fabenc.ColorBlue.Bold()},
{f: fabenc.ColorFormatter{}, level: zapcore.WarnLevel, formatted: fabenc.ColorYellow.Normal()},
{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.WarnLevel, formatted: fabenc.ColorYellow.Bold()},
{f: fabenc.ColorFormatter{}, level: zapcore.ErrorLevel, formatted: fabenc.ColorRed.Normal()},
{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.ErrorLevel, formatted: fabenc.ColorRed.Bold()},
{f: fabenc.ColorFormatter{}, level: zapcore.DPanicLevel, formatted: fabenc.ColorMagenta.Normal()},
{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.DPanicLevel, formatted: fabenc.ColorMagenta.Bold()},
{f: fabenc.ColorFormatter{}, level: zapcore.PanicLevel, formatted: fabenc.ColorMagenta.Normal()},
{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.PanicLevel, formatted: fabenc.ColorMagenta.Bold()},
{f: fabenc.ColorFormatter{}, level: zapcore.FatalLevel, formatted: fabenc.ColorMagenta.Normal()},
{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.FatalLevel, formatted: fabenc.ColorMagenta.Bold()},
{f: fabenc.ColorFormatter{}, level: zapcore.Level(99), formatted: fabenc.ColorNone.Normal()},
{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.Level(99), formatted: fabenc.ColorNone.Normal()},
}
for i, tc := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
buf := &bytes.Buffer{}
entry := zapcore.Entry{Level: tc.level}
tc.f.Format(buf, entry, nil)
require.Equal(t, tc.formatted, buf.String())
})
}
}
func TestLevelFormatter(t *testing.T) {
tests := []struct {
level zapcore.Level
formatted string
}{
{level: zapcore.DebugLevel, formatted: "DEBUG"},
{level: zapcore.InfoLevel, formatted: "INFO"},
{level: zapcore.WarnLevel, formatted: "WARN"},
{level: zapcore.ErrorLevel, formatted: "ERROR"},
{level: zapcore.DPanicLevel, formatted: "DPANIC"},
{level: zapcore.PanicLevel, formatted: "PANIC"},
{level: zapcore.FatalLevel, formatted: "FATAL"},
{level: zapcore.Level(99), formatted: "LEVEL(99)"},
}
for i, tc := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
buf := &bytes.Buffer{}
entry := zapcore.Entry{Level: tc.level}
fabenc.LevelFormatter{FormatVerb: "%s"}.Format(buf, entry, nil)
require.Equal(t, tc.formatted, buf.String())
})
}
}
func TestMessageFormatter(t *testing.T) {
buf := &bytes.Buffer{}
entry := zapcore.Entry{Message: "some message text \n\n"}
f := fabenc.MessageFormatter{FormatVerb: "%s"}
f.Format(buf, entry, nil)
require.Equal(t, "some message text ", buf.String())
}
func TestModuleFormatter(t *testing.T) {
buf := &bytes.Buffer{}
entry := zapcore.Entry{LoggerName: "logger/name"}
f := fabenc.ModuleFormatter{FormatVerb: "%s"}
f.Format(buf, entry, nil)
require.Equal(t, "logger/name", buf.String())
}
func TestSequenceFormatter(t *testing.T) {
mutex := &sync.Mutex{}
results := map[string]struct{}{}
ready := &sync.WaitGroup{}
ready.Add(100)
finished := &sync.WaitGroup{}
finished.Add(100)
fabenc.SetSequence(0)
for i := 1; i <= 100; i++ {
go func(i int) {
buf := &bytes.Buffer{}
entry := zapcore.Entry{Level: zapcore.DebugLevel}
f := fabenc.SequenceFormatter{FormatVerb: "%d"}
ready.Done() // setup complete
ready.Wait() // wait for all go routines to be ready
f.Format(buf, entry, nil) // format concurrently
mutex.Lock()
results[buf.String()] = struct{}{}
mutex.Unlock()
finished.Done()
}(i)
}
finished.Wait()
for i := 1; i <= 100; i++ {
require.Contains(t, results, strconv.Itoa(i))
}
}
func TestShortFuncFormatter(t *testing.T) {
callerpc, _, _, ok := runtime.Caller(0)
require.True(t, ok)
buf := &bytes.Buffer{}
entry := zapcore.Entry{Caller: zapcore.EntryCaller{PC: callerpc}}
fabenc.ShortFuncFormatter{FormatVerb: "%s"}.Format(buf, entry, nil)
require.Equal(t, "TestShortFuncFormatter", buf.String())
buf = &bytes.Buffer{}
entry = zapcore.Entry{Caller: zapcore.EntryCaller{PC: 0}}
fabenc.ShortFuncFormatter{FormatVerb: "%s"}.Format(buf, entry, nil)
require.Equal(t, "(unknown)", buf.String())
}
func TestTimeFormatter(t *testing.T) {
buf := &bytes.Buffer{}
entry := zapcore.Entry{Time: time.Date(1975, time.August, 15, 12, 0, 0, 333, time.UTC)}
f := fabenc.TimeFormatter{Layout: time.RFC3339Nano}
f.Format(buf, entry, nil)
require.Equal(t, "1975-08-15T12:00:00.000000333Z", buf.String())
}
func TestMultiFormatter(t *testing.T) {
entry := zapcore.Entry{
Message: "message",
Level: zapcore.InfoLevel,
}
fields := []zapcore.Field{
zap.String("name", "value"),
}
tests := []struct {
desc string
initial []fabenc.Formatter
update []fabenc.Formatter
expected string
}{
{
desc: "no formatters",
initial: nil,
update: nil,
expected: "",
},
{
desc: "initial formatters",
initial: []fabenc.Formatter{fabenc.StringFormatter{Value: "string1"}},
update: nil,
expected: "string1",
},
{
desc: "set to formatters",
initial: []fabenc.Formatter{fabenc.StringFormatter{Value: "string1"}},
update: []fabenc.Formatter{
fabenc.StringFormatter{Value: "string1"},
fabenc.StringFormatter{Value: "-"},
fabenc.StringFormatter{Value: "string2"},
},
expected: "string1-string2",
},
{
desc: "set to empty",
initial: []fabenc.Formatter{fabenc.StringFormatter{Value: "string1"}},
update: []fabenc.Formatter{},
expected: "",
},
}
for _, tc := range tests {
mf := fabenc.NewMultiFormatter(tc.initial...)
if tc.update != nil {
mf.SetFormatters(tc.update)
}
buf := &bytes.Buffer{}
mf.Format(buf, entry, fields)
require.Equal(t, tc.expected, buf.String())
}
}