319 lines
9.8 KiB
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())
|
|
}
|
|
}
|