github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/decoder/decoder_test.go (about)

     1  /*
     2   * Copyright 2021 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 decoder
    18  
    19  import (
    20      `encoding/json`
    21      `runtime`
    22      `runtime/debug`
    23      `strings`
    24      `sync`
    25      `testing`
    26      `time`
    27  
    28      `github.com/davecgh/go-spew/spew`
    29      `github.com/stretchr/testify/assert`
    30      `github.com/stretchr/testify/require`
    31  )
    32  
    33  func TestMain(m *testing.M) {
    34      go func ()  {
    35          if !debugAsyncGC {
    36              return
    37          }
    38          println("Begin GC looping...")
    39          for {
    40             runtime.GC()
    41             debug.FreeOSMemory() 
    42          }
    43          println("stop GC looping!")
    44      }()
    45      time.Sleep(time.Millisecond)
    46      m.Run()
    47  }
    48  
    49  func TestGC(t *testing.T) {
    50      if debugSyncGC {
    51          return 
    52      }
    53      var w interface{}
    54      out, err := decode(TwitterJson, &w, true)
    55      if err != nil {
    56          t.Fatal(err)
    57      }
    58      if out != len(TwitterJson) {
    59          t.Fatal(out)
    60      }
    61      wg := &sync.WaitGroup{}
    62      N := 10000
    63      for i:=0; i<N; i++ {
    64          wg.Add(1)
    65          go func (wg *sync.WaitGroup)  {
    66              defer wg.Done()
    67              var w interface{}
    68              out, err := decode(TwitterJson, &w, true)
    69              if err != nil {
    70                  t.Error(err)
    71                  return
    72              }
    73              if out != len(TwitterJson) {
    74                  t.Error(out)
    75                  return
    76              }
    77              runtime.GC()
    78          }(wg)
    79      }
    80      wg.Wait()
    81  }
    82  
    83  var _BindingValue TwitterStruct
    84  
    85  func init() {
    86      _ = json.Unmarshal([]byte(TwitterJson), &_BindingValue)
    87  }
    88  
    89  
    90  func TestSkipMismatchTypeError(t *testing.T) {
    91      t.Run("struct", func(t *testing.T) {
    92          println("TestSkipError")
    93          type skiptype struct {
    94              A int `json:"a"`
    95              B string `json:"b"`
    96  
    97              Pass *int `json:"pass"`
    98  
    99              C struct{
   100  
   101                  Pass4 interface{} `json:"pass4"`
   102  
   103                  D struct{
   104                      E float32 `json:"e"`
   105                  } `json:"d"`
   106  
   107                  Pass2 int `json:"pass2"`
   108  
   109              } `json:"c"`
   110  
   111              E bool `json:"e"`
   112              F []int `json:"f"`
   113              G map[string]int `json:"g"`
   114              H bool `json:"h,string"`
   115  
   116              Pass3 int `json:"pass2"`
   117  
   118              I json.Number `json:"i"`
   119          }
   120          var obj, obj2 = &skiptype{Pass:new(int)}, &skiptype{Pass:new(int)}
   121          var data = `{"a":"","b":1,"c":{"d":true,"pass2":1,"pass4":true},"e":{},"f":"","g":[],"pass":null,"h":"1.0","i":true,"pass3":1}`
   122          d := NewDecoder(data)
   123          err := d.Decode(obj)
   124          err2 := json.Unmarshal([]byte(data), obj2)
   125          println(err2.Error())
   126          assert.Equal(t, err2 == nil, err == nil)
   127          // assert.Equal(t, len(data), d.i)
   128          assert.Equal(t, obj2, obj)
   129          if err == nil {
   130              t.Fatal("invalid error")
   131          }
   132      })
   133      t.Run("short array", func(t *testing.T) {
   134          var obj, obj2 = &[]int{}, &[]int{}
   135          var data = `[""]`
   136          d := NewDecoder(data)
   137          err := d.Decode(obj)
   138          err2 := json.Unmarshal([]byte(data), obj2)
   139          // println(err2.Error())
   140          assert.Equal(t, err2 == nil, err == nil)
   141          // assert.Equal(t, len(data), d.i)
   142          assert.Equal(t, obj2, obj)
   143      })
   144  
   145      t.Run("int ", func(t *testing.T) {
   146          var obj int = 123
   147          var obj2 int = 123
   148          var data = `[""]`
   149          d := NewDecoder(data)
   150          err := d.Decode(&obj)
   151          err2 := json.Unmarshal([]byte(data), &obj2)
   152          println(err.Error(), obj, obj2)
   153          assert.Equal(t, err2 == nil, err == nil)
   154          // assert.Equal(t, len(data), d.i)
   155          assert.Equal(t, obj2, obj)
   156      })
   157  
   158      t.Run("array", func(t *testing.T) {
   159          var obj, obj2 = &[]int{}, &[]int{}
   160          var data = `["",true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true]`
   161          d := NewDecoder(data)
   162          err := d.Decode(obj)
   163          err2 := json.Unmarshal([]byte(data), obj2)
   164          // println(err2.Error())
   165          assert.Equal(t, err2 == nil, err == nil)
   166          // assert.Equal(t, len(data), d.i)
   167          assert.Equal(t, obj2, obj)
   168      })
   169  
   170      t.Run("map", func(t *testing.T) {
   171          var obj, obj2 = &map[int]int{}, &map[int]int{}
   172          var data = `{"true" : { },"1":1,"2" : true,"3":3}`
   173          d := NewDecoder(data)
   174          err := d.Decode(obj)
   175          err2 := json.Unmarshal([]byte(data), obj2)
   176          assert.Equal(t, err2 == nil, err == nil)
   177          // assert.Equal(t, len(data), d.i)
   178          assert.Equal(t, obj2, obj)
   179      })
   180      t.Run("map error", func(t *testing.T) {
   181          var obj, obj2 = &map[int]int{}, &map[int]int{}
   182          var data = `{"true" : { ],"1":1,"2" : true,"3":3}`
   183          d := NewDecoder(data)
   184          err := d.Decode(obj)
   185          err2 := json.Unmarshal([]byte(data), obj2)
   186          println(err.Error())
   187          println(err2.Error())
   188          assert.Equal(t, err2 == nil, err == nil)
   189          // assert.Equal(t, len(data), d.i)
   190          // assert.Equal(t, obj2, obj)
   191      })
   192  }
   193  
   194  func TestDecodeCorrupt(t *testing.T) {
   195      var ds = []string{
   196          `{,}`,
   197          `{,"a"}`,
   198          `{"a":}`,
   199          `{"a":1,}`,
   200          `{"a":1,"b"}`,
   201          `{"a":1,"b":}`,
   202          `{,"a":1 "b":2}`,
   203          `{"a",:1 "b":2}`,
   204          `{"a":,1 "b":2}`,
   205          `{"a":1 "b",:2}`,
   206          `{"a":1 "b":,2}`,
   207          `{"a":1 "b":2,}`,
   208          `{"a":1 "b":2}`,
   209          `[,]`,
   210          `[,1]`,
   211          `[1,]`,
   212          `[,1,2]`,
   213          `[1,2,]`,
   214      }
   215      for _, d := range ds {
   216          var o interface{}
   217          _, err := decode(d, &o, false)
   218          if err == nil {
   219              t.Fatalf("%#v", d)
   220          }
   221          if !strings.Contains(err.Error(), "invalid char"){
   222              t.Fatal(err.Error())
   223          }
   224      }
   225  }
   226  
   227  func TestDecodeOption(t *testing.T) {
   228      var s string
   229      var d *Decoder
   230      var out interface{}
   231      var out2 struct {}
   232      var err error
   233  
   234      s = "123"
   235      d = NewDecoder(s)
   236      d.SetOptions(OptionUseNumber);
   237      err = d.Decode(&out)
   238      assert.NoError(t, err)
   239      assert.Equal(t, out.(json.Number), json.Number("123"))
   240  
   241      d = NewDecoder(s)
   242      err = d.Decode(&out)
   243      assert.NoError(t, err)
   244      assert.Equal(t, out.(float64), float64(123))
   245  
   246      s = `{"un": 123}`
   247      d = NewDecoder(s)
   248      d.SetOptions(OptionDisableUnknown);
   249      err = d.Decode(&out2)
   250      assert.Error(t, err)
   251  
   252      d = NewDecoder(s)
   253      err = d.Decode(&out2)
   254      assert.NoError(t, err)
   255  }
   256  
   257  func decode(s string, v interface{}, copy bool) (int, error) {
   258      d := NewDecoder(s)
   259      if copy {
   260          d.CopyString()
   261      }
   262      err := d.Decode(v)
   263      if err != nil {
   264          return 0, err
   265      }
   266      return len(s), err
   267  }
   268  
   269  func TestDecoder_Basic(t *testing.T) {
   270      var v int
   271      pos, err := decode("12345", &v, false)
   272      assert.NoError(t, err)
   273      assert.Equal(t, 5, pos)
   274      assert.Equal(t, 12345, v)
   275  }
   276  
   277  func TestDecoder_Generic(t *testing.T) {
   278      var v interface{}
   279      pos, err := decode(TwitterJson, &v, false)
   280      assert.NoError(t, err)
   281      assert.Equal(t, len(TwitterJson), pos)
   282  }
   283  
   284  func TestDecoder_Binding(t *testing.T) {
   285      var v TwitterStruct
   286      pos, err := decode(TwitterJson, &v, false)
   287      assert.NoError(t, err)
   288      assert.Equal(t, len(TwitterJson), pos)
   289      assert.Equal(t, _BindingValue, v, 0)
   290      spew.Dump(v)
   291  }
   292  
   293  
   294  func TestDecoder_MapWithIndirectElement(t *testing.T) {
   295      var v map[string]struct { A [129]byte }
   296      _, err := decode(`{"":{"A":[1,2,3,4,5]}}`, &v, false)
   297      require.NoError(t, err)
   298      assert.Equal(t, [129]byte{1, 2, 3, 4, 5}, v[""].A)
   299  }
   300  
   301  func BenchmarkDecoder_Generic_Sonic(b *testing.B) {
   302      var w interface{}
   303      _, _ = decode(TwitterJson, &w, true)
   304      b.SetBytes(int64(len(TwitterJson)))
   305      b.ResetTimer()
   306      for i := 0; i < b.N; i++ {
   307          var v interface{}
   308          _, _ = decode(TwitterJson, &v, true)
   309      }
   310  }
   311  
   312  func BenchmarkDecoder_Generic_Sonic_Fast(b *testing.B) {
   313      var w interface{}
   314      _, _ = decode(TwitterJson, &w, false)
   315      b.SetBytes(int64(len(TwitterJson)))
   316      b.ResetTimer()
   317      for i := 0; i < b.N; i++ {
   318          var v interface{}
   319          _, _ = decode(TwitterJson, &v, false)
   320      }
   321  }
   322  
   323  func BenchmarkDecoder_Generic_StdLib(b *testing.B) {
   324      var w interface{}
   325      m := []byte(TwitterJson)
   326      _ = json.Unmarshal(m, &w)
   327      b.SetBytes(int64(len(TwitterJson)))
   328      b.ResetTimer()
   329      for i := 0; i < b.N; i++ {
   330          var v interface{}
   331          _ = json.Unmarshal(m, &v)
   332      }
   333  }
   334  
   335  func BenchmarkDecoder_Binding_Sonic(b *testing.B) {
   336      var w TwitterStruct
   337      _, _ = decode(TwitterJson, &w, true)
   338      b.SetBytes(int64(len(TwitterJson)))
   339      b.ResetTimer()
   340      for i := 0; i < b.N; i++ {
   341          var v TwitterStruct
   342          _, _ = decode(TwitterJson, &v, true)
   343      }
   344  }
   345  
   346  func BenchmarkDecoder_Binding_Sonic_Fast(b *testing.B) {
   347      var w TwitterStruct
   348      _, _ = decode(TwitterJson, &w, false)
   349      b.SetBytes(int64(len(TwitterJson)))
   350      b.ResetTimer()
   351      for i := 0; i < b.N; i++ {
   352          var v TwitterStruct
   353          _, _ = decode(TwitterJson, &v, false)
   354      }
   355  }
   356  
   357  func BenchmarkDecoder_Binding_StdLib(b *testing.B) {
   358      var w TwitterStruct
   359      m := []byte(TwitterJson)
   360      _ = json.Unmarshal(m, &w)
   361      b.SetBytes(int64(len(TwitterJson)))
   362      b.ResetTimer()
   363      for i := 0; i < b.N; i++ {
   364          var v TwitterStruct
   365          _ = json.Unmarshal(m, &v)
   366      }
   367  }
   368  
   369  func BenchmarkDecoder_Parallel_Generic_Sonic(b *testing.B) {
   370      var w interface{}
   371      _, _ = decode(TwitterJson, &w, true)
   372      b.SetBytes(int64(len(TwitterJson)))
   373      b.ResetTimer()
   374      b.RunParallel(func(pb *testing.PB) {
   375          for pb.Next() {
   376              var v interface{}
   377              _, _ = decode(TwitterJson, &v, true)
   378          }
   379      })
   380  }
   381  
   382  func BenchmarkDecoder_Parallel_Generic_Sonic_Fast(b *testing.B) {
   383      var w interface{}
   384      _, _ = decode(TwitterJson, &w, false)
   385      b.SetBytes(int64(len(TwitterJson)))
   386      b.ResetTimer()
   387      b.RunParallel(func(pb *testing.PB) {
   388          for pb.Next() {
   389              var v interface{}
   390              _, _ = decode(TwitterJson, &v, false)
   391          }
   392      })
   393  }
   394  
   395  func BenchmarkDecoder_Parallel_Generic_StdLib(b *testing.B) {
   396      var w interface{}
   397      m := []byte(TwitterJson)
   398      _ = json.Unmarshal(m, &w)
   399      b.SetBytes(int64(len(TwitterJson)))
   400      b.ResetTimer()
   401      b.RunParallel(func(pb *testing.PB) {
   402          for pb.Next() {
   403              var v interface{}
   404              _ = json.Unmarshal(m, &v)
   405          }
   406      })
   407  }
   408  
   409  func BenchmarkDecoder_Parallel_Binding_Sonic(b *testing.B) {
   410      var w TwitterStruct
   411      _, _ = decode(TwitterJson, &w, true)
   412      b.SetBytes(int64(len(TwitterJson)))
   413      b.ResetTimer()
   414      b.RunParallel(func(pb *testing.PB) {
   415          for pb.Next() {
   416              var v TwitterStruct
   417              _, _ = decode(TwitterJson, &v, true)
   418          }
   419      })
   420  }
   421  
   422  func BenchmarkDecoder_Parallel_Binding_Sonic_Fast(b *testing.B) {
   423      var w TwitterStruct
   424      _, _ = decode(TwitterJson, &w, false)
   425      b.SetBytes(int64(len(TwitterJson)))
   426      b.ResetTimer()
   427      b.RunParallel(func(pb *testing.PB) {
   428          for pb.Next() {
   429              var v TwitterStruct
   430              _, _ = decode(TwitterJson, &v, false)
   431          }
   432      })
   433  }
   434  
   435  func BenchmarkDecoder_Parallel_Binding_StdLib(b *testing.B) {
   436      var w TwitterStruct
   437      m := []byte(TwitterJson)
   438      _ = json.Unmarshal(m, &w)
   439      b.SetBytes(int64(len(TwitterJson)))
   440      b.ResetTimer()
   441      b.RunParallel(func(pb *testing.PB) {
   442          for pb.Next() {
   443              var v TwitterStruct
   444              _ = json.Unmarshal(m, &v)
   445          }
   446      })
   447  }