254 lines
6.1 KiB
Go
254 lines
6.1 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package flogging_test
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/hyperledger/fabric/common/flogging"
|
|
"github.com/hyperledger/fabric/common/flogging/mock"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/buffer"
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
func TestCoreWith(t *testing.T) {
|
|
core := &flogging.Core{
|
|
Encoders: map[flogging.Encoding]zapcore.Encoder{},
|
|
Observer: &mock.Observer{},
|
|
}
|
|
clone := core.With([]zapcore.Field{zap.String("key", "value")})
|
|
require.Equal(t, core, clone)
|
|
|
|
jsonEncoder := zapcore.NewJSONEncoder(zapcore.EncoderConfig{})
|
|
consoleEncoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{})
|
|
core = &flogging.Core{
|
|
Encoders: map[flogging.Encoding]zapcore.Encoder{
|
|
flogging.JSON: jsonEncoder,
|
|
flogging.CONSOLE: consoleEncoder,
|
|
},
|
|
}
|
|
decorated := core.With([]zapcore.Field{zap.String("key", "value")})
|
|
|
|
// verify the objects differ
|
|
require.NotEqual(t, core, decorated)
|
|
|
|
// verify the objects only differ by the encoded fields
|
|
jsonEncoder.AddString("key", "value")
|
|
consoleEncoder.AddString("key", "value")
|
|
require.Equal(t, core, decorated)
|
|
}
|
|
|
|
func TestCoreCheck(t *testing.T) {
|
|
var enabledArgs []zapcore.Level
|
|
levels := &flogging.LoggerLevels{}
|
|
err := levels.ActivateSpec("warning")
|
|
require.NoError(t, err)
|
|
core := &flogging.Core{
|
|
LevelEnabler: zap.LevelEnablerFunc(func(l zapcore.Level) bool {
|
|
enabledArgs = append(enabledArgs, l)
|
|
return l >= zapcore.WarnLevel
|
|
}),
|
|
Levels: levels,
|
|
}
|
|
|
|
// not enabled
|
|
ce := core.Check(zapcore.Entry{Level: zapcore.DebugLevel}, nil)
|
|
require.Nil(t, ce)
|
|
ce = core.Check(zapcore.Entry{Level: zapcore.InfoLevel}, nil)
|
|
require.Nil(t, ce)
|
|
|
|
// enabled
|
|
ce = core.Check(zapcore.Entry{Level: zapcore.WarnLevel}, nil)
|
|
require.NotNil(t, ce)
|
|
|
|
require.Equal(t, enabledArgs, []zapcore.Level{zapcore.DebugLevel, zapcore.InfoLevel, zapcore.WarnLevel})
|
|
}
|
|
|
|
type sw struct {
|
|
bytes.Buffer
|
|
writeErr error
|
|
syncCalled bool
|
|
syncErr error
|
|
}
|
|
|
|
func (s *sw) Sync() error {
|
|
s.syncCalled = true
|
|
return s.syncErr
|
|
}
|
|
|
|
func (s *sw) Write(b []byte) (int, error) {
|
|
if s.writeErr != nil {
|
|
return 0, s.writeErr
|
|
}
|
|
return s.Buffer.Write(b)
|
|
}
|
|
|
|
func (s *sw) Encoding() flogging.Encoding {
|
|
return flogging.CONSOLE
|
|
}
|
|
|
|
func TestCoreWrite(t *testing.T) {
|
|
encoderConfig := zap.NewDevelopmentEncoderConfig()
|
|
encoderConfig.EncodeTime = nil
|
|
|
|
output := &sw{}
|
|
core := &flogging.Core{
|
|
Encoders: map[flogging.Encoding]zapcore.Encoder{
|
|
flogging.CONSOLE: zapcore.NewConsoleEncoder(encoderConfig),
|
|
},
|
|
Selector: output,
|
|
Output: output,
|
|
}
|
|
|
|
entry := zapcore.Entry{
|
|
Level: zapcore.InfoLevel,
|
|
Message: "this is a message",
|
|
}
|
|
err := core.Write(entry, nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "INFO\tthis is a message\n", output.String())
|
|
|
|
output.writeErr = errors.New("super-loose")
|
|
err = core.Write(entry, nil)
|
|
require.EqualError(t, err, "super-loose")
|
|
}
|
|
|
|
func TestCoreWriteSync(t *testing.T) {
|
|
encoderConfig := zap.NewDevelopmentEncoderConfig()
|
|
encoderConfig.EncodeTime = nil
|
|
|
|
output := &sw{}
|
|
core := &flogging.Core{
|
|
Encoders: map[flogging.Encoding]zapcore.Encoder{
|
|
flogging.CONSOLE: zapcore.NewConsoleEncoder(encoderConfig),
|
|
},
|
|
Selector: output,
|
|
Output: output,
|
|
}
|
|
|
|
entry := zapcore.Entry{
|
|
Level: zapcore.DebugLevel,
|
|
Message: "no bugs for me",
|
|
}
|
|
err := core.Write(entry, nil)
|
|
require.NoError(t, err)
|
|
require.False(t, output.syncCalled)
|
|
|
|
entry = zapcore.Entry{
|
|
Level: zapcore.PanicLevel,
|
|
Message: "gah!",
|
|
}
|
|
err = core.Write(entry, nil)
|
|
require.NoError(t, err)
|
|
require.True(t, output.syncCalled)
|
|
}
|
|
|
|
type brokenEncoder struct{ zapcore.Encoder }
|
|
|
|
func (b *brokenEncoder) EncodeEntry(zapcore.Entry, []zapcore.Field) (*buffer.Buffer, error) {
|
|
return nil, errors.New("broken encoder")
|
|
}
|
|
|
|
func TestCoreWriteEncodeFail(t *testing.T) {
|
|
output := &sw{}
|
|
core := &flogging.Core{
|
|
Encoders: map[flogging.Encoding]zapcore.Encoder{
|
|
flogging.CONSOLE: &brokenEncoder{},
|
|
},
|
|
Selector: output,
|
|
Output: output,
|
|
}
|
|
|
|
entry := zapcore.Entry{
|
|
Level: zapcore.DebugLevel,
|
|
Message: "no bugs for me",
|
|
}
|
|
err := core.Write(entry, nil)
|
|
require.EqualError(t, err, "broken encoder")
|
|
}
|
|
|
|
func TestCoreSync(t *testing.T) {
|
|
syncWriter := &sw{}
|
|
core := &flogging.Core{
|
|
Output: syncWriter,
|
|
}
|
|
|
|
err := core.Sync()
|
|
require.NoError(t, err)
|
|
require.True(t, syncWriter.syncCalled)
|
|
|
|
syncWriter.syncErr = errors.New("bummer")
|
|
err = core.Sync()
|
|
require.EqualError(t, err, "bummer")
|
|
}
|
|
|
|
func TestObserverCheck(t *testing.T) {
|
|
observer := &mock.Observer{}
|
|
entry := zapcore.Entry{
|
|
Level: zapcore.DebugLevel,
|
|
Message: "message",
|
|
}
|
|
checkedEntry := &zapcore.CheckedEntry{}
|
|
|
|
levels := &flogging.LoggerLevels{}
|
|
err := levels.ActivateSpec("debug")
|
|
require.NoError(t, err)
|
|
core := &flogging.Core{
|
|
LevelEnabler: zap.LevelEnablerFunc(func(l zapcore.Level) bool { return true }),
|
|
Levels: levels,
|
|
Observer: observer,
|
|
}
|
|
|
|
ce := core.Check(entry, checkedEntry)
|
|
require.Exactly(t, ce, checkedEntry)
|
|
|
|
require.Equal(t, 1, observer.CheckCallCount())
|
|
observedEntry, observedCE := observer.CheckArgsForCall(0)
|
|
require.Equal(t, entry, observedEntry)
|
|
require.Equal(t, ce, observedCE)
|
|
}
|
|
|
|
func TestObserverWriteEntry(t *testing.T) {
|
|
observer := &mock.Observer{}
|
|
entry := zapcore.Entry{
|
|
Level: zapcore.DebugLevel,
|
|
Message: "message",
|
|
}
|
|
fields := []zapcore.Field{
|
|
{Key: "key1", Type: zapcore.SkipType},
|
|
{Key: "key2", Type: zapcore.SkipType},
|
|
}
|
|
|
|
levels := &flogging.LoggerLevels{}
|
|
err := levels.ActivateSpec("debug")
|
|
require.NoError(t, err)
|
|
selector := &sw{}
|
|
output := &sw{}
|
|
core := &flogging.Core{
|
|
LevelEnabler: zap.LevelEnablerFunc(func(l zapcore.Level) bool { return true }),
|
|
Levels: levels,
|
|
Selector: selector,
|
|
Encoders: map[flogging.Encoding]zapcore.Encoder{
|
|
flogging.CONSOLE: zapcore.NewConsoleEncoder(zapcore.EncoderConfig{}),
|
|
},
|
|
Output: output,
|
|
Observer: observer,
|
|
}
|
|
|
|
err = core.Write(entry, fields)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, observer.WriteEntryCallCount())
|
|
observedEntry, observedFields := observer.WriteEntryArgsForCall(0)
|
|
require.Equal(t, entry, observedEntry)
|
|
require.Equal(t, fields, observedFields)
|
|
}
|