github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/issue_test/issue379_test.go (about) 1 /* 2 * Copyright 2023 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package issue_test 18 19 import ( 20 `encoding/json` 21 `testing` 22 23 `github.com/bytedance/sonic` 24 `github.com/stretchr/testify/assert` 25 `github.com/stretchr/testify/require` 26 ) 27 28 type Foo struct { 29 Name string 30 } 31 32 func (f *Foo) UnmarshalJSON(data []byte) error { 33 println("UnmarshalJSON called!!!") 34 f.Name = "Unmarshaler" 35 return nil 36 } 37 38 type MyPtr *Foo 39 40 func TestIssue379(t *testing.T) { 41 tests := []struct{ 42 data string 43 newf func() interface{} 44 equal func(exp, act interface{}) bool 45 } { 46 { 47 data: `{"Name":"MyPtr"}`, 48 newf: func() interface{} { return &Foo{} }, 49 }, 50 { 51 data: `{"Name":"MyPtr"}`, 52 newf: func() interface{} { ptr := &Foo{}; return &ptr }, 53 }, 54 { 55 data: `{"Name":"MyPtr"}`, 56 newf: func() interface{} { return MyPtr(&Foo{}) }, 57 }, 58 { 59 data: `{"Name":"MyPtr"}`, 60 newf: func() interface{} { ptr := MyPtr(&Foo{}); return &ptr }, 61 }, 62 { 63 data: `null`, 64 newf: func() interface{} { return MyPtr(&Foo{}) }, 65 }, 66 { 67 data: `null`, 68 newf: func() interface{} { ptr := MyPtr(&Foo{}); return &ptr }, 69 equal: func(exp, act interface{}) bool { 70 isExpNil := exp == nil || *(exp.(*MyPtr)) == nil 71 isActNil := act == nil || *(act.(*MyPtr)) == nil 72 return isActNil == isExpNil 73 }, 74 }, 75 { 76 data: `null`, 77 newf: func() interface{} { return &Foo{} }, 78 }, 79 { 80 data: `null`, 81 newf: func() interface{} { ptr := &Foo{}; return &ptr }, 82 equal: func(exp, act interface{}) bool { 83 isExpNil := exp == nil || *(exp.(**Foo)) == nil 84 isActNil := act == nil || *(act.(**Foo)) == nil 85 return isActNil == isExpNil 86 }, 87 }, 88 { 89 data: `{"map":{"Name":"MyPtr"}}`, 90 newf: func() interface{} { return new(map[string]MyPtr) }, 91 }, 92 { 93 data: `{"map":{"Name":"MyPtr"}}`, 94 newf: func() interface{} { return new(map[string]*Foo) }, 95 }, 96 { 97 data: `{"map":{"Name":"MyPtr"}}`, 98 newf: func() interface{} { return new(map[string]*MyPtr) }, 99 }, 100 { 101 data: `[{"Name":"MyPtr"}]`, 102 newf: func() interface{} { return new([]MyPtr) }, 103 }, 104 { 105 data: `[{"Name":"MyPtr"}]`, 106 newf: func() interface{} { return new([]*MyPtr) }, 107 }, 108 { 109 data: `[{"Name":"MyPtr"}]`, 110 newf: func() interface{} { return new([]*Foo) }, 111 }, 112 } 113 114 for i, tt := range tests { 115 println(i) 116 jv, sv := tt.newf(), tt.newf() 117 jerr := json.Unmarshal([]byte(tt.data), jv) 118 serr := sonic.Unmarshal([]byte(tt.data), sv) 119 require.Equal(t, jv, sv) 120 require.Equal(t, jerr, serr) 121 122 jv, sv = tt.newf(), tt.newf() 123 jerr = json.Unmarshal([]byte(tt.data), &jv) 124 serr = sonic.Unmarshal([]byte(tt.data), &sv) 125 if !assert.ObjectsAreEqual(jv, sv) { 126 if tt.equal == nil || !tt.equal(jv, sv) { 127 t.Fatal() 128 } 129 } 130 require.Equal(t, jerr, serr) 131 } 132 }