github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/common/flogging/fabenc/formatter_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package fabenc_test
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"runtime"
    13  	"strconv"
    14  	"sync"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/hyperledger/fabric/common/flogging/fabenc"
    19  	"github.com/stretchr/testify/assert"
    20  	"go.uber.org/zap"
    21  	"go.uber.org/zap/zapcore"
    22  )
    23  
    24  func TestParseFormat(t *testing.T) {
    25  	var tests = []struct {
    26  		desc       string
    27  		spec       string
    28  		formatters []fabenc.Formatter
    29  	}{
    30  		{
    31  			desc:       "empty spec",
    32  			spec:       "",
    33  			formatters: []fabenc.Formatter{},
    34  		},
    35  		{
    36  			desc: "simple verb",
    37  			spec: "%{color}",
    38  			formatters: []fabenc.Formatter{
    39  				fabenc.ColorFormatter{},
    40  			},
    41  		},
    42  		{
    43  			desc: "with prefix",
    44  			spec: "prefix %{color}",
    45  			formatters: []fabenc.Formatter{
    46  				fabenc.StringFormatter{Value: "prefix "},
    47  				fabenc.ColorFormatter{},
    48  			},
    49  		},
    50  		{
    51  			desc: "with suffix",
    52  			spec: "%{color} suffix",
    53  			formatters: []fabenc.Formatter{
    54  				fabenc.ColorFormatter{},
    55  				fabenc.StringFormatter{Value: " suffix"}},
    56  		},
    57  		{
    58  			desc: "with prefix and suffix",
    59  			spec: "prefix %{color} suffix",
    60  			formatters: []fabenc.Formatter{
    61  				fabenc.StringFormatter{Value: "prefix "},
    62  				fabenc.ColorFormatter{},
    63  				fabenc.StringFormatter{Value: " suffix"},
    64  			},
    65  		},
    66  		{
    67  			desc: "with format",
    68  			spec: "%{level:.4s} suffix",
    69  			formatters: []fabenc.Formatter{
    70  				fabenc.LevelFormatter{FormatVerb: "%.4s"},
    71  				fabenc.StringFormatter{Value: " suffix"},
    72  			},
    73  		},
    74  	}
    75  
    76  	for _, tc := range tests {
    77  		t.Run(fmt.Sprintf(tc.desc), func(t *testing.T) {
    78  			formatters, err := fabenc.ParseFormat(tc.spec)
    79  			assert.NoError(t, err)
    80  			assert.Equal(t, tc.formatters, formatters)
    81  		})
    82  	}
    83  }
    84  
    85  func TestParseFormatError(t *testing.T) {
    86  	_, err := fabenc.ParseFormat("%{color:bad}")
    87  	assert.EqualError(t, err, "invalid color option: bad")
    88  }
    89  
    90  func TestNewFormatter(t *testing.T) {
    91  	var tests = []struct {
    92  		verb      string
    93  		format    string
    94  		formatter fabenc.Formatter
    95  		errorMsg  string
    96  	}{
    97  		{verb: "color", format: "", formatter: fabenc.ColorFormatter{}},
    98  		{verb: "color", format: "bold", formatter: fabenc.ColorFormatter{Bold: true}},
    99  		{verb: "color", format: "reset", formatter: fabenc.ColorFormatter{Reset: true}},
   100  		{verb: "color", format: "unknown", errorMsg: "invalid color option: unknown"},
   101  		{verb: "id", format: "", formatter: fabenc.SequenceFormatter{FormatVerb: "%d"}},
   102  		{verb: "id", format: "04x", formatter: fabenc.SequenceFormatter{FormatVerb: "%04x"}},
   103  		{verb: "level", format: "", formatter: fabenc.LevelFormatter{FormatVerb: "%s"}},
   104  		{verb: "level", format: ".4s", formatter: fabenc.LevelFormatter{FormatVerb: "%.4s"}},
   105  		{verb: "message", format: "", formatter: fabenc.MessageFormatter{FormatVerb: "%s"}},
   106  		{verb: "message", format: "#30s", formatter: fabenc.MessageFormatter{FormatVerb: "%#30s"}},
   107  		{verb: "module", format: "", formatter: fabenc.ModuleFormatter{FormatVerb: "%s"}},
   108  		{verb: "module", format: "ok", formatter: fabenc.ModuleFormatter{FormatVerb: "%ok"}},
   109  		{verb: "shortfunc", format: "", formatter: fabenc.ShortFuncFormatter{FormatVerb: "%s"}},
   110  		{verb: "shortfunc", format: "U", formatter: fabenc.ShortFuncFormatter{FormatVerb: "%U"}},
   111  		{verb: "time", format: "", formatter: fabenc.TimeFormatter{Layout: "2006-01-02T15:04:05.999Z07:00"}},
   112  		{verb: "time", format: "04:05.999999Z05:00", formatter: fabenc.TimeFormatter{Layout: "04:05.999999Z05:00"}},
   113  		{verb: "unknown", format: "", errorMsg: "unknown verb: unknown"},
   114  	}
   115  
   116  	for i, tc := range tests {
   117  		t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
   118  			f, err := fabenc.NewFormatter(tc.verb, tc.format)
   119  			if tc.errorMsg == "" {
   120  				assert.NoError(t, err)
   121  				assert.Equal(t, tc.formatter, f)
   122  			} else {
   123  				assert.EqualError(t, err, tc.errorMsg)
   124  			}
   125  		})
   126  	}
   127  }
   128  
   129  func TestColorFormatter(t *testing.T) {
   130  	var tests = []struct {
   131  		f         fabenc.ColorFormatter
   132  		level     zapcore.Level
   133  		formatted string
   134  	}{
   135  		{f: fabenc.ColorFormatter{Reset: true}, level: zapcore.DebugLevel, formatted: fabenc.ResetColor()},
   136  		{f: fabenc.ColorFormatter{}, level: zapcore.DebugLevel, formatted: fabenc.ColorCyan.Normal()},
   137  		{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.DebugLevel, formatted: fabenc.ColorCyan.Bold()},
   138  		{f: fabenc.ColorFormatter{}, level: zapcore.InfoLevel, formatted: fabenc.ColorBlue.Normal()},
   139  		{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.InfoLevel, formatted: fabenc.ColorBlue.Bold()},
   140  		{f: fabenc.ColorFormatter{}, level: zapcore.WarnLevel, formatted: fabenc.ColorYellow.Normal()},
   141  		{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.WarnLevel, formatted: fabenc.ColorYellow.Bold()},
   142  		{f: fabenc.ColorFormatter{}, level: zapcore.ErrorLevel, formatted: fabenc.ColorRed.Normal()},
   143  		{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.ErrorLevel, formatted: fabenc.ColorRed.Bold()},
   144  		{f: fabenc.ColorFormatter{}, level: zapcore.DPanicLevel, formatted: fabenc.ColorMagenta.Normal()},
   145  		{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.DPanicLevel, formatted: fabenc.ColorMagenta.Bold()},
   146  		{f: fabenc.ColorFormatter{}, level: zapcore.PanicLevel, formatted: fabenc.ColorMagenta.Normal()},
   147  		{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.PanicLevel, formatted: fabenc.ColorMagenta.Bold()},
   148  		{f: fabenc.ColorFormatter{}, level: zapcore.FatalLevel, formatted: fabenc.ColorMagenta.Normal()},
   149  		{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.FatalLevel, formatted: fabenc.ColorMagenta.Bold()},
   150  		{f: fabenc.ColorFormatter{}, level: zapcore.Level(99), formatted: fabenc.ColorNone.Normal()},
   151  		{f: fabenc.ColorFormatter{Bold: true}, level: zapcore.Level(99), formatted: fabenc.ColorNone.Normal()},
   152  	}
   153  
   154  	for i, tc := range tests {
   155  		t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
   156  			buf := &bytes.Buffer{}
   157  			entry := zapcore.Entry{Level: tc.level}
   158  			tc.f.Format(buf, entry, nil)
   159  			assert.Equal(t, tc.formatted, buf.String())
   160  		})
   161  	}
   162  }
   163  
   164  func TestLevelFormatter(t *testing.T) {
   165  	var tests = []struct {
   166  		level     zapcore.Level
   167  		formatted string
   168  	}{
   169  		{level: zapcore.DebugLevel, formatted: "DEBUG"},
   170  		{level: zapcore.InfoLevel, formatted: "INFO"},
   171  		{level: zapcore.WarnLevel, formatted: "WARN"},
   172  		{level: zapcore.ErrorLevel, formatted: "ERROR"},
   173  		{level: zapcore.DPanicLevel, formatted: "DPANIC"},
   174  		{level: zapcore.PanicLevel, formatted: "PANIC"},
   175  		{level: zapcore.FatalLevel, formatted: "FATAL"},
   176  		{level: zapcore.Level(99), formatted: "LEVEL(99)"},
   177  	}
   178  
   179  	for i, tc := range tests {
   180  		t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
   181  			buf := &bytes.Buffer{}
   182  			entry := zapcore.Entry{Level: tc.level}
   183  			fabenc.LevelFormatter{FormatVerb: "%s"}.Format(buf, entry, nil)
   184  			assert.Equal(t, tc.formatted, buf.String())
   185  		})
   186  	}
   187  }
   188  
   189  func TestMessageFormatter(t *testing.T) {
   190  	buf := &bytes.Buffer{}
   191  	entry := zapcore.Entry{Message: "some message text \n\n"}
   192  	f := fabenc.MessageFormatter{FormatVerb: "%s"}
   193  	f.Format(buf, entry, nil)
   194  	assert.Equal(t, "some message text ", buf.String())
   195  }
   196  
   197  func TestModuleFormatter(t *testing.T) {
   198  	buf := &bytes.Buffer{}
   199  	entry := zapcore.Entry{LoggerName: "logger/name"}
   200  	f := fabenc.ModuleFormatter{FormatVerb: "%s"}
   201  	f.Format(buf, entry, nil)
   202  	assert.Equal(t, "logger/name", buf.String())
   203  }
   204  
   205  func TestSequenceFormatter(t *testing.T) {
   206  	mutex := &sync.Mutex{}
   207  	results := map[string]struct{}{}
   208  
   209  	ready := &sync.WaitGroup{}
   210  	ready.Add(100)
   211  
   212  	finished := &sync.WaitGroup{}
   213  	finished.Add(100)
   214  
   215  	fabenc.SetSequence(0)
   216  	for i := 1; i <= 100; i++ {
   217  		go func(i int) {
   218  			buf := &bytes.Buffer{}
   219  			entry := zapcore.Entry{Level: zapcore.DebugLevel}
   220  			f := fabenc.SequenceFormatter{FormatVerb: "%d"}
   221  			ready.Done() // setup complete
   222  			ready.Wait() // wait for all go routines to be ready
   223  
   224  			f.Format(buf, entry, nil) // format concurrently
   225  
   226  			mutex.Lock()
   227  			results[buf.String()] = struct{}{}
   228  			mutex.Unlock()
   229  
   230  			finished.Done()
   231  		}(i)
   232  	}
   233  
   234  	finished.Wait()
   235  	for i := 1; i <= 100; i++ {
   236  		assert.Contains(t, results, strconv.Itoa(i))
   237  	}
   238  }
   239  
   240  func TestShortFuncFormatter(t *testing.T) {
   241  	callerpc, _, _, ok := runtime.Caller(0)
   242  	assert.True(t, ok)
   243  	buf := &bytes.Buffer{}
   244  	entry := zapcore.Entry{Caller: zapcore.EntryCaller{PC: callerpc}}
   245  	fabenc.ShortFuncFormatter{FormatVerb: "%s"}.Format(buf, entry, nil)
   246  	assert.Equal(t, "TestShortFuncFormatter", buf.String())
   247  
   248  	buf = &bytes.Buffer{}
   249  	entry = zapcore.Entry{Caller: zapcore.EntryCaller{PC: 0}}
   250  	fabenc.ShortFuncFormatter{FormatVerb: "%s"}.Format(buf, entry, nil)
   251  	assert.Equal(t, "(unknown)", buf.String())
   252  }
   253  
   254  func TestTimeFormatter(t *testing.T) {
   255  	buf := &bytes.Buffer{}
   256  	entry := zapcore.Entry{Time: time.Date(1975, time.August, 15, 12, 0, 0, 333, time.UTC)}
   257  	f := fabenc.TimeFormatter{Layout: time.RFC3339Nano}
   258  	f.Format(buf, entry, nil)
   259  	assert.Equal(t, "1975-08-15T12:00:00.000000333Z", buf.String())
   260  }
   261  
   262  func TestMultiFormatter(t *testing.T) {
   263  	entry := zapcore.Entry{
   264  		Message: "message",
   265  		Level:   zapcore.InfoLevel,
   266  	}
   267  	fields := []zapcore.Field{
   268  		zap.String("name", "value"),
   269  	}
   270  
   271  	var tests = []struct {
   272  		desc     string
   273  		initial  []fabenc.Formatter
   274  		update   []fabenc.Formatter
   275  		expected string
   276  	}{
   277  		{
   278  			desc:     "no formatters",
   279  			initial:  nil,
   280  			update:   nil,
   281  			expected: "",
   282  		},
   283  		{
   284  			desc:     "initial formatters",
   285  			initial:  []fabenc.Formatter{fabenc.StringFormatter{Value: "string1"}},
   286  			update:   nil,
   287  			expected: "string1",
   288  		},
   289  		{
   290  			desc:    "set to formatters",
   291  			initial: []fabenc.Formatter{fabenc.StringFormatter{Value: "string1"}},
   292  			update: []fabenc.Formatter{
   293  				fabenc.StringFormatter{Value: "string1"},
   294  				fabenc.StringFormatter{Value: "-"},
   295  				fabenc.StringFormatter{Value: "string2"},
   296  			},
   297  			expected: "string1-string2",
   298  		},
   299  		{
   300  			desc:     "set to empty",
   301  			initial:  []fabenc.Formatter{fabenc.StringFormatter{Value: "string1"}},
   302  			update:   []fabenc.Formatter{},
   303  			expected: "",
   304  		},
   305  	}
   306  
   307  	for _, tc := range tests {
   308  		mf := fabenc.NewMultiFormatter(tc.initial...)
   309  		if tc.update != nil {
   310  			mf.SetFormatters(tc.update)
   311  		}
   312  
   313  		buf := &bytes.Buffer{}
   314  		mf.Format(buf, entry, fields)
   315  		assert.Equal(t, tc.expected, buf.String())
   316  	}
   317  }