github.com/shoshinnikita/budget-manager@v0.7.1-0.20220131195411-8c46ff1c6778/internal/logger/struct_test.go (about)

     1  package logger
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  func TestStructToFields(t *testing.T) {
    12  	t.Parallel()
    13  
    14  	type testCase struct {
    15  		in         interface{}
    16  		namePrefix string
    17  		want       Fields
    18  	}
    19  	runTestCases := func(t *testing.T, testCases []testCase) {
    20  		for _, tt := range testCases {
    21  			tt := tt
    22  			t.Run("", func(t *testing.T) {
    23  				got := structToFields(tt.in, tt.namePrefix)
    24  				require.Equal(t, tt.want, got)
    25  			})
    26  		}
    27  	}
    28  
    29  	t.Run("wrong types", func(t *testing.T) {
    30  		runTestCases(t, []testCase{
    31  			{in: 5, want: nil},
    32  			{in: 15.7, want: nil},
    33  			{in: "hello", want: nil},
    34  			{in: func() error { return nil }, want: nil},
    35  			{in: map[string]int{"1": 2}, want: nil},
    36  		})
    37  	})
    38  
    39  	t.Run("basic", func(t *testing.T) {
    40  		type S struct {
    41  			A float64 `json:"a"`
    42  			B string  `json:"b"`
    43  			C map[string]float64
    44  			E **int `json:"e"`
    45  			F *float64
    46  			g string
    47  		}
    48  
    49  		var (
    50  			i    = 10
    51  			iPtr = &i
    52  		)
    53  		runTestCases(t, []testCase{
    54  			{
    55  				in:   S{A: 0.15, B: "hello world", C: map[string]float64{"1": 2}, E: &iPtr, F: nil, g: "g"},
    56  				want: Fields{"a": 0.15, "b": "hello world", "C": map[string]float64{"1": 2}, "e": 10, "F": "<nil>"},
    57  			},
    58  			{
    59  				in:         S{A: 0, B: "", E: &iPtr},
    60  				namePrefix: "p",
    61  				want:       Fields{"p.a": 0.0, "p.b": "", "p.C": "<nil>", "p.e": 10, "p.F": "<nil>"},
    62  			},
    63  		})
    64  	})
    65  
    66  	t.Run("complex", func(t *testing.T) {
    67  		type Embedded struct {
    68  			A int `json:"a"`
    69  			B int `json:"b"`
    70  		}
    71  
    72  		type Empty struct{}
    73  
    74  		type Nested1 struct {
    75  			Arr []string `json:"arr"`
    76  		}
    77  
    78  		type Nested struct {
    79  			X      int     `json:"x"`
    80  			Nested Nested1 `json:"nested1"`
    81  		}
    82  
    83  		type S struct {
    84  			Embedded
    85  			Empty
    86  
    87  			A      string `json:"a"`
    88  			Nested Nested `json:"nested"`
    89  		}
    90  
    91  		runTestCases(t, []testCase{
    92  			{
    93  				in:         S{Embedded: Embedded{A: 1, B: 2}, A: "qwerty", Nested: Nested{X: 3}},
    94  				namePrefix: "req",
    95  				want:       Fields{"req.Embedded.a": 1, "req.Embedded.b": 2, "req.a": "qwerty", "req.nested.x": 3, "req.nested.nested1.arr": "<nil>"},
    96  			},
    97  		})
    98  	})
    99  
   100  	t.Run("format", func(t *testing.T) {
   101  		type S struct {
   102  			T time.Time        `json:"t"`
   103  			D time.Duration    `json:"d"`
   104  			B *strings.Builder `json:"b"` // (*strings.Builder).String() panics if builder is nil
   105  		}
   106  
   107  		runTestCases(t, []testCase{
   108  			{
   109  				in: S{
   110  					T: time.Date(2021, time.August, 11, 0, 0, 0, 0, time.UTC),
   111  					D: 5 * time.Second,
   112  				},
   113  				want: Fields{
   114  					"t": "2021-08-11T00:00:00Z",
   115  					"d": "5s",
   116  					"b": "<nil>",
   117  				},
   118  			},
   119  			{
   120  				in: S{
   121  					T: time.Date(2021, time.August, 11, 0, 0, 0, 0, time.UTC),
   122  					B: &strings.Builder{},
   123  				},
   124  				want: Fields{
   125  					"t": "2021-08-11T00:00:00Z",
   126  					"d": "0s",
   127  					"b": "",
   128  				},
   129  			},
   130  		})
   131  	})
   132  }