@@ -83,11 +83,22 @@ func TestJSONEscaping(t *testing.T) {
83
83
"\xed \xa0 \x80 " : `\ufffd\ufffd\ufffd` ,
84
84
"foo\xed \xa0 \x80 " : `foo\ufffd\ufffd\ufffd` ,
85
85
}
86
- for input , output := range cases {
87
- enc .truncate ()
88
- enc .safeAddString (input )
89
- assertJSON (t , output , enc )
90
- }
86
+
87
+ t .Run ("String" , func (t * testing.T ) {
88
+ for input , output := range cases {
89
+ enc .truncate ()
90
+ enc .safeAddString (input )
91
+ assertJSON (t , output , enc )
92
+ }
93
+ })
94
+
95
+ t .Run ("ByteString" , func (t * testing.T ) {
96
+ for input , output := range cases {
97
+ enc .truncate ()
98
+ enc .safeAddByteString ([]byte (input ))
99
+ assertJSON (t , output , enc )
100
+ }
101
+ })
91
102
}
92
103
93
104
func TestJSONEncoderObjectFields (t * testing.T ) {
@@ -100,6 +111,10 @@ func TestJSONEncoderObjectFields(t *testing.T) {
100
111
{"bool" , `"k\\":true` , func (e Encoder ) { e .AddBool (`k\` , true ) }}, // test key escaping once
101
112
{"bool" , `"k":true` , func (e Encoder ) { e .AddBool ("k" , true ) }},
102
113
{"bool" , `"k":false` , func (e Encoder ) { e .AddBool ("k" , false ) }},
114
+ {"byteString" , `"k":"v\\"` , func (e Encoder ) { e .AddByteString (`k` , []byte (`v\` )) }},
115
+ {"byteString" , `"k":"v"` , func (e Encoder ) { e .AddByteString ("k" , []byte ("v" )) }},
116
+ {"byteString" , `"k":""` , func (e Encoder ) { e .AddByteString ("k" , []byte {}) }},
117
+ {"byteString" , `"k":""` , func (e Encoder ) { e .AddByteString ("k" , nil ) }},
103
118
{"complex128" , `"k":"1+2i"` , func (e Encoder ) { e .AddComplex128 ("k" , 1 + 2i ) }},
104
119
{"complex64" , `"k":"1+2i"` , func (e Encoder ) { e .AddComplex64 ("k" , 1 + 2i ) }},
105
120
{"duration" , `"k":0.000000001` , func (e Encoder ) { e .AddDuration ("k" , 1 ) }},
@@ -219,6 +234,8 @@ func TestJSONEncoderArrays(t *testing.T) {
219
234
f func (ArrayEncoder )
220
235
}{
221
236
{"bool" , `[true,true]` , func (e ArrayEncoder ) { e .AppendBool (true ) }},
237
+ {"byteString" , `["k","k"]` , func (e ArrayEncoder ) { e .AppendByteString ([]byte ("k" )) }},
238
+ {"byteString" , `["k\\","k\\"]` , func (e ArrayEncoder ) { e .AppendByteString ([]byte (`k\` )) }},
222
239
{"complex128" , `["1+2i","1+2i"]` , func (e ArrayEncoder ) { e .AppendComplex128 (1 + 2i ) }},
223
240
{"complex64" , `["1+2i","1+2i"]` , func (e ArrayEncoder ) { e .AppendComplex64 (1 + 2i ) }},
224
241
{"durations" , `[0.000000002,0.000000002]` , func (e ArrayEncoder ) { e .AppendDuration (2 ) }},
@@ -385,22 +402,24 @@ func (nj noJSON) MarshalJSON() ([]byte, error) {
385
402
return nil , errors .New ("no" )
386
403
}
387
404
388
- func zapEncodeString (s string ) []byte {
389
- enc := & jsonEncoder {buf : bufferpool .Get ()}
390
- // Escape and quote a string using our encoder.
391
- var ret []byte
392
- enc .safeAddString (s )
393
- ret = make ([]byte , 0 , enc .buf .Len ()+ 2 )
394
- ret = append (ret , '"' )
395
- ret = append (ret , enc .buf .Bytes ()... )
396
- ret = append (ret , '"' )
397
- return ret
405
+ func zapEncode (encode func (* jsonEncoder , string )) func (s string ) []byte {
406
+ return func (s string ) []byte {
407
+ enc := & jsonEncoder {buf : bufferpool .Get ()}
408
+ // Escape and quote a string using our encoder.
409
+ var ret []byte
410
+ encode (enc , s )
411
+ ret = make ([]byte , 0 , enc .buf .Len ()+ 2 )
412
+ ret = append (ret , '"' )
413
+ ret = append (ret , enc .buf .Bytes ()... )
414
+ ret = append (ret , '"' )
415
+ return ret
416
+ }
398
417
}
399
418
400
- func roundTripsCorrectly (original string ) bool {
419
+ func roundTripsCorrectly (encode func ( string ) [] byte , original string ) bool {
401
420
// Encode using our encoder, decode using the standard library, and assert
402
421
// that we haven't lost any information.
403
- encoded := zapEncodeString (original )
422
+ encoded := encode (original )
404
423
405
424
var decoded string
406
425
err := json .Unmarshal (encoded , & decoded )
@@ -410,6 +429,18 @@ func roundTripsCorrectly(original string) bool {
410
429
return original == decoded
411
430
}
412
431
432
+ func roundTripsCorrectlyString (original string ) bool {
433
+ return roundTripsCorrectly (zapEncode ((* jsonEncoder ).safeAddString ), original )
434
+ }
435
+
436
+ func roundTripsCorrectlyByteString (original string ) bool {
437
+ return roundTripsCorrectly (
438
+ zapEncode (func (enc * jsonEncoder , s string ) {
439
+ enc .safeAddByteString ([]byte (s ))
440
+ }),
441
+ original )
442
+ }
443
+
413
444
type ASCII string
414
445
415
446
func (s ASCII ) Generate (r * rand.Rand , size int ) reflect.Value {
@@ -421,20 +452,24 @@ func (s ASCII) Generate(r *rand.Rand, size int) reflect.Value {
421
452
return reflect .ValueOf (a )
422
453
}
423
454
424
- func asciiRoundTripsCorrectly (s ASCII ) bool {
425
- return roundTripsCorrectly (string (s ))
455
+ func asciiRoundTripsCorrectlyString (s ASCII ) bool {
456
+ return roundTripsCorrectlyString (string (s ))
457
+ }
458
+
459
+ func asciiRoundTripsCorrectlyByteString (s ASCII ) bool {
460
+ return roundTripsCorrectlyByteString (string (s ))
426
461
}
427
462
428
463
func TestJSONQuick (t * testing.T ) {
429
- // Test the full range of UTF-8 strings.
430
- err := quick .Check (roundTripsCorrectly , & quick.Config {MaxCountScale : 100.0 })
431
- if err != nil {
432
- t .Error (err .Error ())
464
+ check := func (f interface {}) {
465
+ err := quick .Check (f , & quick.Config {MaxCountScale : 100.0 })
466
+ assert .NoError (t , err )
433
467
}
468
+ // Test the full range of UTF-8 strings.
469
+ check (roundTripsCorrectlyString )
470
+ check (roundTripsCorrectlyByteString )
434
471
435
472
// Focus on ASCII strings.
436
- err = quick .Check (asciiRoundTripsCorrectly , & quick.Config {MaxCountScale : 100.0 })
437
- if err != nil {
438
- t .Error (err .Error ())
439
- }
473
+ check (asciiRoundTripsCorrectlyString )
474
+ check (asciiRoundTripsCorrectlyByteString )
440
475
}
0 commit comments