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 }