github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/ast/parser_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 ast
    18  
    19  import (
    20  	"encoding/json"
    21  	"os"
    22  	"runtime"
    23  	"runtime/debug"
    24  	"sync"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  var (
    33  	debugSyncGC  = os.Getenv("SONIC_SYNC_GC") != ""
    34  	debugAsyncGC = os.Getenv("SONIC_NO_ASYNC_GC") == ""
    35  )
    36  
    37  func TestMain(m *testing.M) {
    38  	go func() {
    39  		if !debugAsyncGC {
    40  			return
    41  		}
    42  		println("Begin GC looping...")
    43  		for {
    44  			runtime.GC()
    45  			debug.FreeOSMemory()
    46  		}
    47  		println("stop GC looping!")
    48  	}()
    49  	time.Sleep(time.Millisecond)
    50  	m.Run()
    51  }
    52  
    53  func TestGC_Parse(t *testing.T) {
    54  	if debugSyncGC {
    55  		return
    56  	}
    57  	_, _, err := Loads(_TwitterJson)
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  	wg := &sync.WaitGroup{}
    62  	N := 1000
    63  	for i := 0; i < N; i++ {
    64  		wg.Add(1)
    65  		go func(wg *sync.WaitGroup) {
    66  			defer wg.Done()
    67  			_, _, err := Loads(_TwitterJson)
    68  			if err != nil {
    69  				t.Error(err)
    70  				return
    71  			}
    72  			runtime.GC()
    73  		}(wg)
    74  	}
    75  	wg.Wait()
    76  }
    77  
    78  func runDecoderTest(t *testing.T, src string, expect interface{}) {
    79  	vv, err := NewParser(src).Parse()
    80  	if err != 0 {
    81  		panic(err)
    82  	}
    83  	x, _ := vv.Interface()
    84  	assert.Equal(t, expect, x)
    85  }
    86  
    87  func runDecoderTestUseNumber(t *testing.T, src string, expect interface{}) {
    88  	vv, err := NewParser(src).Parse()
    89  	if err != 0 {
    90  		panic(err)
    91  	}
    92  	vvv, _ := vv.InterfaceUseNumber()
    93  	switch vvv.(type) {
    94  	case json.Number:
    95  		assert.Equal(t, expect, n2f64(vvv.(json.Number)))
    96  	case []interface{}:
    97  		x := vvv.([]interface{})
    98  		for i, e := range x {
    99  			if ev, ok := e.(json.Number); ok {
   100  				x[i] = n2f64(ev)
   101  			}
   102  		}
   103  		assert.Equal(t, expect, x)
   104  	case map[string]interface{}:
   105  		x := vvv.(map[string]interface{})
   106  		for k, v := range x {
   107  			if ev, ok := v.(json.Number); ok {
   108  				x[k] = n2f64(ev)
   109  			}
   110  		}
   111  		assert.Equal(t, expect, x)
   112  	}
   113  }
   114  
   115  func n2f64(i json.Number) float64 {
   116  	x, err := i.Float64()
   117  	if err != nil {
   118  		panic(err)
   119  	}
   120  	return x
   121  }
   122  
   123  func TestParser_Basic(t *testing.T) {
   124  	runDecoderTest(t, `null`, nil)
   125  	runDecoderTest(t, `true`, true)
   126  	runDecoderTest(t, `false`, false)
   127  	runDecoderTest(t, `"hello, world \\ \/ \b \f \n \r \t \u666f 测试中文"`, "hello, world \\ / \b \f \n \r \t \u666f 测试中文")
   128  	runDecoderTest(t, `"\ud83d\ude00"`, "😀")
   129  	runDecoderTest(t, `0`, float64(0))
   130  	runDecoderTest(t, `-0`, float64(0))
   131  	runDecoderTest(t, `123456`, float64(123456))
   132  	runDecoderTest(t, `-12345`, float64(-12345))
   133  	runDecoderTest(t, `0.2`, 0.2)
   134  	runDecoderTest(t, `1.2`, 1.2)
   135  	runDecoderTest(t, `-0.2`, -0.2)
   136  	runDecoderTest(t, `-1.2`, -1.2)
   137  	runDecoderTest(t, `0e12`, 0e12)
   138  	runDecoderTest(t, `0e+12`, 0e+12)
   139  	runDecoderTest(t, `0e-12`, 0e-12)
   140  	runDecoderTest(t, `-0e12`, -0e12)
   141  	runDecoderTest(t, `-0e+12`, -0e+12)
   142  	runDecoderTest(t, `-0e-12`, -0e-12)
   143  	runDecoderTest(t, `2e12`, 2e12)
   144  	runDecoderTest(t, `2E12`, 2e12)
   145  	runDecoderTest(t, `2e+12`, 2e+12)
   146  	runDecoderTest(t, `2e-12`, 2e-12)
   147  	runDecoderTest(t, `-2e12`, -2e12)
   148  	runDecoderTest(t, `-2e+12`, -2e+12)
   149  	runDecoderTest(t, `-2e-12`, -2e-12)
   150  	runDecoderTest(t, `0.2e12`, 0.2e12)
   151  	runDecoderTest(t, `0.2e+12`, 0.2e+12)
   152  	runDecoderTest(t, `0.2e-12`, 0.2e-12)
   153  	runDecoderTest(t, `-0.2e12`, -0.2e12)
   154  	runDecoderTest(t, `-0.2e+12`, -0.2e+12)
   155  	runDecoderTest(t, `-0.2e-12`, -0.2e-12)
   156  	runDecoderTest(t, `1.2e12`, 1.2e12)
   157  	runDecoderTest(t, `1.2e+12`, 1.2e+12)
   158  	runDecoderTest(t, `1.2e-12`, 1.2e-12)
   159  	runDecoderTest(t, `-1.2e12`, -1.2e12)
   160  	runDecoderTest(t, `-1.2e+12`, -1.2e+12)
   161  	runDecoderTest(t, `-1.2e-12`, -1.2e-12)
   162  	runDecoderTest(t, `-1.2E-12`, -1.2e-12)
   163  	runDecoderTest(t, `[]`, []interface{}{})
   164  	runDecoderTest(t, `{}`, map[string]interface{}{})
   165  	runDecoderTest(t, `["asd", "123", true, false, null, 2.4, 1.2e15]`, []interface{}{"asd", "123", true, false, nil, 2.4, 1.2e15})
   166  	runDecoderTest(t, `{"asdf": "qwer", "zxcv": true}`, map[string]interface{}{"asdf": "qwer", "zxcv": true})
   167  	runDecoderTest(t, `{"a": "123", "b": true, "c": false, "d": null, "e": 2.4, "f": 1.2e15, "g": 1}`, map[string]interface{}{"a": "123", "b": true, "c": false, "d": nil, "e": 2.4, "f": 1.2e15, "g": float64(1)})
   168  
   169  	runDecoderTestUseNumber(t, `null`, nil)
   170  	runDecoderTestUseNumber(t, `true`, true)
   171  	runDecoderTestUseNumber(t, `false`, false)
   172  	runDecoderTestUseNumber(t, `"hello, world \\ \/ \b \f \n \r \t \u666f 测试中文"`, "hello, world \\ / \b \f \n \r \t \u666f 测试中文")
   173  	runDecoderTestUseNumber(t, `"\ud83d\ude00"`, "😀")
   174  	runDecoderTestUseNumber(t, `0`, float64(0))
   175  	runDecoderTestUseNumber(t, `-0`, float64(0))
   176  	runDecoderTestUseNumber(t, `123456`, float64(123456))
   177  	runDecoderTestUseNumber(t, `-12345`, float64(-12345))
   178  	runDecoderTestUseNumber(t, `0.2`, 0.2)
   179  	runDecoderTestUseNumber(t, `1.2`, 1.2)
   180  	runDecoderTestUseNumber(t, `-0.2`, -0.2)
   181  	runDecoderTestUseNumber(t, `-1.2`, -1.2)
   182  	runDecoderTestUseNumber(t, `0e12`, 0e12)
   183  	runDecoderTestUseNumber(t, `0e+12`, 0e+12)
   184  	runDecoderTestUseNumber(t, `0e-12`, 0e-12)
   185  	runDecoderTestUseNumber(t, `-0e12`, -0e12)
   186  	runDecoderTestUseNumber(t, `-0e+12`, -0e+12)
   187  	runDecoderTestUseNumber(t, `-0e-12`, -0e-12)
   188  	runDecoderTestUseNumber(t, `2e12`, 2e12)
   189  	runDecoderTestUseNumber(t, `2E12`, 2e12)
   190  	runDecoderTestUseNumber(t, `2e+12`, 2e+12)
   191  	runDecoderTestUseNumber(t, `2e-12`, 2e-12)
   192  	runDecoderTestUseNumber(t, `-2e12`, -2e12)
   193  	runDecoderTestUseNumber(t, `-2e+12`, -2e+12)
   194  	runDecoderTestUseNumber(t, `-2e-12`, -2e-12)
   195  	runDecoderTestUseNumber(t, `0.2e12`, 0.2e12)
   196  	runDecoderTestUseNumber(t, `0.2e+12`, 0.2e+12)
   197  	runDecoderTestUseNumber(t, `0.2e-12`, 0.2e-12)
   198  	runDecoderTestUseNumber(t, `-0.2e12`, -0.2e12)
   199  	runDecoderTestUseNumber(t, `-0.2e+12`, -0.2e+12)
   200  	runDecoderTestUseNumber(t, `-0.2e-12`, -0.2e-12)
   201  	runDecoderTestUseNumber(t, `1.2e12`, 1.2e12)
   202  	runDecoderTestUseNumber(t, `1.2e+12`, 1.2e+12)
   203  	runDecoderTestUseNumber(t, `1.2e-12`, 1.2e-12)
   204  	runDecoderTestUseNumber(t, `-1.2e12`, -1.2e12)
   205  	runDecoderTestUseNumber(t, `-1.2e+12`, -1.2e+12)
   206  	runDecoderTestUseNumber(t, `-1.2e-12`, -1.2e-12)
   207  	runDecoderTestUseNumber(t, `-1.2E-12`, -1.2e-12)
   208  	runDecoderTestUseNumber(t, `["asd", "123", true, false, null, 2.4, 1.2e15, 1]`, []interface{}{"asd", "123", true, false, nil, 2.4, 1.2e15, float64(1)})
   209  	runDecoderTestUseNumber(t, `{"a": "123", "b": true, "c": false, "d": null, "e": 2.4, "f": 1.2e15, "g": 1}`, map[string]interface{}{"a": "123", "b": true, "c": false, "d": nil, "e": 2.4, "f": 1.2e15, "g": float64(1)})
   210  }
   211  
   212  func TestLoads(t *testing.T) {
   213  	_, i, e := Loads(`{"a": "123", "b": true, "c": false, "d": null, "e": 2.4, "f": 1.2e15, "g": 1}`)
   214  	if e != nil {
   215  		t.Fatal(e)
   216  	}
   217  	assert.Equal(t, map[string]interface{}{"a": "123", "b": true, "c": false, "d": nil, "e": 2.4, "f": 1.2e15, "g": float64(1)}, i)
   218  	_, i, e = LoadsUseNumber(`{"a": "123", "b": true, "c": false, "d": null, "e": 2.4, "f": 1.2e15, "g": 1}`)
   219  	if e != nil {
   220  		t.Fatal(e)
   221  	}
   222  	assert.Equal(t, map[string]interface{}{"a": "123", "b": true, "c": false, "d": nil, "e": json.Number("2.4"), "f": json.Number("1.2e15"), "g": json.Number("1")}, i)
   223  }
   224  
   225  func TestParsehNotExist(t *testing.T) {
   226  	s, err := NewParser(` { "xx" : [ 0, "" ] ,"yy" :{ "2": "" } } `).Parse()
   227  	if err != 0 {
   228  		t.Fatal(err)
   229  	}
   230  	node := s.GetByPath("xx", 2)
   231  	if node.Exists() {
   232  		t.Fatalf("node: %v", node)
   233  	}
   234  	node = s.GetByPath("xx", 1)
   235  	if !node.Exists() {
   236  		t.Fatalf("node: %v", nil)
   237  	}
   238  	node = s.GetByPath("yy", "3")
   239  	if node.Exists() {
   240  		t.Fatalf("node: %v", node)
   241  	}
   242  	node = s.GetByPath("yy", "2")
   243  	if !node.Exists() {
   244  		t.Fatalf("node: %v", nil)
   245  	}
   246  }
   247  
   248  func BenchmarkParser_Sonic(b *testing.B) {
   249  	r, err := NewParser(_TwitterJson).Parse()
   250  	if err != 0 {
   251  		b.Fatal(err)
   252  	}
   253  	if err := r.LoadAll(); err != nil {
   254  		b.Fatal(err)
   255  	}
   256  	b.SetBytes(int64(len(_TwitterJson)))
   257  	b.ResetTimer()
   258  	for i := 0; i < b.N; i++ {
   259  		r, _ = NewParser(_TwitterJson).Parse()
   260  		_ = r.LoadAll()
   261  	}
   262  }
   263  
   264  func BenchmarkParser_Parallel_Sonic(b *testing.B) {
   265  	r, _ := NewParser(_TwitterJson).Parse()
   266  	if err := r.LoadAll(); err != nil {
   267  		b.Fatal(err)
   268  	}
   269  	b.SetBytes(int64(len(_TwitterJson)))
   270  	b.ResetTimer()
   271  	b.RunParallel(func(pb *testing.PB) {
   272  		for pb.Next() {
   273  			r, _ := NewParser(_TwitterJson).Parse()
   274  			_ = r.LoadAll()
   275  		}
   276  	})
   277  }
   278  
   279  func BenchmarkParseEmpty_Sonic(b *testing.B) {
   280  	var emptySample = `{"a":[],"b":{},"c":[{},{},{},{}],"d":{"e":[],"f":[],"g":[],"h":[]}}`
   281  	p := NewParserObj(emptySample)
   282  	ast, _ := p.Parse()
   283  	require.NoError(b, ast.LoadAll())
   284  	b.SetBytes(int64(len(_TwitterJson)))
   285  	b.ResetTimer()
   286  	for i := 0; i < b.N; i++ {
   287  		p := NewParserObj(emptySample)
   288  		ast, _ := p.Parse()
   289  		_ = ast.LoadAll()
   290  	}
   291  }
   292  
   293  func BenchmarkParseOne_Sonic(b *testing.B) {
   294  	ast, _ := NewParser(_TwitterJson).Parse()
   295  	node, _ := ast.Get("statuses").Index(2).Get("id").Int64()
   296  	if node != 249289491129438208 {
   297  		b.Fail()
   298  	}
   299  	b.SetBytes(int64(len(_TwitterJson)))
   300  	b.ResetTimer()
   301  	for i := 0; i < b.N; i++ {
   302  		ast, _ := NewParser(_TwitterJson).Parse()
   303  		_, _ = ast.Get("statuses").Index(2).Get("id").Int64()
   304  	}
   305  }
   306  
   307  func BenchmarkParseOne_Parallel_Sonic(b *testing.B) {
   308  	ast, _ := NewParser(_TwitterJson).Parse()
   309  	node, _ := ast.Get("statuses").Index(2).Get("id").Int64()
   310  	if node != 249289491129438208 {
   311  		b.Fail()
   312  	}
   313  	b.SetBytes(int64(len(_TwitterJson)))
   314  	b.ResetTimer()
   315  	b.RunParallel(func(pb *testing.PB) {
   316  		for pb.Next() {
   317  			ast, _ := NewParser(_TwitterJson).Parse()
   318  			_, _ = ast.Get("statuses").Index(2).Get("id").Int64()
   319  		}
   320  	})
   321  }
   322  
   323  func BenchmarkParseSeven_Sonic(b *testing.B) {
   324  	b.SetBytes(int64(len(_TwitterJson)))
   325  	b.ResetTimer()
   326  	for i := 0; i < b.N; i++ {
   327  		ast, _ := NewParser(_TwitterJson).Parse()
   328  		node := ast.GetByPath("statuses", 3, "id")
   329  		node = ast.GetByPath("statuses", 3, "user", "entities", "description")
   330  		node = ast.GetByPath("statuses", 3, "user", "entities", "url", "urls")
   331  		node = ast.GetByPath("statuses", 3, "user", "entities", "url")
   332  		node = ast.GetByPath("statuses", 3, "user", "created_at")
   333  		node = ast.GetByPath("statuses", 3, "user", "name")
   334  		node = ast.GetByPath("statuses", 3, "text")
   335  		if node.Check() != nil {
   336  			b.Fail()
   337  		}
   338  	}
   339  }
   340  
   341  func BenchmarkParseSeven_Parallel_Sonic(b *testing.B) {
   342  	b.SetBytes(int64(len(_TwitterJson)))
   343  	b.ResetTimer()
   344  	b.RunParallel(func(pb *testing.PB) {
   345  		for pb.Next() {
   346  			ast, _ := NewParser(_TwitterJson).Parse()
   347  			node := ast.GetByPath("statuses", 3, "id")
   348  			node = ast.GetByPath("statuses", 3, "user", "entities", "description")
   349  			node = ast.GetByPath("statuses", 3, "user", "entities", "url", "urls")
   350  			node = ast.GetByPath("statuses", 3, "user", "entities", "url")
   351  			node = ast.GetByPath("statuses", 3, "user", "created_at")
   352  			node = ast.GetByPath("statuses", 3, "user", "name")
   353  			node = ast.GetByPath("statuses", 3, "text")
   354  			if node.Check() != nil {
   355  				b.Fail()
   356  			}
   357  		}
   358  	})
   359  }