github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/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/goshafaq/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  }