github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/ast/iterator_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  	"fmt"
    21  	"strconv"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  func getTestIteratorSample(loop int) (string, int) {
    29  	var data []int
    30  	var v1 = ""
    31  	var v2 = ""
    32  	for i := 0; i < loop; i++ {
    33  		data = append(data, i*i)
    34  		v1 += strconv.Itoa(i)
    35  		v2 += `"k` + strconv.Itoa(i) + `":` + strconv.Itoa(i)
    36  		if i != loop-1 {
    37  			v1 += `,`
    38  			v2 += `,`
    39  		}
    40  	}
    41  	return `{"array":[` + v1 + `], "object":{` + v2 + `}}`, loop
    42  }
    43  
    44  func TestForEach(t *testing.T) {
    45  	pathes := []Sequence{}
    46  	values := []*Node{}
    47  	sc := func(path Sequence, node *Node) bool {
    48  		pathes = append(pathes, path)
    49  		values = append(values, node)
    50  		if path.Key != nil && *path.Key == "array" {
    51  			node.ForEach(func(path Sequence, node *Node) bool {
    52  				pathes = append(pathes, path)
    53  				values = append(values, node)
    54  				return true
    55  			})
    56  		}
    57  		return true
    58  	}
    59  
    60  	str, _ := getTestIteratorSample(3)
    61  	fmt.Println(str)
    62  	root, err := NewSearcher(str).GetByPath()
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  	err = root.ForEach(sc)
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	eObjKey := "object"
    71  	eArrKey := "array"
    72  	expPath := []Sequence{
    73  		{0, &eArrKey},
    74  		{0, nil},
    75  		{1, nil},
    76  		{2, nil},
    77  		{1, &eObjKey},
    78  	}
    79  	expValue := []*Node{
    80  		root.Get("array"),
    81  		root.GetByPath("array", 0),
    82  		root.GetByPath("array", 1),
    83  		root.GetByPath("array", 2),
    84  		root.Get("object"),
    85  	}
    86  	// fmt.Printf("pathes:%+v\n", pathes)
    87  	// fmt.Printf("values:%+v\n", values)
    88  	assert.Equal(t, expPath, pathes)
    89  	assert.Equal(t, expValue, values)
    90  
    91  }
    92  
    93  func TestRawIterator(t *testing.T) {
    94  	str, loop := getTestIteratorSample(_DEFAULT_NODE_CAP)
    95  	fmt.Println(str)
    96  
    97  	root, err := NewSearcher(str).GetByPath("array")
    98  	if err != nil {
    99  		t.Fatal(err)
   100  	}
   101  	ai, _ := root.Values()
   102  	i := int64(0)
   103  	for ai.HasNext() {
   104  		v := &Node{}
   105  		if !ai.Next(v) {
   106  			t.Fatalf("no next")
   107  		}
   108  		x, _ := v.Int64()
   109  		if i < int64(loop) && x != i {
   110  			t.Fatalf("exp:%v, got:%v", i, v)
   111  		}
   112  		if i != int64(ai.Pos())-1 || i >= int64(ai.Len()) {
   113  			t.Fatal(i)
   114  		}
   115  		i++
   116  	}
   117  	if i != int64(loop) {
   118  		t.Fatal(i)
   119  	}
   120  
   121  	root, err = NewSearcher(str).GetByPath("object")
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	mi, _ := root.Properties()
   126  	i = int64(0)
   127  	for mi.HasNext() {
   128  		v := &Pair{}
   129  		if !mi.Next(v) {
   130  			t.Fatalf("no next")
   131  		}
   132  		x, _ := v.Value.Int64()
   133  		if i < int64(loop) && (x != i || v.Key != fmt.Sprintf("k%d", i)) {
   134  			vv, _ := v.Value.Interface()
   135  			t.Fatalf("exp:%v, got:%v", i, vv)
   136  		}
   137  		if i != int64(mi.Pos())-1 || i >= int64(mi.Len()) {
   138  			t.Fatal(i)
   139  		}
   140  		i++
   141  	}
   142  	if i != int64(loop) {
   143  		t.Fatal(i)
   144  	}
   145  }
   146  
   147  func TestIterator(t *testing.T) {
   148  	str, loop := getTestIteratorSample(_DEFAULT_NODE_CAP)
   149  	fmt.Println(str)
   150  
   151  	root, err := NewParser(str).Parse()
   152  	if err != 0 {
   153  		t.Fatal(err)
   154  	}
   155  	ai, _ := root.Get("array").Values()
   156  	i := int64(0)
   157  	for ai.HasNext() {
   158  		v := &Node{}
   159  		if !ai.Next(v) {
   160  			t.Fatalf("no next")
   161  		}
   162  		x, _ := v.Int64()
   163  		if i < int64(loop) && x != i {
   164  			t.Fatalf("exp:%v, got:%v", i, v)
   165  		}
   166  		if i != int64(ai.Pos())-1 || i >= int64(ai.Len()) {
   167  			t.Fatal(i)
   168  		}
   169  		i++
   170  	}
   171  	if i != int64(loop) {
   172  		t.Fatal(i)
   173  	}
   174  
   175  	root, err = NewParser(str).Parse()
   176  	if err != 0 {
   177  		t.Fatal(err)
   178  	}
   179  	mi, _ := root.Get("object").Properties()
   180  	i = int64(0)
   181  	for mi.HasNext() {
   182  		v := &Pair{}
   183  		if !mi.Next(v) {
   184  			t.Fatalf("no next")
   185  		}
   186  		x, _ := v.Value.Int64()
   187  		if i < int64(loop) && (x != i || v.Key != fmt.Sprintf("k%d", i)) {
   188  			vv, _ := v.Value.Interface()
   189  			t.Fatalf("exp:%v, got:%v", i, vv)
   190  		}
   191  		if i != int64(mi.Pos())-1 || i >= int64(mi.Len()) {
   192  			t.Fatal(i)
   193  		}
   194  		i++
   195  	}
   196  	if i != int64(loop) {
   197  		t.Fatal(i)
   198  	}
   199  
   200  	str, _ = getTestIteratorSample(0)
   201  	root, err = NewParser(str).Parse()
   202  	if err != 0 {
   203  		t.Fatal(err)
   204  	}
   205  	mi, _ = root.Get("object").Properties()
   206  	if mi.HasNext() {
   207  		t.Fatalf("should not have next")
   208  	}
   209  }
   210  
   211  func TestExist(t *testing.T) {
   212  	n := NewRaw(`null`)
   213  	if !n.Exists() {
   214  		t.Fatal()
   215  	}
   216  	nn := n.Get("xx")
   217  	if nn.Exists() {
   218  		t.Fatal()
   219  	}
   220  
   221  	root := NewRaw(`{"a":1, "b":[1,2], "c":{"1":1, "2":2}}`)
   222  	if !root.Exists() {
   223  		t.Fatal()
   224  	}
   225  	exi, err := root.Unset("a")
   226  	if !exi || err != nil {
   227  		t.Fatal(exi, err)
   228  	}
   229  
   230  	root.ForEach(func(path Sequence, node *Node) bool {
   231  		if path.Key != nil && *path.Key == "a" {
   232  			t.Fatal()
   233  		}
   234  		if path.Index == 1 {
   235  			if *path.Key != "b" {
   236  				t.Fatal()
   237  			}
   238  			exi, err := node.UnsetByIndex(1)
   239  			if !exi || err != nil {
   240  				t.Fatal(exi, err)
   241  			}
   242  			node.ForEach(func(path Sequence, node *Node) bool {
   243  				if path.Index == 1 {
   244  					t.Fatal()
   245  				}
   246  				return true
   247  			})
   248  		}
   249  
   250  		if path.Index == 2 {
   251  			if *path.Key != "c" {
   252  				t.Fatal()
   253  			}
   254  			exi, err := node.UnsetByIndex(1)
   255  			if !exi || err != nil {
   256  				t.Fatal(exi, err)
   257  			}
   258  			node.ForEach(func(path Sequence, node *Node) bool {
   259  				if path.Index == 1 {
   260  					t.Fatal()
   261  				}
   262  				return true
   263  			})
   264  		}
   265  		return true
   266  	})
   267  
   268  	out, err := root.Raw()
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  	require.Equal(t, `{"b":[1],"c":{"1":1}}`, out)
   273  
   274  }
   275  
   276  func BenchmarkArrays(b *testing.B) {
   277  	for i := 0; i < b.N; i++ {
   278  		root, err := NewSearcher(_TwitterJson).GetByPath("statuses", 1, "entities", "hashtags")
   279  		if err != nil {
   280  			b.Fatal(err)
   281  		}
   282  		a, _ := root.Array()
   283  		for _, v := range a {
   284  			_ = v
   285  		}
   286  	}
   287  }
   288  
   289  func BenchmarkListIterator(b *testing.B) {
   290  	for i := 0; i < b.N; i++ {
   291  		root, err := NewSearcher(_TwitterJson).GetByPath("statuses", 1, "entities", "hashtags")
   292  		if err != nil {
   293  			b.Fatal(err)
   294  		}
   295  		it, _ := root.Values()
   296  		for it.HasNext() {
   297  			v := &Node{}
   298  			if !it.Next(v) {
   299  				b.Fatalf("no value")
   300  			}
   301  		}
   302  	}
   303  }
   304  
   305  func BenchmarkMap(b *testing.B) {
   306  	for i := 0; i < b.N; i++ {
   307  		root, err := NewSearcher(_TwitterJson).GetByPath("statuses", 1, "user")
   308  		if err != nil {
   309  			b.Fatal(err)
   310  		}
   311  		m, _ := root.Map()
   312  		for k, v := range m {
   313  			_ = v
   314  			_ = k
   315  		}
   316  	}
   317  }
   318  
   319  func BenchmarkObjectIterator(b *testing.B) {
   320  	for i := 0; i < b.N; i++ {
   321  		root, err := NewSearcher(_TwitterJson).GetByPath("statuses", 1, "user")
   322  		if err != nil {
   323  			b.Fatal(err)
   324  		}
   325  		it, _ := root.Properties()
   326  		for it.HasNext() {
   327  			v := &Pair{}
   328  			if !it.Next(v) {
   329  				b.Fatalf("no value")
   330  			}
   331  		}
   332  	}
   333  }