github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/flogging/fabenc/formatter_test.go (about)

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