github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/encode_test.go (about) 1 // +build amd64,go1.16,!go1.23 2 3 /* 4 * Copyright 2021 ByteDance Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package sonic 20 21 import ( 22 `bytes` 23 `encoding` 24 `encoding/json` 25 `fmt` 26 `log` 27 `math` 28 `os` 29 `reflect` 30 `regexp` 31 `runtime` 32 `runtime/debug` 33 `strconv` 34 `testing` 35 `time` 36 `unsafe` 37 `strings` 38 39 `github.com/bytedance/sonic/encoder` 40 `github.com/stretchr/testify/assert` 41 ) 42 43 var ( 44 debugAsyncGC = os.Getenv("SONIC_NO_ASYNC_GC") == "" 45 ) 46 func TestMain(m *testing.M) { 47 go func () { 48 if !debugAsyncGC { 49 return 50 } 51 println("Begin GC looping...") 52 for { 53 runtime.GC() 54 debug.FreeOSMemory() 55 } 56 }() 57 time.Sleep(time.Millisecond) 58 m.Run() 59 } 60 61 type Optionals struct { 62 Sr string `json:"sr"` 63 So string `json:"so,omitempty"` 64 Sw string `json:"-"` 65 66 Ir int `json:"omitempty"` // actually named omitempty, not an option 67 Io int `json:"io,omitempty"` 68 69 Slr []string `json:"slr,random"` 70 Slo []string `json:"slo,omitempty"` 71 72 Mr map[string]interface{} `json:"mr"` 73 Mo map[string]interface{} `json:",omitempty"` 74 75 Fr float64 `json:"fr"` 76 Fo float64 `json:"fo,omitempty"` 77 78 Br bool `json:"br"` 79 Bo bool `json:"bo,omitempty"` 80 81 Ur uint `json:"ur"` 82 Uo uint `json:"uo,omitempty"` 83 84 Str struct{} `json:"str"` 85 Sto struct{} `json:"sto,omitempty"` 86 } 87 88 var optionalsExpected = `{ 89 "sr": "", 90 "omitempty": 0, 91 "slr": null, 92 "mr": {}, 93 "fr": 0, 94 "br": false, 95 "ur": 0, 96 "str": {}, 97 "sto": {} 98 }` 99 100 func TestOmitEmpty(t *testing.T) { 101 var o Optionals 102 o.Sw = "something" 103 o.Mr = map[string]interface{}{} 104 o.Mo = map[string]interface{}{} 105 106 got, err := encoder.EncodeIndented(&o, "", " ", 0) 107 if err != nil { 108 t.Fatal(err) 109 } 110 if got := string(got); got != optionalsExpected { 111 t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected) 112 } 113 } 114 115 type StringTag struct { 116 BoolStr bool `json:",string"` 117 IntStr int64 `json:",string"` 118 UintptrStr uintptr `json:",string"` 119 StrStr string `json:",string"` 120 NumberStr json.Number `json:",string"` 121 } 122 123 func TestRoundtripStringTag(t *testing.T) { 124 tests := []struct { 125 name string 126 in StringTag 127 want string // empty to just test that we roundtrip 128 }{ 129 { 130 name: "AllTypes", 131 in: StringTag{ 132 BoolStr: true, 133 IntStr: 42, 134 UintptrStr: 44, 135 StrStr: "xzbit", 136 NumberStr: "46", 137 }, 138 want: `{ 139 "BoolStr": "true", 140 "IntStr": "42", 141 "UintptrStr": "44", 142 "StrStr": "\"xzbit\"", 143 "NumberStr": "46" 144 }`, 145 }, 146 { 147 // See golang.org/issues/38173. 148 name: "StringDoubleEscapes", 149 in: StringTag{ 150 StrStr: "\b\f\n\r\t\"\\", 151 NumberStr: "0", // just to satisfy the roundtrip 152 }, 153 want: `{ 154 "BoolStr": "false", 155 "IntStr": "0", 156 "UintptrStr": "0", 157 "StrStr": "\"\\u0008\\u000c\\n\\r\\t\\\"\\\\\"", 158 "NumberStr": "0" 159 }`, 160 }, 161 } 162 for _, test := range tests { 163 t.Run(test.name, func(t *testing.T) { 164 // Indent with a tab prefix to make the multi-line string 165 // literals in the table nicer to read. 166 got, err := encoder.EncodeIndented(&test.in, " ", " ", 0) 167 if err != nil { 168 t.Fatal(err) 169 } 170 if got := string(got); got != test.want { 171 t.Fatalf(" got: %s\nwant: %s\n", got, test.want) 172 } 173 174 // Verify that it round-trips. 175 var s2 StringTag 176 if err := Unmarshal(got, &s2); err != nil { 177 t.Fatalf("Decode: %v", err) 178 } 179 if !reflect.DeepEqual(test.in, s2) { 180 t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", test.in, string(got), s2) 181 } 182 }) 183 } 184 } 185 186 // byte slices are special even if they're renamed types. 187 type renamedByte byte 188 type renamedByteSlice []byte 189 type renamedRenamedByteSlice []renamedByte 190 191 func TestEncodeRenamedByteSlice(t *testing.T) { 192 s := renamedByteSlice("abc") 193 result, err := Marshal(s) 194 if err != nil { 195 t.Fatal(err) 196 } 197 expect := `"YWJj"` 198 if string(result) != expect { 199 t.Errorf(" got %s want %s", result, expect) 200 } 201 r := renamedRenamedByteSlice("abc") 202 result, err = Marshal(r) 203 if err != nil { 204 t.Fatal(err) 205 } 206 if string(result) != expect { 207 t.Errorf(" got %s want %s", result, expect) 208 } 209 } 210 211 type SamePointerNoCycle struct { 212 Ptr1, Ptr2 *SamePointerNoCycle 213 } 214 215 var samePointerNoCycle = &SamePointerNoCycle{} 216 217 type PointerCycle struct { 218 Ptr *PointerCycle 219 } 220 221 var pointerCycle = &PointerCycle{} 222 223 type PointerCycleIndirect struct { 224 Ptrs []interface{} 225 } 226 227 type RecursiveSlice []RecursiveSlice 228 229 var ( 230 pointerCycleIndirect = &PointerCycleIndirect{} 231 mapCycle = make(map[string]interface{}) 232 sliceCycle = []interface{}{nil} 233 sliceNoCycle = []interface{}{nil, nil} 234 recursiveSliceCycle = []RecursiveSlice{nil} 235 ) 236 237 func init() { 238 ptr := &SamePointerNoCycle{} 239 samePointerNoCycle.Ptr1 = ptr 240 samePointerNoCycle.Ptr2 = ptr 241 242 pointerCycle.Ptr = pointerCycle 243 pointerCycleIndirect.Ptrs = []interface{}{pointerCycleIndirect} 244 245 mapCycle["x"] = mapCycle 246 sliceCycle[0] = sliceCycle 247 sliceNoCycle[1] = sliceNoCycle[:1] 248 for i := 3; i > 0; i-- { 249 sliceNoCycle = []interface{}{sliceNoCycle} 250 } 251 recursiveSliceCycle[0] = recursiveSliceCycle 252 } 253 254 func TestSamePointerNoCycle(t *testing.T) { 255 if _, err := Marshal(samePointerNoCycle); err != nil { 256 t.Fatalf("unexpected error: %v", err) 257 } 258 } 259 260 func TestSliceNoCycle(t *testing.T) { 261 if _, err := Marshal(sliceNoCycle); err != nil { 262 t.Fatalf("unexpected error: %v", err) 263 } 264 } 265 266 var unsupportedValues = []interface{}{ 267 math.NaN(), 268 math.Inf(-1), 269 math.Inf(1), 270 pointerCycle, 271 pointerCycleIndirect, 272 mapCycle, 273 sliceCycle, 274 recursiveSliceCycle, 275 } 276 277 func TestUnsupportedValues(t *testing.T) { 278 for _, v := range unsupportedValues { 279 if _, err := Marshal(v); err != nil { 280 if _, ok := err.(*json.UnsupportedValueError); !ok { 281 t.Errorf("for %v, got %T want UnsupportedValueError", v, err) 282 } 283 } else { 284 t.Errorf("for %v, expected error", v) 285 } 286 } 287 } 288 289 // Ref has Marshaler and Unmarshaler methods with pointer receiver. 290 type Ref int 291 292 func (*Ref) MarshalJSON() ([]byte, error) { 293 return []byte(`"ref"`), nil 294 } 295 296 func (r *Ref) UnmarshalJSON([]byte) error { 297 *r = 12 298 return nil 299 } 300 301 // Val has Marshaler methods with value receiver. 302 type Val int 303 304 func (Val) MarshalJSON() ([]byte, error) { 305 return []byte(`"val"`), nil 306 } 307 308 // RefText has Marshaler and Unmarshaler methods with pointer receiver. 309 type RefText int 310 311 func (*RefText) MarshalText() ([]byte, error) { 312 return []byte(`"ref"`), nil 313 } 314 315 func (r *RefText) UnmarshalText([]byte) error { 316 *r = 13 317 return nil 318 } 319 320 // ValText has Marshaler methods with value receiver. 321 type ValText int 322 323 func (ValText) MarshalText() ([]byte, error) { 324 return []byte(`"val"`), nil 325 } 326 327 func TestRefValMarshal(t *testing.T) { 328 var s = struct { 329 R0 Ref 330 R1 *Ref 331 R2 RefText 332 R3 *RefText 333 V0 Val 334 V1 *Val 335 V2 ValText 336 V3 *ValText 337 }{ 338 R0: 12, 339 R1: new(Ref), 340 R2: 14, 341 R3: new(RefText), 342 V0: 13, 343 V1: new(Val), 344 V2: 15, 345 V3: new(ValText), 346 } 347 const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}` 348 b, err := Marshal(&s) 349 if err != nil { 350 t.Fatalf("Marshal: %v", err) 351 } 352 if got := string(b); got != want { 353 t.Errorf("got %q, want %q", got, want) 354 } 355 } 356 357 /* 358 FIXME: disabling these test cases for now, because Sonic does not implement HTML escape 359 I don't think there are real usages of the `HTMLEscape` feature in real code 360 361 // C implements Marshaler and returns unescaped JSON. 362 type C int 363 364 func (C) MarshalJSON() ([]byte, error) { 365 return []byte(`"<&>"`), nil 366 } 367 368 // CText implements Marshaler and returns unescaped text. 369 type CText int 370 371 func (CText) MarshalText() ([]byte, error) { 372 return []byte(`"<&>"`), nil 373 } 374 375 func TestMarshalerEscaping(t *testing.T) { 376 var c C 377 want := `"\u003c\u0026\u003e"` 378 b, err := Marshal(c) 379 if err != nil { 380 t.Fatalf("Marshal(c): %v", err) 381 } 382 if got := string(b); got != want { 383 t.Errorf("Marshal(c) = %#q, want %#q", got, want) 384 } 385 386 var ct CText 387 want = `"\"\u003c\u0026\u003e\""` 388 b, err = Marshal(ct) 389 if err != nil { 390 t.Fatalf("Marshal(ct): %v", err) 391 } 392 if got := string(b); got != want { 393 t.Errorf("Marshal(ct) = %#q, want %#q", got, want) 394 } 395 } 396 */ 397 398 func TestAnonymousFields(t *testing.T) { 399 tests := []struct { 400 label string // Test name 401 makeInput func() interface{} // Function to create input value 402 want string // Expected JSON output 403 }{{ 404 // Both S1 and S2 have a field named X. From the perspective of S, 405 // it is ambiguous which one X refers to. 406 // This should not serialize either field. 407 label: "AmbiguousField", 408 makeInput: func() interface{} { 409 type ( 410 S1 struct{ x, X int } 411 S2 struct{ x, X int } 412 S struct { 413 S1 414 S2 415 } 416 ) 417 return S{S1{1, 2}, S2{3, 4}} 418 }, 419 want: `{}`, 420 }, { 421 label: "DominantField", 422 // Both S1 and S2 have a field named X, but since S has an X field as 423 // well, it takes precedence over S1.X and S2.X. 424 makeInput: func() interface{} { 425 type ( 426 S1 struct{ x, X int } 427 S2 struct{ x, X int } 428 S struct { 429 S1 430 S2 431 x, X int 432 } 433 ) 434 return S{S1{1, 2}, S2{3, 4}, 5, 6} 435 }, 436 want: `{"X":6}`, 437 }, { 438 // Unexported embedded field of non-struct type should not be serialized. 439 label: "UnexportedEmbeddedInt", 440 makeInput: func() interface{} { 441 type ( 442 myInt int 443 S struct{ myInt } 444 ) 445 return S{5} 446 }, 447 want: `{}`, 448 }, { 449 // Exported embedded field of non-struct type should be serialized. 450 label: "ExportedEmbeddedInt", 451 makeInput: func() interface{} { 452 type ( 453 MyInt int 454 S struct{ MyInt } 455 ) 456 return S{5} 457 }, 458 want: `{"MyInt":5}`, 459 }, { 460 // Unexported embedded field of pointer to non-struct type 461 // should not be serialized. 462 label: "UnexportedEmbeddedIntPointer", 463 makeInput: func() interface{} { 464 type ( 465 myInt int 466 S struct{ *myInt } 467 ) 468 s := S{new(myInt)} 469 *s.myInt = 5 470 return s 471 }, 472 want: `{}`, 473 }, { 474 // Exported embedded field of pointer to non-struct type 475 // should be serialized. 476 label: "ExportedEmbeddedIntPointer", 477 makeInput: func() interface{} { 478 type ( 479 MyInt int 480 S struct{ *MyInt } 481 ) 482 s := S{new(MyInt)} 483 *s.MyInt = 5 484 return s 485 }, 486 want: `{"MyInt":5}`, 487 }, { 488 // Exported fields of embedded structs should have their 489 // exported fields be serialized regardless of whether the struct types 490 // themselves are exported. 491 label: "EmbeddedStruct", 492 makeInput: func() interface{} { 493 type ( 494 s1 struct{ x, X int } 495 S2 struct{ y, Y int } 496 S struct { 497 s1 498 S2 499 } 500 ) 501 return S{s1{1, 2}, S2{3, 4}} 502 }, 503 want: `{"X":2,"Y":4}`, 504 }, { 505 // Exported fields of pointers to embedded structs should have their 506 // exported fields be serialized regardless of whether the struct types 507 // themselves are exported. 508 label: "EmbeddedStructPointer", 509 makeInput: func() interface{} { 510 type ( 511 s1 struct{ x, X int } 512 S2 struct{ y, Y int } 513 S struct { 514 *s1 515 *S2 516 } 517 ) 518 return S{&s1{1, 2}, &S2{3, 4}} 519 }, 520 want: `{"X":2,"Y":4}`, 521 }, { 522 // Exported fields on embedded unexported structs at multiple levels 523 // of nesting should still be serialized. 524 label: "NestedStructAndInts", 525 makeInput: func() interface{} { 526 type ( 527 MyInt1 int 528 MyInt2 int 529 myInt int 530 s2 struct { 531 MyInt2 532 myInt 533 } 534 s1 struct { 535 MyInt1 536 myInt 537 s2 538 } 539 S struct { 540 s1 541 myInt 542 } 543 ) 544 return S{s1{1, 2, s2{3, 4}}, 6} 545 }, 546 want: `{"MyInt1":1,"MyInt2":3}`, 547 }, { 548 // If an anonymous struct pointer field is nil, we should ignore 549 // the embedded fields behind it. Not properly doing so may 550 // result in the wrong output or reflect panics. 551 label: "EmbeddedFieldBehindNilPointer", 552 makeInput: func() interface{} { 553 type ( 554 S2 struct{ Field string } 555 S struct{ *S2 } 556 ) 557 return S{} 558 }, 559 want: `{}`, 560 }} 561 562 for _, tt := range tests { 563 t.Run(tt.label, func(t *testing.T) { 564 b, err := Marshal(tt.makeInput()) 565 if err != nil { 566 t.Fatalf("Marshal() = %v, want nil error", err) 567 } 568 if string(b) != tt.want { 569 t.Fatalf("Marshal() = %q, want %q", b, tt.want) 570 } 571 }) 572 } 573 } 574 575 type BugA struct { 576 S string 577 } 578 579 type BugB struct { 580 BugA 581 S string 582 } 583 584 type BugC struct { 585 S string 586 } 587 588 // Legal Go: We never use the repeated embedded field (S). 589 type BugX struct { 590 A int 591 BugA 592 BugB 593 } 594 595 // golang.org/issue/16042. 596 // Even if a nil interface value is passed in, as long as 597 // it implements Marshaler, it should be marshaled. 598 type nilJSONMarshaler string 599 600 func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) { 601 if nm == nil { 602 return Marshal("0zenil0") 603 } 604 return Marshal("zenil:" + string(*nm)) 605 } 606 607 // golang.org/issue/34235. 608 // Even if a nil interface value is passed in, as long as 609 // it implements encoding.TextMarshaler, it should be marshaled. 610 type nilTextMarshaler string 611 612 func (nm *nilTextMarshaler) MarshalText() ([]byte, error) { 613 if nm == nil { 614 return []byte("0zenil0"), nil 615 } 616 return []byte("zenil:" + string(*nm)), nil 617 } 618 619 // See golang.org/issue/16042 and golang.org/issue/34235. 620 func TestNilMarshal(t *testing.T) { 621 testCases := []struct { 622 v interface{} 623 want string 624 }{ 625 {v: nil, want: `null`}, 626 {v: new(float64), want: `0`}, 627 {v: []interface{}(nil), want: `null`}, 628 {v: []string(nil), want: `null`}, 629 {v: map[string]string(nil), want: `null`}, 630 {v: []byte(nil), want: `null`}, 631 {v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`}, 632 {v: struct{ M json.Marshaler }{}, want: `{"M":null}`}, 633 {v: struct{ M json.Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, 634 {v: struct{ M interface{} }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`}, 635 {v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`}, 636 {v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`}, 637 {v: struct{ M interface{} }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`}, 638 } 639 640 for _, tt := range testCases { 641 out, err := Marshal(tt.v) 642 if err != nil || string(out) != tt.want { 643 t.Errorf("Marshal(%#v) = %#q, %#v, want %#q, nil", tt.v, out, err, tt.want) 644 continue 645 } 646 } 647 } 648 649 // Issue 5245. 650 func TestEmbeddedBug(t *testing.T) { 651 v := BugB{ 652 BugA{"A"}, 653 "B", 654 } 655 b, err := Marshal(v) 656 if err != nil { 657 t.Fatal("Marshal:", err) 658 } 659 want := `{"S":"B"}` 660 got := string(b) 661 if got != want { 662 t.Fatalf("Marshal: got %s want %s", got, want) 663 } 664 // Now check that the duplicate field, S, does not appear. 665 x := BugX{ 666 A: 23, 667 } 668 b, err = Marshal(x) 669 if err != nil { 670 t.Fatal("Marshal:", err) 671 } 672 want = `{"A":23}` 673 got = string(b) 674 if got != want { 675 t.Fatalf("Marshal: got %s want %s", got, want) 676 } 677 } 678 679 type BugD struct { // Same as BugA after tagging. 680 XXX string `json:"S"` 681 } 682 683 // BugD's tagged S field should dominate BugA's. 684 type BugY struct { 685 BugA 686 BugD 687 } 688 689 // Test that a field with a tag dominates untagged fields. 690 func TestTaggedFieldDominates(t *testing.T) { 691 v := BugY{ 692 BugA{"BugA"}, 693 BugD{"BugD"}, 694 } 695 b, err := Marshal(v) 696 if err != nil { 697 t.Fatal("Marshal:", err) 698 } 699 want := `{"S":"BugD"}` 700 got := string(b) 701 if got != want { 702 t.Fatalf("Marshal: got %s want %s", got, want) 703 } 704 } 705 706 // There are no tags here, so S should not appear. 707 type BugZ struct { 708 BugA 709 BugC 710 BugY // Contains a tagged S field through BugD; should not dominate. 711 } 712 713 func TestDuplicatedFieldDisappears(t *testing.T) { 714 v := BugZ{ 715 BugA{"BugA"}, 716 BugC{"BugC"}, 717 BugY{ 718 BugA{"nested BugA"}, 719 BugD{"nested BugD"}, 720 }, 721 } 722 b, err := Marshal(v) 723 if err != nil { 724 t.Fatal("Marshal:", err) 725 } 726 want := `{}` 727 got := string(b) 728 if got != want { 729 t.Fatalf("Marshal: got %s want %s", got, want) 730 } 731 } 732 733 func TestStdLibIssue10281(t *testing.T) { 734 type Foo struct { 735 N json.Number 736 } 737 x := Foo{json.Number(`invalid`)} 738 739 b, err := Marshal(&x) 740 if err == nil { 741 t.Errorf("Marshal(&x) = %#q; want error", b) 742 } 743 } 744 745 // golang.org/issue/8582 746 func TestEncodePointerString(t *testing.T) { 747 type stringPointer struct { 748 N *int64 `json:"n,string"` 749 } 750 var n int64 = 42 751 b, err := Marshal(stringPointer{N: &n}) 752 if err != nil { 753 t.Fatalf("Marshal: %v", err) 754 } 755 if got, want := string(b), `{"n":"42"}`; got != want { 756 t.Errorf("Marshal = %s, want %s", got, want) 757 } 758 var back stringPointer 759 err = Unmarshal(b, &back) 760 if err != nil { 761 t.Fatalf("Unmarshal: %v", err) 762 } 763 if back.N == nil { 764 t.Fatalf("Unmarshaled nil N field") 765 } 766 if *back.N != 42 { 767 t.Fatalf("*N = %d; want 42", *back.N) 768 } 769 } 770 771 var encodeStringTests = []struct { 772 in string 773 out string 774 }{ 775 {"\x00", `"\u0000"`}, 776 {"\x01", `"\u0001"`}, 777 {"\x02", `"\u0002"`}, 778 {"\x03", `"\u0003"`}, 779 {"\x04", `"\u0004"`}, 780 {"\x05", `"\u0005"`}, 781 {"\x06", `"\u0006"`}, 782 {"\x07", `"\u0007"`}, 783 {"\x08", `"\u0008"`}, 784 {"\x09", `"\t"`}, 785 {"\x0a", `"\n"`}, 786 {"\x0b", `"\u000b"`}, 787 {"\x0c", `"\u000c"`}, 788 {"\x0d", `"\r"`}, 789 {"\x0e", `"\u000e"`}, 790 {"\x0f", `"\u000f"`}, 791 {"\x10", `"\u0010"`}, 792 {"\x11", `"\u0011"`}, 793 {"\x12", `"\u0012"`}, 794 {"\x13", `"\u0013"`}, 795 {"\x14", `"\u0014"`}, 796 {"\x15", `"\u0015"`}, 797 {"\x16", `"\u0016"`}, 798 {"\x17", `"\u0017"`}, 799 {"\x18", `"\u0018"`}, 800 {"\x19", `"\u0019"`}, 801 {"\x1a", `"\u001a"`}, 802 {"\x1b", `"\u001b"`}, 803 {"\x1c", `"\u001c"`}, 804 {"\x1d", `"\u001d"`}, 805 {"\x1e", `"\u001e"`}, 806 {"\x1f", `"\u001f"`}, 807 } 808 809 func TestEncodeString(t *testing.T) { 810 for _, tt := range encodeStringTests { 811 b, err := Marshal(tt.in) 812 if err != nil { 813 t.Errorf("Marshal(%q): %v", tt.in, err) 814 continue 815 } 816 out := string(b) 817 if out != tt.out { 818 t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out) 819 } 820 } 821 } 822 823 type jsonbyte byte 824 825 func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) } 826 827 type textbyte byte 828 829 func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) } 830 831 type jsonint int 832 833 func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) } 834 835 type textint int 836 837 func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) } 838 839 func tenc(format string, a ...interface{}) ([]byte, error) { 840 var buf bytes.Buffer 841 _, _ = fmt.Fprintf(&buf, format, a...) 842 return buf.Bytes(), nil 843 } 844 845 // Issue 13783 846 func TestEncodeBytekind(t *testing.T) { 847 testdata := []struct { 848 data interface{} 849 want string 850 }{ 851 {byte(7), "7"}, 852 {jsonbyte(7), `{"JB":7}`}, 853 {textbyte(4), `"TB:4"`}, 854 {jsonint(5), `{"JI":5}`}, 855 {textint(1), `"TI:1"`}, 856 {[]byte{0, 1}, `"AAE="`}, 857 {[]jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`}, 858 {[][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`}, 859 {[]textbyte{2, 3}, `["TB:2","TB:3"]`}, 860 {[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`}, 861 {[]textint{9, 3}, `["TI:9","TI:3"]`}, 862 {[]int{9, 3}, `[9,3]`}, 863 } 864 for _, d := range testdata { 865 js, err := Marshal(d.data) 866 if err != nil { 867 t.Error(err) 868 continue 869 } 870 got, want := string(js), d.want 871 if got != want { 872 t.Errorf("got %s, want %s", got, want) 873 } 874 } 875 } 876 877 // https://golang.org/issue/33675 878 func TestNilMarshalerTextMapKey(t *testing.T) { 879 b, err := Marshal(map[*unmarshalerText]int{ 880 (*unmarshalerText)(nil): 1, 881 }) 882 if err != nil { 883 t.Fatalf("Failed to Marshal *text.Marshaler: %v", err) 884 } 885 const want = `{"":1}` 886 if string(b) != want { 887 t.Errorf("Marshal map with *text.Marshaler keys: got %#q, want %#q", b, want) 888 } 889 } 890 891 var re = regexp.MustCompile 892 893 // syntactic checks on form of marshaled floating point numbers. 894 var badFloatREs = []*regexp.Regexp{ 895 re(`p`), // no binary exponential notation 896 re(`^\+`), // no leading + sign 897 re(`^-?0[^.]`), // no unnecessary leading zeros 898 re(`^-?\.`), // leading zero required before decimal point 899 re(`\.(e|$)`), // no trailing decimal 900 re(`\.[0-9]+0(e|$)`), // no trailing zero in fraction 901 re(`^-?(0|[0-9]{2,})\..*e`), // exponential notation must have normalized mantissa 902 re(`e[+-]0`), // exponent must not have leading zeros 903 re(`e-[1-6]$`), // not tiny enough for exponential notation 904 re(`e+(.|1.|20)$`), // not big enough for exponential notation 905 re(`^-?0\.0000000`), // too tiny, should use exponential notation 906 re(`^-?[0-9]{22}`), // too big, should use exponential notation 907 re(`[1-9][0-9]{16}[1-9]`), // too many significant digits in integer 908 re(`[1-9][0-9.]{17}[1-9]`), // too many significant digits in decimal 909 } 910 911 func TestMarshalFloat(t *testing.T) { 912 t.Parallel() 913 nfail := 0 914 test := func(f float64, bits int) { 915 vf := interface{}(f) 916 if bits == 32 { 917 f = float64(float32(f)) // round 918 vf = float32(f) 919 } 920 bout, err := Marshal(vf) 921 if err != nil { 922 t.Errorf("Marshal(%T(%g)): %v", vf, vf, err) 923 nfail++ 924 return 925 } 926 out := string(bout) 927 928 // result must convert back to the same float 929 g, err := strconv.ParseFloat(out, bits) 930 if err != nil { 931 t.Errorf("Marshal(%T(%g)) = %q, cannot parse back: %v", vf, vf, out, err) 932 nfail++ 933 return 934 } 935 if f != g { 936 t.Errorf("Marshal(%T(%g)) = %q (is %g, not %g)", vf, vf, out, float32(g), vf) 937 nfail++ 938 return 939 } 940 941 for _, re := range badFloatREs { 942 if re.MatchString(out) { 943 t.Errorf("Marshal(%T(%g)) = %q, must not match /%s/", vf, vf, out, re) 944 nfail++ 945 return 946 } 947 } 948 } 949 950 var ( 951 bigger = math.Inf(+1) 952 smaller = math.Inf(-1) 953 ) 954 955 var digits = "1.2345678901234567890123" 956 for i := len(digits); i >= 2; i-- { 957 if testing.Short() && i < len(digits)-4 { 958 break 959 } 960 for exp := -30; exp <= 30; exp++ { 961 for _, sign := range "+-" { 962 for bits := 32; bits <= 64; bits += 32 { 963 s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp) 964 f, err := strconv.ParseFloat(s, bits) 965 if err != nil { 966 log.Fatal(err) 967 } 968 next := math.Nextafter 969 if bits == 32 { 970 next = func(g, h float64) float64 { 971 return float64(math.Nextafter32(float32(g), float32(h))) 972 } 973 } 974 test(f, bits) 975 test(next(f, bigger), bits) 976 test(next(f, smaller), bits) 977 if nfail > 50 { 978 t.Fatalf("stopping test early") 979 } 980 } 981 } 982 } 983 } 984 test(0, 64) 985 test(math.Copysign(0, -1), 64) 986 test(0, 32) 987 test(math.Copysign(0, -1), 32) 988 } 989 990 func TestMarshalRawMessageValue(t *testing.T) { 991 type ( 992 T1 struct { 993 M json.RawMessage `json:",omitempty"` 994 } 995 T2 struct { 996 M *json.RawMessage `json:",omitempty"` 997 } 998 ) 999 1000 var ( 1001 rawNil = json.RawMessage(nil) 1002 rawEmpty = json.RawMessage([]byte{}) 1003 rawText = json.RawMessage(`"foo"`) 1004 ) 1005 1006 tests := []struct { 1007 in interface{} 1008 want string 1009 ok bool 1010 }{ 1011 // Test with nil RawMessage. 1012 {rawNil, "null", true}, 1013 {&rawNil, "null", true}, 1014 {[]interface{}{rawNil}, "[null]", true}, 1015 {&[]interface{}{rawNil}, "[null]", true}, 1016 {[]interface{}{&rawNil}, "[null]", true}, 1017 {&[]interface{}{&rawNil}, "[null]", true}, 1018 {struct{ M json.RawMessage }{rawNil}, `{"M":null}`, true}, 1019 {&struct{ M json.RawMessage }{rawNil}, `{"M":null}`, true}, 1020 {struct{ M *json.RawMessage }{&rawNil}, `{"M":null}`, true}, 1021 {&struct{ M *json.RawMessage }{&rawNil}, `{"M":null}`, true}, 1022 {map[string]interface{}{"M": rawNil}, `{"M":null}`, true}, 1023 {&map[string]interface{}{"M": rawNil}, `{"M":null}`, true}, 1024 {map[string]interface{}{"M": &rawNil}, `{"M":null}`, true}, 1025 {&map[string]interface{}{"M": &rawNil}, `{"M":null}`, true}, 1026 {T1{rawNil}, "{}", true}, 1027 {T2{&rawNil}, `{"M":null}`, true}, 1028 {&T1{rawNil}, "{}", true}, 1029 {&T2{&rawNil}, `{"M":null}`, true}, 1030 1031 // Test with empty, but non-nil, RawMessage. 1032 {rawEmpty, "", false}, 1033 {&rawEmpty, "", false}, 1034 {[]interface{}{rawEmpty}, "", false}, 1035 {&[]interface{}{rawEmpty}, "", false}, 1036 {[]interface{}{&rawEmpty}, "", false}, 1037 {&[]interface{}{&rawEmpty}, "", false}, 1038 {struct{ X json.RawMessage }{rawEmpty}, "", false}, 1039 {&struct{ X json.RawMessage }{rawEmpty}, "", false}, 1040 {struct{ X *json.RawMessage }{&rawEmpty}, "", false}, 1041 {&struct{ X *json.RawMessage }{&rawEmpty}, "", false}, 1042 {map[string]interface{}{"nil": rawEmpty}, "", false}, 1043 {&map[string]interface{}{"nil": rawEmpty}, "", false}, 1044 {map[string]interface{}{"nil": &rawEmpty}, "", false}, 1045 {&map[string]interface{}{"nil": &rawEmpty}, "", false}, 1046 {T1{rawEmpty}, "{}", true}, 1047 {T2{&rawEmpty}, "", false}, 1048 {&T1{rawEmpty}, "{}", true}, 1049 {&T2{&rawEmpty}, "", false}, 1050 1051 // Test with RawMessage with some text. 1052 // 1053 // The tests below marked with Issue6458 used to generate "ImZvbyI=" instead "foo". 1054 // This behavior was intentionally changed in Go 1.8. 1055 // See https://golang.org/issues/14493#issuecomment-255857318 1056 {rawText, `"foo"`, true}, // Issue6458 1057 {&rawText, `"foo"`, true}, 1058 {[]interface{}{rawText}, `["foo"]`, true}, // Issue6458 1059 {&[]interface{}{rawText}, `["foo"]`, true}, // Issue6458 1060 {[]interface{}{&rawText}, `["foo"]`, true}, 1061 {&[]interface{}{&rawText}, `["foo"]`, true}, 1062 {struct{ M json.RawMessage }{rawText}, `{"M":"foo"}`, true}, // Issue6458 1063 {&struct{ M json.RawMessage }{rawText}, `{"M":"foo"}`, true}, 1064 {struct{ M *json.RawMessage }{&rawText}, `{"M":"foo"}`, true}, 1065 {&struct{ M *json.RawMessage }{&rawText}, `{"M":"foo"}`, true}, 1066 {map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 1067 {&map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458 1068 {map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true}, 1069 {&map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true}, 1070 {T1{rawText}, `{"M":"foo"}`, true}, // Issue6458 1071 {T2{&rawText}, `{"M":"foo"}`, true}, 1072 {&T1{rawText}, `{"M":"foo"}`, true}, 1073 {&T2{&rawText}, `{"M":"foo"}`, true}, 1074 } 1075 1076 for i, tt := range tests { 1077 b, err := Marshal(tt.in) 1078 if ok := err == nil; ok != tt.ok { 1079 if err != nil { 1080 t.Errorf("test %d, unexpected failure: %v", i, err) 1081 } else { 1082 t.Errorf("test %d, unexpected success", i) 1083 } 1084 } 1085 if got := string(b); got != tt.want { 1086 t.Errorf("test %d, Marshal(%#v) = %q, want %q", i, tt.in, got, tt.want) 1087 } 1088 } 1089 } 1090 1091 type marshalPanic struct{} 1092 1093 func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) } 1094 1095 func TestMarshalPanic(t *testing.T) { 1096 defer func() { 1097 if got := recover(); !reflect.DeepEqual(got, 0xdead) { 1098 t.Errorf("panic() = (%T)(%v), want 0xdead", got, got) 1099 } 1100 }() 1101 _, _ = Marshal(&marshalPanic{}) 1102 t.Error("Marshal should have panicked") 1103 } 1104 1105 //goland:noinspection NonAsciiCharacters 1106 func TestMarshalUncommonFieldNames(t *testing.T) { 1107 v := struct { 1108 A0, À, Aβ int 1109 }{} 1110 b, err := Marshal(v) 1111 if err != nil { 1112 t.Fatal("Marshal:", err) 1113 } 1114 want := `{"A0":0,"À":0,"Aβ":0}` 1115 got := string(b) 1116 if got != want { 1117 t.Fatalf("Marshal: got %s want %s", got, want) 1118 } 1119 } 1120 1121 type DummyMarshalerError struct { 1122 Type reflect.Type 1123 Err error 1124 SourceFunc string 1125 } 1126 1127 func (self *DummyMarshalerError) err() *json.MarshalerError { 1128 return (*json.MarshalerError)(unsafe.Pointer(self)) 1129 } 1130 1131 func TestMarshalerError(t *testing.T) { 1132 s := "test variable" 1133 st := reflect.TypeOf(s) 1134 errText := "json: test error" 1135 1136 tests := []struct { 1137 err *json.MarshalerError 1138 want string 1139 }{ 1140 { 1141 (&DummyMarshalerError{st, fmt.Errorf(errText), ""}).err(), 1142 "json: error calling MarshalJSON for type " + st.String() + ": " + errText, 1143 }, 1144 { 1145 (&DummyMarshalerError{st, fmt.Errorf(errText), "TestMarshalerError"}).err(), 1146 "json: error calling TestMarshalerError for type " + st.String() + ": " + errText, 1147 }, 1148 } 1149 1150 for i, tt := range tests { 1151 got := tt.err.Error() 1152 if got != tt.want { 1153 t.Errorf("MarshalerError test %d, got: %s, want: %s", i, got, tt.want) 1154 } 1155 } 1156 } 1157 1158 func TestMarshalNullNil(t *testing.T) { 1159 var v = struct { 1160 A []int 1161 B map[string]int 1162 }{} 1163 o, e := Marshal(v) 1164 assert.Nil(t, e) 1165 assert.Equal(t, `{"A":null,"B":null}`, string(o)) 1166 o, e = Config{ 1167 NoNullSliceOrMap: true, 1168 }.Froze().Marshal(v) 1169 assert.Nil(t, e) 1170 assert.Equal(t, `{"A":[],"B":{}}`, string(o)) 1171 } 1172 1173 func TestEncoder_LongestInvalidUtf8(t *testing.T) { 1174 for _, data := range([]string{ 1175 "\"" + strings.Repeat("\x80", 4096) + "\"", 1176 "\"" + strings.Repeat("\x80", 4095) + "\"", 1177 "\"" + strings.Repeat("\x80", 4097) + "\"", 1178 "\"" + strings.Repeat("\x80", 12345) + "\"", 1179 }) { 1180 testEncodeInvalidUtf8(t, []byte(data)) 1181 } 1182 } 1183 1184 func testEncodeInvalidUtf8(t *testing.T, data []byte) { 1185 jgot, jerr := json.Marshal(data) 1186 sgot, serr := ConfigStd.Marshal(data) 1187 assert.Equal(t, serr != nil, jerr != nil) 1188 if jerr == nil { 1189 assert.Equal(t, sgot, jgot) 1190 } 1191 } 1192 1193 func TestEncoder_RandomInvalidUtf8(t *testing.T) { 1194 nums := 1000 1195 maxLen := 1000 1196 for i := 0; i < nums; i++ { 1197 testEncodeInvalidUtf8(t, genRandJsonBytes(maxLen)) 1198 testEncodeInvalidUtf8(t, genRandJsonRune(maxLen)) 1199 } 1200 }