github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/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 == 0 {
   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 == 1 {
   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  }