|
@@ -7,6 +7,7 @@ import (
|
|
|
"io/ioutil"
|
|
|
"log"
|
|
|
"os"
|
|
|
+ "reflect"
|
|
|
"runtime"
|
|
|
"strings"
|
|
|
"sync"
|
|
@@ -92,6 +93,86 @@ func (mw *mockWriter) String() string {
|
|
|
return mw.builder.String()
|
|
|
}
|
|
|
|
|
|
+func TestField(t *testing.T) {
|
|
|
+ tests := []struct {
|
|
|
+ name string
|
|
|
+ f LogField
|
|
|
+ want map[string]interface{}
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ name: "error",
|
|
|
+ f: Field("foo", errors.New("bar")),
|
|
|
+ want: map[string]interface{}{
|
|
|
+ "foo": "bar",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "errors",
|
|
|
+ f: Field("foo", []error{errors.New("bar"), errors.New("baz")}),
|
|
|
+ want: map[string]interface{}{
|
|
|
+ "foo": []interface{}{"bar", "baz"},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "strings",
|
|
|
+ f: Field("foo", []string{"bar", "baz"}),
|
|
|
+ want: map[string]interface{}{
|
|
|
+ "foo": []interface{}{"bar", "baz"},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "duration",
|
|
|
+ f: Field("foo", time.Second),
|
|
|
+ want: map[string]interface{}{
|
|
|
+ "foo": "1s",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "durations",
|
|
|
+ f: Field("foo", []time.Duration{time.Second, 2 * time.Second}),
|
|
|
+ want: map[string]interface{}{
|
|
|
+ "foo": []interface{}{"1s", "2s"},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "times",
|
|
|
+ f: Field("foo", []time.Time{
|
|
|
+ time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC),
|
|
|
+ time.Date(2020, time.January, 2, 0, 0, 0, 0, time.UTC),
|
|
|
+ }),
|
|
|
+ want: map[string]interface{}{
|
|
|
+ "foo": []interface{}{"2020-01-01 00:00:00 +0000 UTC", "2020-01-02 00:00:00 +0000 UTC"},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "stringer",
|
|
|
+ f: Field("foo", ValStringer{val: "bar"}),
|
|
|
+ want: map[string]interface{}{
|
|
|
+ "foo": "bar",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "stringers",
|
|
|
+ f: Field("foo", []fmt.Stringer{ValStringer{val: "bar"}, ValStringer{val: "baz"}}),
|
|
|
+ want: map[string]interface{}{
|
|
|
+ "foo": []interface{}{"bar", "baz"},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, test := range tests {
|
|
|
+ test := test
|
|
|
+ t.Run(test.name, func(t *testing.T) {
|
|
|
+ w := new(mockWriter)
|
|
|
+ old := writer.Swap(w)
|
|
|
+ defer writer.Store(old)
|
|
|
+
|
|
|
+ Infow("foo", test.f)
|
|
|
+ validateFields(t, w.String(), test.want)
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func TestFileLineFileMode(t *testing.T) {
|
|
|
w := new(mockWriter)
|
|
|
old := writer.Swap(w)
|
|
@@ -675,3 +756,18 @@ type ValStringer struct {
|
|
|
func (v ValStringer) String() string {
|
|
|
return v.val
|
|
|
}
|
|
|
+
|
|
|
+func validateFields(t *testing.T, content string, fields map[string]interface{}) {
|
|
|
+ var m map[string]interface{}
|
|
|
+ if err := json.Unmarshal([]byte(content), &m); err != nil {
|
|
|
+ t.Error(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ for k, v := range fields {
|
|
|
+ if reflect.TypeOf(v).Kind() == reflect.Slice {
|
|
|
+ assert.EqualValues(t, v, m[k])
|
|
|
+ } else {
|
|
|
+ assert.Equal(t, v, m[k], content)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|