github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/decoder/stream_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  	"bytes"
    21  	"encoding/json"
    22  	"io"
    23  	"io/ioutil"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/goshafaq/sonic/option"
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  var (
    33  	DefaultBufferSize = option.DefaultDecoderBufferSize
    34  	_Single_JSON      = `{"aaaaa":"` + strings.Repeat("b", int(DefaultBufferSize)) + `"} { `
    35  	_Double_JSON      = `{"aaaaa":"` + strings.Repeat("b", int(DefaultBufferSize)) + `"}    {"11111":"` + strings.Repeat("2", int(DefaultBufferSize)) + `"}`
    36  	_Triple_JSON      = `{"aaaaa":"` + strings.Repeat("b", int(DefaultBufferSize)) + `"}{ } {"11111":"` +
    37  		strings.Repeat("2", int(DefaultBufferSize)) + `"} b {}`
    38  )
    39  
    40  func TestStreamError(t *testing.T) {
    41  	var qs = []string{
    42  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"`,
    43  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"}`,
    44  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `""}`,
    45  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":}`,
    46  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":]`,
    47  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":1x`,
    48  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":1x}`,
    49  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":1x]`,
    50  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":t`,
    51  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":t}`,
    52  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":true]`,
    53  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":f`,
    54  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":f}`,
    55  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":false]`,
    56  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":n`,
    57  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":n}`,
    58  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":null]`,
    59  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":"`,
    60  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":"a`,
    61  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":"a}`,
    62  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":"a"`,
    63  		`{` + strings.Repeat(" ", int(DefaultBufferSize)) + `"":"a"]`,
    64  	}
    65  
    66  	for i, q := range qs {
    67  		var qq = []byte(q[:int(DefaultBufferSize)] + strings.Repeat(" ", i*100) + q[int(DefaultBufferSize):])
    68  		var obj interface{}
    69  		require.NotNil(t, NewStreamDecoder(bytes.NewReader(qq)).Decode(&obj))
    70  	}
    71  }
    72  
    73  func TestDecodeEmpty(t *testing.T) {
    74  	var str = ``
    75  	var r1 = strings.NewReader(str)
    76  	var v1 interface{}
    77  	var d1 = json.NewDecoder(r1)
    78  	var r2 = strings.NewReader(str)
    79  	var v2 interface{}
    80  	var d2 = NewStreamDecoder(r2)
    81  	es1 := d1.Decode(&v1)
    82  	ee1 := d2.Decode(&v2)
    83  	assert.Equal(t, es1, ee1)
    84  	assert.Equal(t, v1, v2)
    85  }
    86  
    87  type HaltReader struct {
    88  	halts map[int]bool
    89  	buf   string
    90  	p     int
    91  }
    92  
    93  func NewHaltReader(buf string, halts map[int]bool) *HaltReader {
    94  	return &HaltReader{
    95  		halts: halts,
    96  		buf:   buf,
    97  		p:     0,
    98  	}
    99  }
   100  
   101  func (self *HaltReader) Read(p []byte) (int, error) {
   102  	t := 0
   103  	for t < len(p) {
   104  		if self.p >= len(self.buf) {
   105  			return t, io.EOF
   106  		}
   107  		if b, ok := self.halts[self.p]; b {
   108  			self.halts[self.p] = false
   109  			return t, nil
   110  		} else if ok {
   111  			delete(self.halts, self.p)
   112  			return 0, nil
   113  		}
   114  		p[t] = self.buf[self.p]
   115  		self.p++
   116  		t++
   117  	}
   118  	return t, nil
   119  }
   120  
   121  func (self *HaltReader) Reset(buf string) {
   122  	self.p = 0
   123  	self.buf = buf
   124  }
   125  
   126  var testHalts = func() map[int]bool {
   127  	return map[int]bool{
   128  		1:  true,
   129  		10: true,
   130  		20: true}
   131  }
   132  
   133  func TestBuffered(t *testing.T) {
   134  	var str = _Triple_JSON
   135  	var r1 = NewHaltReader(str, testHalts())
   136  	var v1 map[string]interface{}
   137  	var d1 = json.NewDecoder(r1)
   138  	require.Nil(t, d1.Decode(&v1))
   139  	var r2 = NewHaltReader(str, testHalts())
   140  	var v2 map[string]interface{}
   141  	var d2 = NewStreamDecoder(r2)
   142  	require.Nil(t, d2.Decode(&v2))
   143  	left1, err1 := ioutil.ReadAll(d1.Buffered())
   144  	require.Nil(t, err1)
   145  	left2, err2 := ioutil.ReadAll(d2.Buffered())
   146  	require.Nil(t, err2)
   147  	require.Equal(t, d1.InputOffset(), d2.InputOffset())
   148  	min := len(left1)
   149  	if min > len(left2) {
   150  		min = len(left2)
   151  	}
   152  	require.Equal(t, left1[:min], left2[:min])
   153  
   154  	es4 := d1.Decode(&v1)
   155  	ee4 := d2.Decode(&v2)
   156  	assert.Equal(t, es4, ee4)
   157  	assert.Equal(t, d1.InputOffset(), d2.InputOffset())
   158  
   159  	es2 := d1.Decode(&v1)
   160  	ee2 := d2.Decode(&v2)
   161  	assert.Equal(t, es2, ee2)
   162  	assert.Equal(t, d1.InputOffset(), d2.InputOffset())
   163  }
   164  
   165  func BenchmarkDecodeStream_Std(b *testing.B) {
   166  	b.Run("single", func(b *testing.B) {
   167  		var str = _Single_JSON
   168  		for i := 0; i < b.N; i++ {
   169  			var r1 = strings.NewReader(str)
   170  			var v1 map[string]interface{}
   171  			dc := json.NewDecoder(r1)
   172  			_ = dc.Decode(&v1)
   173  			_ = dc.Decode(&v1)
   174  		}
   175  	})
   176  
   177  	b.Run("double", func(b *testing.B) {
   178  		var str = _Double_JSON
   179  		for i := 0; i < b.N; i++ {
   180  			var r1 = strings.NewReader(str)
   181  			var v1 map[string]interface{}
   182  			dc := json.NewDecoder(r1)
   183  			_ = dc.Decode(&v1)
   184  			_ = dc.Decode(&v1)
   185  		}
   186  	})
   187  
   188  	b.Run("halt", func(b *testing.B) {
   189  		var str = _Double_JSON
   190  		for i := 0; i < b.N; i++ {
   191  			var r1 = NewHaltReader(str, testHalts())
   192  			var v1 map[string]interface{}
   193  			dc := json.NewDecoder(r1)
   194  			_ = dc.Decode(&v1)
   195  		}
   196  	})
   197  }
   198  
   199  // func BenchmarkDecodeError_Sonic(b *testing.B) {
   200  //     var str = `\b测试1234`
   201  //     for i:=0; i<b.N; i++ {
   202  //         var v1 map[string]interface{}
   203  //         _ = NewDecoder(str).Decode(&v1)
   204  //     }
   205  // }
   206  
   207  func BenchmarkDecodeStream_Sonic(b *testing.B) {
   208  	b.Run("single", func(b *testing.B) {
   209  		var str = _Single_JSON
   210  		for i := 0; i < b.N; i++ {
   211  			var r1 = strings.NewReader(str)
   212  			var v1 map[string]interface{}
   213  			dc := NewStreamDecoder(r1)
   214  			_ = dc.Decode(&v1)
   215  			_ = dc.Decode(&v1)
   216  		}
   217  	})
   218  
   219  	b.Run("double", func(b *testing.B) {
   220  		var str = _Double_JSON
   221  		for i := 0; i < b.N; i++ {
   222  			var r1 = strings.NewReader(str)
   223  			var v1 map[string]interface{}
   224  			dc := NewStreamDecoder(r1)
   225  			_ = dc.Decode(&v1)
   226  			_ = dc.Decode(&v1)
   227  		}
   228  	})
   229  
   230  	b.Run("halt", func(b *testing.B) {
   231  		var str = _Double_JSON
   232  		for i := 0; i < b.N; i++ {
   233  			var r1 = NewHaltReader(str, testHalts())
   234  			var v1 map[string]interface{}
   235  			dc := NewStreamDecoder(r1)
   236  			_ = dc.Decode(&v1)
   237  		}
   238  	})
   239  }