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