@@ -27,6 +27,7 @@ import (
27
27
"github.com/go-logr/logr"
28
28
)
29
29
30
+ // Will be handled via reflection instead of type assertions.
30
31
type substr string
31
32
32
33
func ptrint (i int ) * int {
@@ -36,6 +37,20 @@ func ptrstr(s string) *string {
36
37
return & s
37
38
}
38
39
40
+ // point implements encoding.TextMarshaler and can be used as a map key.
41
+ type point struct { x , y int }
42
+
43
+ func (p point ) MarshalText () ([]byte , error ) {
44
+ return []byte (fmt .Sprintf ("(%d, %d)" , p .x , p .y )), nil
45
+ }
46
+
47
+ // pointErr implements encoding.TextMarshaler but returns an error.
48
+ type pointErr struct { x , y int }
49
+
50
+ func (p pointErr ) MarshalText () ([]byte , error ) {
51
+ return nil , fmt .Errorf ("uh oh: %d, %d" , p .x , p .y )
52
+ }
53
+
39
54
// Logging this should result in the MarshalLog() value.
40
55
type Tmarshaler string
41
56
@@ -198,7 +213,9 @@ func TestPretty(t *testing.T) {
198
213
exp string // used in cases where JSON can't handle it
199
214
}{
200
215
{val : "strval" },
216
+ {val : "strval\n with\t \" escapes\" " },
201
217
{val : substr ("substrval" )},
218
+ {val : substr ("substrval\n with\t \" escapes\" " )},
202
219
{val : true },
203
220
{val : false },
204
221
{val : int (93 )},
@@ -235,7 +252,11 @@ func TestPretty(t *testing.T) {
235
252
exp : `[]` ,
236
253
},
237
254
{val : []int {9 , 3 , 7 , 6 }},
255
+ {val : []string {"str" , "with\t escape" }},
256
+ {val : []substr {"substr" , "with\t escape" }},
238
257
{val : [4 ]int {9 , 3 , 7 , 6 }},
258
+ {val : [2 ]string {"str" , "with\t escape" }},
259
+ {val : [2 ]substr {"substr" , "with\t escape" }},
239
260
{
240
261
val : struct {
241
262
Int int
@@ -255,11 +276,43 @@ func TestPretty(t *testing.T) {
255
276
"nine" : 3 ,
256
277
},
257
278
},
279
+ {
280
+ val : map [string ]int {
281
+ "with\t escape" : 76 ,
282
+ },
283
+ },
258
284
{
259
285
val : map [substr ]int {
260
286
"nine" : 3 ,
261
287
},
262
288
},
289
+ {
290
+ val : map [substr ]int {
291
+ "with\t escape" : 76 ,
292
+ },
293
+ },
294
+ {
295
+ val : map [int ]int {
296
+ 9 : 3 ,
297
+ },
298
+ },
299
+ {
300
+ val : map [float64 ]int {
301
+ 9.5 : 3 ,
302
+ },
303
+ exp : `{"9.5":3}` ,
304
+ },
305
+ {
306
+ val : map [point ]int {
307
+ {x : 1 , y : 2 }: 3 ,
308
+ },
309
+ },
310
+ {
311
+ val : map [pointErr ]int {
312
+ {x : 1 , y : 2 }: 3 ,
313
+ },
314
+ exp : `{"<error-MarshalText: uh oh: 1, 2>":3}` ,
315
+ },
263
316
{
264
317
val : struct {
265
318
X int `json:"x"`
@@ -283,6 +336,7 @@ func TestPretty(t *testing.T) {
283
336
val : []struct { X , Y string }{
284
337
{"nine" , "three" },
285
338
{"seven" , "six" },
339
+ {"with\t " , "\t escapes" },
286
340
},
287
341
},
288
342
{
@@ -438,6 +492,24 @@ func TestPretty(t *testing.T) {
438
492
val : PseudoStruct (makeKV ("f1" , 1 , "f2" , true , "f3" , []int {})),
439
493
exp : `{"f1":1,"f2":true,"f3":[]}` ,
440
494
},
495
+ {
496
+ val : map [TjsontagsString ]int {
497
+ {String1 : `"quoted"` , String4 : `unquoted` }: 1 ,
498
+ },
499
+ exp : `{"{\"string1\":\"\\\"quoted\\\"\",\"-\":\"\",\"string4\":\"unquoted\",\"String5\":\"\"}":1}` ,
500
+ },
501
+ {
502
+ val : map [TjsontagsInt ]int {
503
+ {Int1 : 1 , Int2 : 2 }: 3 ,
504
+ },
505
+ exp : `{"{\"int1\":1,\"-\":0,\"Int5\":0}":3}` ,
506
+ },
507
+ {
508
+ val : map [[2 ]struct { S string }]int {
509
+ {{S : `"quoted"` }, {S : "unquoted" }}: 1 ,
510
+ },
511
+ exp : `{"[{\"S\":\"\\\"quoted\\\"\"},{\"S\":\"unquoted\"}]":1}` ,
512
+ },
441
513
}
442
514
443
515
f := NewFormatter (Options {})
@@ -449,7 +521,7 @@ func TestPretty(t *testing.T) {
449
521
} else {
450
522
jb , err := json .Marshal (tc .val )
451
523
if err != nil {
452
- t .Errorf ("[%d]: unexpected error: %v" , i , err )
524
+ t .Fatalf ("[%d]: unexpected error: %v\n got: %q " , i , err , ours )
453
525
}
454
526
want = string (jb )
455
527
}
@@ -496,6 +568,13 @@ func TestRender(t *testing.T) {
496
568
args : makeKV ("bool" , PseudoStruct (makeKV ("boolsub" , true ))),
497
569
expectKV : `"int"={"intsub":1} "str"={"strsub":"2"} "bool"={"boolsub":true}` ,
498
570
expectJSON : `{"int":{"intsub":1},"str":{"strsub":"2"},"bool":{"boolsub":true}}` ,
571
+ }, {
572
+ name : "escapes" ,
573
+ builtins : makeKV ("\" 1\" " , 1 ), // will not be escaped, but should never happen
574
+ values : makeKV ("\t str" , "ABC" ), // escaped
575
+ args : makeKV ("bool\n " , true ), // escaped
576
+ expectKV : `""1""=1 "\tstr"="ABC" "bool\n"=true` ,
577
+ expectJSON : `{""1"":1,"\tstr":"ABC","bool\n":true}` ,
499
578
}, {
500
579
name : "missing value" ,
501
580
builtins : makeKV ("builtin" ),
@@ -505,27 +584,27 @@ func TestRender(t *testing.T) {
505
584
expectJSON : `{"builtin":"<no-value>","value":"<no-value>","arg":"<no-value>"}` ,
506
585
}, {
507
586
name : "non-string key int" ,
508
- args : makeKV (123 , "val" ),
587
+ builtins : makeKV (123 , "val" ), // should never happen
509
588
values : makeKV (456 , "val" ),
510
- builtins : makeKV (789 , "val" ),
511
- expectKV : `"<non-string-key: 789 >"="val" "<non-string-key: 456>"="val" "<non-string-key: 123 >"="val"` ,
512
- expectJSON : `{"<non-string-key: 789 >":"val","<non-string-key: 456>":"val","<non-string-key: 123 >":"val"}` ,
589
+ args : makeKV (789 , "val" ),
590
+ expectKV : `"<non-string-key: 123 >"="val" "<non-string-key: 456>"="val" "<non-string-key: 789 >"="val"` ,
591
+ expectJSON : `{"<non-string-key: 123 >":"val","<non-string-key: 456>":"val","<non-string-key: 789 >":"val"}` ,
513
592
}, {
514
593
name : "non-string key struct" ,
515
- args : makeKV (struct {
594
+ builtins : makeKV (struct { // will not be escaped, but should never happen
516
595
F1 string
517
596
F2 int
518
- }{"arg " , 123 }, "val" ),
597
+ }{"builtin " , 123 }, "val" ),
519
598
values : makeKV (struct {
520
599
F1 string
521
600
F2 int
522
601
}{"value" , 456 }, "val" ),
523
- builtins : makeKV (struct {
602
+ args : makeKV (struct {
524
603
F1 string
525
604
F2 int
526
- }{"builtin " , 789 }, "val" ),
527
- expectKV : `"<non-string-key: {"F1":"builtin",>"="val" "<non-string-key: {"F1": "value", "F>"="val" "<non-string-key: {"F1": "arg", "F2">"="val"` ,
528
- expectJSON : `{"<non-string-key: {"F1":"builtin",>":"val","<non-string-key: {"F1": "value", "F>":"val","<non-string-key: {"F1": "arg", "F2">":"val"}` ,
605
+ }{"arg " , 789 }, "val" ),
606
+ expectKV : `"<non-string-key: {"F1":"builtin",>"="val" "<non-string-key: {\ "F1\":\ "value\",\ "F>"="val" "<non-string-key: {\ "F1\":\ "arg\",\ "F2\ ">"="val"` ,
607
+ expectJSON : `{"<non-string-key: {"F1":"builtin",>":"val","<non-string-key: {\ "F1\":\ "value\",\ "F>":"val","<non-string-key: {\ "F1\":\ "arg\",\ "F2\ ">":"val"}` ,
529
608
}}
530
609
531
610
for _ , tc := range testCases {
@@ -534,7 +613,7 @@ func TestRender(t *testing.T) {
534
613
formatter .AddValues (tc .values )
535
614
r := formatter .render (tc .builtins , tc .args )
536
615
if r != expect {
537
- t .Errorf ("wrong output:\n expected %q \n got %q " , expect , r )
616
+ t .Errorf ("wrong output:\n expected %v \n got %v " , expect , r )
538
617
}
539
618
}
540
619
t .Run ("KV" , func (t * testing.T ) {
0 commit comments