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  }