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