...

Source file src/cdr.dev/slog/map_test.go

Documentation: cdr.dev/slog

     1  package slog_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io"
     7  	"runtime"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"golang.org/x/xerrors"
    13  
    14  	"cdr.dev/slog"
    15  	"cdr.dev/slog/internal/assert"
    16  )
    17  
    18  var _, mapTestFile, _, _ = runtime.Caller(0)
    19  
    20  func TestMap(t *testing.T) {
    21  	t.Parallel()
    22  
    23  	test := func(t *testing.T, m slog.Map, exp string) {
    24  		t.Helper()
    25  		exp = indentJSON(t, exp)
    26  		act := marshalJSON(t, m)
    27  		assert.Equal(t, "JSON", exp, act)
    28  	}
    29  
    30  	t.Run("JSON", func(t *testing.T) {
    31  		t.Parallel()
    32  
    33  		type Meow struct {
    34  			Wow       string `json:"meow"`
    35  			Something int    `json:",omitempty"`
    36  			Ignored   bool   `json:"-"`
    37  		}
    38  
    39  		test(t, slog.M(
    40  			slog.Error(
    41  				xerrors.Errorf("wrap1: %w",
    42  					xerrors.Errorf("wrap2: %w",
    43  						io.EOF,
    44  					),
    45  				),
    46  			),
    47  			slog.F("meow", struct {
    48  				Izi string `json:"izi"`
    49  				M   *Meow  `json:"Amazing"`
    50  
    51  				ignored bool
    52  			}{
    53  				Izi: "sogood",
    54  				M: &Meow{
    55  					Wow:       "",
    56  					Something: 0,
    57  					Ignored:   true,
    58  				},
    59  			}),
    60  		), `{
    61  			"error": [
    62  				{
    63  					"msg": "wrap1",
    64  					"fun": "cdr.dev/slog_test.TestMap.func2",
    65  					"loc": "`+mapTestFile+`:41" 
    66  				},
    67  				{
    68  					"msg": "wrap2",
    69  					"fun": "cdr.dev/slog_test.TestMap.func2",
    70  					"loc": "`+mapTestFile+`:42" 
    71  				},
    72  				"EOF"
    73  			],
    74  			"meow": {
    75  				"izi": "sogood",
    76  				"Amazing": {
    77  					"meow": ""
    78  				}
    79  			}
    80  		}`)
    81  	})
    82  
    83  	t.Run("badJSON", func(t *testing.T) {
    84  		t.Parallel()
    85  
    86  		mapTestFile := strings.Replace(mapTestFile, "_test", "", 1)
    87  
    88  		test(t, slog.M(
    89  			slog.F("meow", complexJSON(complex(10, 10))),
    90  		), `{
    91  			"meow": {
    92  				"error": [
    93  					{
    94  						"msg": "failed to marshal to JSON",
    95  						"fun": "cdr.dev/slog.encodeJSON",
    96  						"loc": "`+mapTestFile+`:131"
    97  					},
    98  					"json: error calling MarshalJSON for type slog_test.complexJSON: json: unsupported type: complex128"
    99  				],
   100  				"type": "slog_test.complexJSON",
   101  				"value": "(10+10i)"
   102  			}
   103  		}`)
   104  	})
   105  
   106  	t.Run("basic", func(t *testing.T) {
   107  		t.Parallel()
   108  
   109  		test(t, slog.M(
   110  			slog.F("wow", slog.M(
   111  				slog.F("nested", true),
   112  				slog.F("much", 3),
   113  				slog.F("list", []string{
   114  					"3",
   115  					"5",
   116  				}),
   117  			)),
   118  		), `{
   119  			"wow": {
   120  				"nested": true,
   121  				"much": 3,
   122  				"list": [
   123  					"3",
   124  					"5"
   125  				]
   126  			}
   127  		}`)
   128  	})
   129  
   130  	t.Run("slice", func(t *testing.T) {
   131  		t.Parallel()
   132  
   133  		test(t, slog.M(
   134  			slog.F("meow", []string{
   135  				"1",
   136  				"2",
   137  				"3",
   138  			}),
   139  		), `{
   140  			"meow": [
   141  				"1",
   142  				"2",
   143  				"3"
   144  			]
   145  		}`)
   146  	})
   147  
   148  	t.Run("array", func(t *testing.T) {
   149  		t.Parallel()
   150  
   151  		test(t, slog.M(
   152  			slog.F("meow", [3]string{
   153  				"1",
   154  				"2",
   155  				"3",
   156  			}),
   157  		), `{
   158  			"meow": [
   159  				"1",
   160  				"2",
   161  				"3"
   162  			]
   163  		}`)
   164  	})
   165  
   166  	t.Run("nilSlice", func(t *testing.T) {
   167  		t.Parallel()
   168  
   169  		test(t, slog.M(
   170  			slog.F("slice", []string(nil)),
   171  		), `{
   172  			"slice": null
   173  		}`)
   174  	})
   175  
   176  	t.Run("nil", func(t *testing.T) {
   177  		t.Parallel()
   178  
   179  		test(t, slog.M(
   180  			slog.F("val", nil),
   181  		), `{
   182  			"val": null
   183  		}`)
   184  	})
   185  
   186  	t.Run("json.Marshaler", func(t *testing.T) {
   187  		t.Parallel()
   188  
   189  		test(t, slog.M(
   190  			slog.F("val", time.Date(2000, 02, 05, 4, 4, 4, 0, time.UTC)),
   191  		), `{
   192  			"val": "2000-02-05T04:04:04Z"
   193  		}`)
   194  	})
   195  
   196  	t.Run("complex", func(t *testing.T) {
   197  		t.Parallel()
   198  
   199  		test(t, slog.M(
   200  			slog.F("val", complex(10, 10)),
   201  		), `{
   202  			"val": "(10+10i)"
   203  		}`)
   204  	})
   205  
   206  	t.Run("privateStruct", func(t *testing.T) {
   207  		t.Parallel()
   208  
   209  		test(t, slog.M(
   210  			slog.F("val", struct {
   211  				meow string
   212  				bar  int
   213  				far  uint
   214  			}{
   215  				meow: "hi",
   216  				bar:  23,
   217  				far:  600,
   218  			}),
   219  		), `{
   220  			"val": "{meow:hi bar:23 far:600}"
   221  		}`)
   222  	})
   223  }
   224  
   225  type meow struct {
   226  	a int
   227  }
   228  
   229  func indentJSON(t *testing.T, j string) string {
   230  	b := &bytes.Buffer{}
   231  	err := json.Indent(b, []byte(j), "", strings.Repeat(" ", 4))
   232  	assert.Success(t, "indent JSON", err)
   233  
   234  	return b.String()
   235  }
   236  
   237  func marshalJSON(t *testing.T, m slog.Map) string {
   238  	actb, err := json.Marshal(m)
   239  	assert.Success(t, "marshal map to JSON", err)
   240  	return indentJSON(t, string(actb))
   241  }
   242  
   243  type complexJSON complex128
   244  
   245  func (c complexJSON) MarshalJSON() ([]byte, error) {
   246  	return json.Marshal(complex128(c))
   247  }
   248  

View as plain text