github.com/ssgreg/logf@v1.4.1/field_test.go (about)

     1  package logf
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func TestField(t *testing.T) {
    12  	cases := []struct {
    13  		name     string
    14  		fn       func(interface{}) Field
    15  		original interface{}
    16  		expected interface{}
    17  	}{
    18  		{
    19  			name:     "Bool",
    20  			fn:       func(v interface{}) Field { return Bool("k", v.(bool)) },
    21  			original: true,
    22  			expected: true,
    23  		},
    24  		{
    25  			name:     "Int",
    26  			fn:       func(v interface{}) Field { return Int("k", v.(int)) },
    27  			original: 42,
    28  			expected: int64(42),
    29  		},
    30  		{
    31  			name:     "Int64",
    32  			fn:       func(v interface{}) Field { return Int64("k", v.(int64)) },
    33  			original: int64(42),
    34  			expected: int64(42),
    35  		},
    36  		{
    37  			name:     "Int32",
    38  			fn:       func(v interface{}) Field { return Int32("k", v.(int32)) },
    39  			original: int32(42),
    40  			expected: int32(42),
    41  		},
    42  		{
    43  			name:     "Int16",
    44  			fn:       func(v interface{}) Field { return Int16("k", v.(int16)) },
    45  			original: int16(42),
    46  			expected: int16(42),
    47  		},
    48  		{
    49  			name:     "Int8",
    50  			fn:       func(v interface{}) Field { return Int8("k", v.(int8)) },
    51  			original: int8(42),
    52  			expected: int8(42),
    53  		},
    54  		{
    55  			name:     "Uint",
    56  			fn:       func(v interface{}) Field { return Uint("k", v.(uint)) },
    57  			original: uint(42),
    58  			expected: uint64(42),
    59  		},
    60  		{
    61  			name:     "Uint64",
    62  			fn:       func(v interface{}) Field { return Uint64("k", v.(uint64)) },
    63  			original: uint64(42),
    64  			expected: uint64(42),
    65  		},
    66  		{
    67  			name:     "Uint32",
    68  			fn:       func(v interface{}) Field { return Uint32("k", v.(uint32)) },
    69  			original: uint32(42),
    70  			expected: uint32(42),
    71  		},
    72  		{
    73  			name:     "Uint16",
    74  			fn:       func(v interface{}) Field { return Uint16("k", v.(uint16)) },
    75  			original: uint16(42),
    76  			expected: uint16(42),
    77  		},
    78  		{
    79  			name:     "Uint8",
    80  			fn:       func(v interface{}) Field { return Uint8("k", v.(uint8)) },
    81  			original: uint8(42),
    82  			expected: uint8(42),
    83  		},
    84  		{
    85  			name:     "Float64",
    86  			fn:       func(v interface{}) Field { return Float64("k", v.(float64)) },
    87  			original: float64(42),
    88  			expected: float64(42),
    89  		},
    90  		{
    91  			name:     "Float32",
    92  			fn:       func(v interface{}) Field { return Float32("k", v.(float32)) },
    93  			original: float32(42),
    94  			expected: float32(42),
    95  		},
    96  		{
    97  			name:     "Duration",
    98  			fn:       func(v interface{}) Field { return Duration("k", v.(time.Duration)) },
    99  			original: time.Second,
   100  			expected: time.Second,
   101  		},
   102  		{
   103  			name:     "String",
   104  			fn:       func(v interface{}) Field { return String("k", v.(string)) },
   105  			original: "42",
   106  			expected: "42",
   107  		},
   108  		{
   109  			name:     "ConstBytes",
   110  			fn:       func(v interface{}) Field { return ConstBytes("k", v.([]byte)) },
   111  			original: []byte{42},
   112  			expected: []byte{42},
   113  		},
   114  		{
   115  			name:     "ConstBools",
   116  			fn:       func(v interface{}) Field { return ConstBools("k", v.([]bool)) },
   117  			original: []bool{true},
   118  			expected: []bool{true},
   119  		},
   120  		{
   121  			name:     "ConstInts",
   122  			fn:       func(v interface{}) Field { return ConstInts("k", v.([]int)) },
   123  			original: []int{42},
   124  			expected: []int64{42},
   125  		},
   126  		{
   127  			name:     "ConstInts64",
   128  			fn:       func(v interface{}) Field { return ConstInts64("k", v.([]int64)) },
   129  			original: []int64{42},
   130  			expected: []int64{42},
   131  		},
   132  		{
   133  			name:     "ConstInts32",
   134  			fn:       func(v interface{}) Field { return ConstInts32("k", v.([]int32)) },
   135  			original: []int32{42},
   136  			expected: []int32{42},
   137  		},
   138  		{
   139  			name:     "ConstInts16",
   140  			fn:       func(v interface{}) Field { return ConstInts16("k", v.([]int16)) },
   141  			original: []int16{42},
   142  			expected: []int16{42},
   143  		},
   144  		{
   145  			name:     "ConstInts8",
   146  			fn:       func(v interface{}) Field { return ConstInts8("k", v.([]int8)) },
   147  			original: []int8{42},
   148  			expected: []int8{42},
   149  		},
   150  		{
   151  			name:     "ConstUints",
   152  			fn:       func(v interface{}) Field { return ConstUints("k", v.([]uint)) },
   153  			original: []uint{42},
   154  			expected: []uint64{42},
   155  		},
   156  		{
   157  			name:     "ConstUints64",
   158  			fn:       func(v interface{}) Field { return ConstUints64("k", v.([]uint64)) },
   159  			original: []uint64{42},
   160  			expected: []uint64{42},
   161  		},
   162  		{
   163  			name:     "ConstUints32",
   164  			fn:       func(v interface{}) Field { return ConstUints32("k", v.([]uint32)) },
   165  			original: []uint32{42},
   166  			expected: []uint32{42},
   167  		},
   168  		{
   169  			name:     "ConstUints16",
   170  			fn:       func(v interface{}) Field { return ConstUints16("k", v.([]uint16)) },
   171  			original: []uint16{42},
   172  			expected: []uint16{42},
   173  		},
   174  		{
   175  			name:     "ConstUints8",
   176  			fn:       func(v interface{}) Field { return ConstUints8("k", v.([]uint8)) },
   177  			original: []uint8{42},
   178  			expected: []uint8{42},
   179  		},
   180  		{
   181  			name:     "ConstFloats64",
   182  			fn:       func(v interface{}) Field { return ConstFloats64("k", v.([]float64)) },
   183  			original: []float64{42},
   184  			expected: []float64{42},
   185  		},
   186  		{
   187  			name:     "ConstFloats32",
   188  			fn:       func(v interface{}) Field { return ConstFloats32("k", v.([]float32)) },
   189  			original: []float32{42},
   190  			expected: []float32{42},
   191  		},
   192  		{
   193  			name:     "ConstDurations",
   194  			fn:       func(v interface{}) Field { return ConstDurations("k", v.([]time.Duration)) },
   195  			original: []time.Duration{time.Second},
   196  			expected: []time.Duration{time.Second},
   197  		},
   198  	}
   199  
   200  	for _, c := range cases {
   201  		t.Run(c.name, func(t *testing.T) {
   202  			f := c.fn(c.original)
   203  			e := newTestFieldEncoder()
   204  			f.Accept(e)
   205  			assert.Equal(t, c.expected, e.result["k"])
   206  		})
   207  		t.Run(c.name+"->Any", func(t *testing.T) {
   208  			f := Any("k", c.original)
   209  
   210  			// Need to snapshot fields because Any could return raw byte
   211  			// types that need to be copied.
   212  			snapshotField(&f)
   213  			e := newTestFieldEncoder()
   214  			f.Accept(e)
   215  
   216  			assert.Equal(t, c.expected, e.result["k"])
   217  		})
   218  	}
   219  }
   220  
   221  func TestFieldStrings(t *testing.T) {
   222  	check := func(t *testing.T, f *Field) {
   223  		e := newTestFieldEncoder()
   224  		f.Accept(e)
   225  
   226  		ae := e.result["k"].(ArrayEncoder)
   227  		te := testTypeEncoder{}
   228  		ae.EncodeLogfArray(&te)
   229  
   230  		assert.Equal(t, "42", te.result)
   231  	}
   232  
   233  	t.Run("Time", func(t *testing.T) {
   234  		f := Strings("k", []string{"42"})
   235  		check(t, &f)
   236  	})
   237  	t.Run("Time->Any", func(t *testing.T) {
   238  		f := Any("k", []string{"42"})
   239  		check(t, &f)
   240  	})
   241  }
   242  
   243  func TestFieldArray(t *testing.T) {
   244  	golden := &testArrayEncoder{}
   245  
   246  	check := func(t *testing.T, f *Field) {
   247  		e := newTestFieldEncoder()
   248  		f.Accept(e)
   249  		assert.Equal(t, golden, e.result["k"])
   250  	}
   251  
   252  	t.Run("Array", func(t *testing.T) {
   253  		f := Array("k", &testArrayEncoder{})
   254  		check(t, &f)
   255  	})
   256  	t.Run("Array->Any", func(t *testing.T) {
   257  		f := Any("k", &testArrayEncoder{})
   258  		check(t, &f)
   259  	})
   260  }
   261  
   262  func TestFieldNilArray(t *testing.T) {
   263  	e := newTestFieldEncoder()
   264  	f := Array("k", nil)
   265  	f.Accept(e)
   266  	assert.Equal(t, "nil", e.result["k"])
   267  }
   268  
   269  func TestFieldObject(t *testing.T) {
   270  	golden := &testObjectEncoder{}
   271  
   272  	check := func(t *testing.T, f *Field) {
   273  		e := newTestFieldEncoder()
   274  		f.Accept(e)
   275  		assert.Equal(t, golden, e.result["k"])
   276  	}
   277  
   278  	t.Run("Array", func(t *testing.T) {
   279  		f := Object("k", &testObjectEncoder{})
   280  		check(t, &f)
   281  	})
   282  	t.Run("Array->Any", func(t *testing.T) {
   283  		f := Any("k", &testObjectEncoder{})
   284  		check(t, &f)
   285  	})
   286  }
   287  
   288  func TestFieldNilObject(t *testing.T) {
   289  	e := newTestFieldEncoder()
   290  	f := Object("k", nil)
   291  	f.Accept(e)
   292  	assert.Equal(t, "nil", e.result["k"])
   293  }
   294  
   295  func TestFieldTime(t *testing.T) {
   296  	golden := time.Now()
   297  
   298  	check := func(t *testing.T, f *Field) {
   299  		e := newTestFieldEncoder()
   300  		f.Accept(e)
   301  
   302  		assert.Equal(t, golden.Format(time.RFC3339Nano), (e.result["k"].(time.Time)).Format(time.RFC3339Nano))
   303  	}
   304  
   305  	t.Run("Time", func(t *testing.T) {
   306  		f := Time("k", golden)
   307  		check(t, &f)
   308  	})
   309  	t.Run("Any->Time", func(t *testing.T) {
   310  		f := Any("k", golden)
   311  		check(t, &f)
   312  	})
   313  }
   314  
   315  func TestFieldTimeWithoutLocation(t *testing.T) {
   316  	golden := time.Unix(320836234, 0)
   317  
   318  	e := newTestFieldEncoder()
   319  	f := Field{Key: "k", Type: FieldTypeTime, Int: golden.UnixNano()}
   320  	f.Accept(e)
   321  
   322  	assert.Equal(t, golden.Format(time.RFC3339Nano), (e.result["k"].(time.Time)).Format(time.RFC3339Nano))
   323  }
   324  
   325  func TestFieldStringer(t *testing.T) {
   326  	golden := "before"
   327  	str := &testStringer{golden}
   328  
   329  	e := newTestFieldEncoder()
   330  	f := Stringer("k", str)
   331  
   332  	// Change result returning by str. Stinger must call String() during a
   333  	// call of Stringer().
   334  	str.result = "after"
   335  
   336  	f.Accept(e)
   337  	assert.Equal(t, golden, e.result["k"])
   338  }
   339  
   340  func TestFieldNilStringer(t *testing.T) {
   341  	e := newTestFieldEncoder()
   342  	f := Stringer("k", nil)
   343  
   344  	f.Accept(e)
   345  	assert.Equal(t, "nil", e.result["k"])
   346  }
   347  
   348  func TestFieldConstStringer(t *testing.T) {
   349  	golden := "before"
   350  	str := &testStringer{golden}
   351  
   352  	e := newTestFieldEncoder()
   353  	f := ConstStringer("k", str)
   354  
   355  	f.Accept(e)
   356  	assert.Equal(t, golden, e.result["k"])
   357  }
   358  
   359  func TestFieldNilConstStringer(t *testing.T) {
   360  	e := newTestFieldEncoder()
   361  	f := ConstStringer("k", nil)
   362  
   363  	f.Accept(e)
   364  	assert.Equal(t, "nil", e.result["k"])
   365  }
   366  func TestFieldConstFormatter(t *testing.T) {
   367  	golden := "42"
   368  	e := newTestFieldEncoder()
   369  	f := ConstFormatter("k", "%d", 42)
   370  
   371  	f.Accept(e)
   372  	assert.Equal(t, golden, e.result["k"])
   373  }
   374  
   375  func TestFieldConstFormatterV(t *testing.T) {
   376  	type testFormatterV struct {
   377  		str string
   378  	}
   379  
   380  	e := newTestFieldEncoder()
   381  	f := ConstFormatterV("k", testFormatterV{"42"})
   382  
   383  	f.Accept(e)
   384  	assert.Equal(t, `logf.testFormatterV{str:"42"}`, e.result["k"])
   385  }
   386  
   387  func TestFieldFormatter(t *testing.T) {
   388  	type testFormatterV struct {
   389  		str string
   390  	}
   391  	testing := testFormatterV{"42"}
   392  
   393  	e := newTestFieldEncoder()
   394  	f := Formatter("k", "%s", &testing)
   395  
   396  	// Change testing value to check that ConstFormatter formats string
   397  	// during it's call.
   398  	testing.str = "66"
   399  
   400  	f.Accept(e)
   401  	assert.Equal(t, "&{42}", e.result["k"])
   402  }
   403  
   404  func TestFieldFormatterV(t *testing.T) {
   405  	type testFormatterV struct {
   406  		str string
   407  	}
   408  	testing := testFormatterV{"42"}
   409  
   410  	e := newTestFieldEncoder()
   411  	f := FormatterV("k", &testing)
   412  
   413  	// Change testing value to check that ConstFormatter formats string
   414  	// during it's call.
   415  	testing.str = "66"
   416  
   417  	f.Accept(e)
   418  	assert.Equal(t, `&logf.testFormatterV{str:"42"}`, e.result["k"])
   419  }
   420  
   421  func TestFieldNamedError(t *testing.T) {
   422  	golden := errors.New("named error")
   423  
   424  	check := func(t *testing.T, f *Field) {
   425  		e := newTestFieldEncoder()
   426  		f.Accept(e)
   427  		assert.Equal(t, golden, e.result["k"])
   428  	}
   429  
   430  	t.Run("NamedError", func(t *testing.T) {
   431  		f := NamedError("k", golden)
   432  		check(t, &f)
   433  	})
   434  	t.Run("NamedError->Any", func(t *testing.T) {
   435  		f := Any("k", golden)
   436  		check(t, &f)
   437  	})
   438  }
   439  
   440  func TestFieldError(t *testing.T) {
   441  	golden := errors.New("common error")
   442  
   443  	e := newTestFieldEncoder()
   444  	f := Error(golden)
   445  
   446  	f.Accept(e)
   447  	assert.Equal(t, golden, e.result["error"])
   448  }
   449  
   450  func TestFieldNilError(t *testing.T) {
   451  	f := Error(nil)
   452  	e := newTestFieldEncoder()
   453  	f.Accept(e)
   454  	assert.Equal(t, nil, e.result["error"])
   455  }
   456  
   457  func TestFieldAnyWithCustomType(t *testing.T) {
   458  	type customType struct{}
   459  	customTypeValue := customType{}
   460  
   461  	f := Any("k", &customTypeValue)
   462  	e := newTestFieldEncoder()
   463  	f.Accept(e)
   464  	assert.Equal(t, &customTypeValue, e.result["k"])
   465  }
   466  
   467  func TestFieldAnyReflect(t *testing.T) {
   468  	type customStringType string
   469  	type customBoolType bool
   470  	type customIntType int
   471  	type customInt64Type int64
   472  	type customInt32Type int32
   473  	type customInt16Type int16
   474  	type customInt8Type int8
   475  	type customUintType uint
   476  	type customUint64Type uint64
   477  	type customUint32Type uint32
   478  	type customUint16Type uint16
   479  	type customUint8Type uint8
   480  	type customFloat64Type float64
   481  	type customFloat32Type float32
   482  
   483  	cases := []struct {
   484  		name     string
   485  		original interface{}
   486  		expected interface{}
   487  	}{
   488  		{
   489  			name:     "String",
   490  			original: customStringType("42"),
   491  			expected: "42",
   492  		},
   493  		{
   494  			name:     "Bool",
   495  			original: customBoolType(true),
   496  			expected: true,
   497  		},
   498  		{
   499  			name:     "Int",
   500  			original: customIntType(42),
   501  			expected: int64(42),
   502  		},
   503  		{
   504  			name:     "Int64",
   505  			original: customInt64Type(42),
   506  			expected: int64(42),
   507  		},
   508  		{
   509  			name:     "Int32",
   510  			original: customInt32Type(42),
   511  			expected: int64(42),
   512  		},
   513  		{
   514  			name:     "Int16",
   515  			original: customInt16Type(42),
   516  			expected: int64(42),
   517  		},
   518  		{
   519  			name:     "Int8",
   520  			original: customInt8Type(42),
   521  			expected: int64(42),
   522  		},
   523  		{
   524  			name:     "Uint",
   525  			original: customUintType(42),
   526  			expected: uint64(42),
   527  		},
   528  		{
   529  			name:     "Uint64",
   530  			original: customUint64Type(42),
   531  			expected: uint64(42),
   532  		},
   533  		{
   534  			name:     "Uint32",
   535  			original: customUint32Type(42),
   536  			expected: uint64(42),
   537  		},
   538  		{
   539  			name:     "Uint16",
   540  			original: customUint16Type(42),
   541  			expected: uint64(42),
   542  		},
   543  		{
   544  			name:     "Uint8",
   545  			original: customUint8Type(42),
   546  			expected: uint64(42),
   547  		},
   548  		{
   549  			name:     "Float64",
   550  			original: customFloat64Type(42),
   551  			expected: float64(42),
   552  		},
   553  		{
   554  			name:     "Float32",
   555  			original: customFloat32Type(42),
   556  			expected: float64(42),
   557  		},
   558  		{
   559  			name:     "nil",
   560  			original: nil,
   561  			expected: nil,
   562  		},
   563  	}
   564  
   565  	for _, c := range cases {
   566  		t.Run(c.name, func(t *testing.T) {
   567  			f := Any("k", c.original)
   568  			e := newTestFieldEncoder()
   569  			f.Accept(e)
   570  			assert.Equal(t, c.expected, e.result["k"])
   571  		})
   572  	}
   573  
   574  }