github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/zlog/logfmt_encoder_test.go (about)

     1  package zlog
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"go.uber.org/zap"
    10  	"go.uber.org/zap/buffer"
    11  	"go.uber.org/zap/zapcore"
    12  )
    13  
    14  func TestEncoderObjectFields(t *testing.T) {
    15  	tests := []struct {
    16  		desc     string
    17  		expected string
    18  		f        func(zapcore.Encoder)
    19  	}{
    20  		{"binary", `k="YWIxMg=="`, func(e zapcore.Encoder) { e.AddBinary("k", []byte("ab12")) }},
    21  		{"bool", `k\\=true`, func(e zapcore.Encoder) { e.AddBool(`k\`, true) }}, // test key escaping once
    22  		{"bool", `k=true`, func(e zapcore.Encoder) { e.AddBool("k", true) }},
    23  		{"bool", `k=false`, func(e zapcore.Encoder) { e.AddBool("k", false) }},
    24  		{"byteString", `k=v\\`, func(e zapcore.Encoder) { e.AddByteString(`k`, []byte(`v\`)) }},
    25  		{"byteString", `k=v`, func(e zapcore.Encoder) { e.AddByteString("k", []byte("v")) }},
    26  		{"byteString", `k=`, func(e zapcore.Encoder) { e.AddByteString("k", []byte{}) }},
    27  		{"byteString", `k=`, func(e zapcore.Encoder) { e.AddByteString("k", nil) }},
    28  		{"byteString", `k="a b"`, func(e zapcore.Encoder) { e.AddByteString("k", []byte("a b")) }},
    29  		{"complex128", `k=1+2i`, func(e zapcore.Encoder) { e.AddComplex128("k", 1+2i) }},
    30  		{"complex64", `k=1+2i`, func(e zapcore.Encoder) { e.AddComplex64("k", 1+2i) }},
    31  		{"duration", `k=0.000000001`, func(e zapcore.Encoder) { e.AddDuration("k", 1) }},
    32  		{"float64", `k=1`, func(e zapcore.Encoder) { e.AddFloat64("k", 1.0) }},
    33  		{"float64", `k=10000000000`, func(e zapcore.Encoder) { e.AddFloat64("k", 1e10) }},
    34  		{"float64", `k=NaN`, func(e zapcore.Encoder) { e.AddFloat64("k", math.NaN()) }},
    35  		{"float64", `k=+Inf`, func(e zapcore.Encoder) { e.AddFloat64("k", math.Inf(1)) }},
    36  		{"float64", `k=-Inf`, func(e zapcore.Encoder) { e.AddFloat64("k", math.Inf(-1)) }},
    37  		{"float32", `k=1`, func(e zapcore.Encoder) { e.AddFloat32("k", 1.0) }},
    38  		{"float32", `k=10000000000`, func(e zapcore.Encoder) { e.AddFloat32("k", 1e10) }},
    39  		{"float32", `k=NaN`, func(e zapcore.Encoder) { e.AddFloat32("k", float32(math.NaN())) }},
    40  		{"float32", `k=+Inf`, func(e zapcore.Encoder) { e.AddFloat32("k", float32(math.Inf(1))) }},
    41  		{"float32", `k=-Inf`, func(e zapcore.Encoder) { e.AddFloat32("k", float32(math.Inf(-1))) }},
    42  		{"int", `k=42`, func(e zapcore.Encoder) { e.AddInt("k", 42) }},
    43  		{"int64", `k=42`, func(e zapcore.Encoder) { e.AddInt64("k", 42) }},
    44  		{"int32", `k=42`, func(e zapcore.Encoder) { e.AddInt32("k", 42) }},
    45  		{"int16", `k=42`, func(e zapcore.Encoder) { e.AddInt16("k", 42) }},
    46  		{"int8", `k=42`, func(e zapcore.Encoder) { e.AddInt8("k", 42) }},
    47  		{"string", `k=v\\`, func(e zapcore.Encoder) { e.AddString(`k`, `v\`) }},
    48  		{"string", `k=v`, func(e zapcore.Encoder) { e.AddString("k", "v") }},
    49  		{"string", `k=`, func(e zapcore.Encoder) { e.AddString("k", "") }},
    50  		{"string", `k="a b"`, func(e zapcore.Encoder) { e.AddString("k", "a b") }},
    51  		{"time", `k=1`, func(e zapcore.Encoder) { e.AddTime("k", time.Unix(1, 0)) }},
    52  		{"uint", `k=42`, func(e zapcore.Encoder) { e.AddUint("k", 42) }},
    53  		{"uint64", `k=42`, func(e zapcore.Encoder) { e.AddUint64("k", 42) }},
    54  		{"uint32", `k=42`, func(e zapcore.Encoder) { e.AddUint32("k", 42) }},
    55  		{"uint16", `k=42`, func(e zapcore.Encoder) { e.AddUint16("k", 42) }},
    56  		{"uint8", `k=42`, func(e zapcore.Encoder) { e.AddUint8("k", 42) }},
    57  		{"uintptr", `k=42`, func(e zapcore.Encoder) { e.AddUintptr("k", 42) }},
    58  		{
    59  			desc:     "array (success)",
    60  			expected: `k=a,b`,
    61  			f: func(e zapcore.Encoder) {
    62  				assert.NoError(
    63  					t,
    64  					e.AddArray(`k`, zapcore.ArrayMarshalerFunc(func(enc zapcore.ArrayEncoder) error {
    65  						for _, s := range []string{"a", "b"} {
    66  							enc.AppendString(s)
    67  						}
    68  						return nil
    69  					}),
    70  					),
    71  					"Unexpected error calling MarshalLogArray.",
    72  				)
    73  			},
    74  		},
    75  		{
    76  			desc:     "namespace",
    77  			expected: `outermost.outer.foo=1 outermost.outer.inner.foo=2`,
    78  			f: func(e zapcore.Encoder) {
    79  				e.OpenNamespace("outermost")
    80  				e.OpenNamespace("outer")
    81  				e.AddInt("foo", 1)
    82  				e.OpenNamespace("inner")
    83  				e.AddInt("foo", 2)
    84  				e.OpenNamespace("innermost")
    85  			},
    86  		},
    87  		{"reflected slice", "k=a,b", func(e zapcore.Encoder) { e.AddReflected("k", []string{"a", "b"}) }},
    88  		{"reflected slice of int", "k=1,2,3", func(e zapcore.Encoder) { e.AddReflected("k", []int16{1, 2, 3}) }},
    89  		{"reflected array", "k=a,b", func(e zapcore.Encoder) { e.AddReflected("k", [2]string{"a", "b"}) }},
    90  	}
    91  
    92  	for _, tt := range tests {
    93  		assertOutput(t, tt.desc, tt.expected, tt.f)
    94  	}
    95  }
    96  
    97  func assertOutput(t testing.TB, desc string, expected string, f func(zapcore.Encoder)) {
    98  	enc := &logfmtEncoder{buf: bufferpool.Get(), EncoderConfig: &zapcore.EncoderConfig{
    99  		EncodeTime:     zapcore.EpochTimeEncoder,
   100  		EncodeDuration: zapcore.SecondsDurationEncoder,
   101  	}}
   102  	f(enc)
   103  	assert.Equal(t, expected, enc.buf.String(), "Unexpected encoder output after adding a %s.", desc)
   104  
   105  	enc.truncate()
   106  	enc.AddString("foo", "bar")
   107  	f(enc)
   108  	expectedPrefix := `foo=bar`
   109  	if expected != "" {
   110  		// If we expect output, it should be comma-separated from the previous
   111  		// field.
   112  		expectedPrefix += " "
   113  	}
   114  	assert.Equal(t, expectedPrefix+expected, enc.buf.String(), "Unexpected encoder output after adding a %s as a second field.", desc)
   115  }
   116  
   117  func TestEncodeCaller(t *testing.T) {
   118  	enc := &logfmtEncoder{buf: bufferpool.Get(), EncoderConfig: &zapcore.EncoderConfig{
   119  		EncodeTime:     zapcore.EpochTimeEncoder,
   120  		EncodeDuration: zapcore.SecondsDurationEncoder,
   121  		EncodeCaller:   zapcore.ShortCallerEncoder,
   122  	}}
   123  
   124  	var buf *buffer.Buffer
   125  	var err error
   126  	encodeEntry := func() {
   127  		buf, err = enc.EncodeEntry(
   128  			zapcore.Entry{
   129  				Level:      zapcore.DebugLevel,
   130  				Time:       time.Time{},
   131  				LoggerName: "test",
   132  				Message:    "caller test",
   133  				Caller: zapcore.EntryCaller{
   134  					Defined: true,
   135  					File:    "h2g2.go",
   136  					Line:    42,
   137  				},
   138  			},
   139  			[]zapcore.Field{
   140  				zap.String("k", "v"),
   141  			},
   142  		)
   143  	}
   144  
   145  	encodeEntry()
   146  	assert.Nil(t, err)
   147  	assert.Equal(t, "k=v\n", buf.String())
   148  
   149  	enc.truncate()
   150  	enc.EncoderConfig.CallerKey = "caller"
   151  	encodeEntry()
   152  	assert.Nil(t, err)
   153  	assert.Equal(t, "caller=h2g2.go:42 k=v\n", buf.String())
   154  }
   155  
   156  func TestEncodeStacktrace(t *testing.T) {
   157  	enc := &logfmtEncoder{buf: bufferpool.Get(), EncoderConfig: &zapcore.EncoderConfig{
   158  		EncodeTime:     zapcore.EpochTimeEncoder,
   159  		EncodeDuration: zapcore.SecondsDurationEncoder,
   160  	}}
   161  
   162  	var buf *buffer.Buffer
   163  	var err error
   164  	encodeEntry := func() {
   165  		buf, err = enc.EncodeEntry(
   166  			zapcore.Entry{
   167  				Level:      zapcore.DebugLevel,
   168  				Time:       time.Time{},
   169  				LoggerName: "test",
   170  				Message:    "stacktrace test",
   171  				Stack: `panic: an unexpected error occurred
   172  
   173  goroutine 1 [running]:
   174  main.main()
   175  		/go/src/github.com/jsternberg/myawesomeproject/h2g2.go:4 +0x39
   176  `,
   177  			},
   178  			[]zapcore.Field{
   179  				zap.String("k", "v"),
   180  			},
   181  		)
   182  	}
   183  
   184  	encodeEntry()
   185  	assert.Nil(t, err)
   186  	assert.Equal(t, "k=v\n", buf.String())
   187  
   188  	enc.truncate()
   189  	enc.EncoderConfig.StacktraceKey = "stacktrace"
   190  	encodeEntry()
   191  	assert.Nil(t, err)
   192  	assert.Equal(t, `k=v stacktrace="panic: an unexpected error occurred\n\ngoroutine 1 [running]:\nmain.main()\n\t\t/go/src/github.com/jsternberg/myawesomeproject/h2g2.go:4 +0x39\n"
   193  `, buf.String())
   194  }