node_test.gno
31.81 Kb ยท 1392 lines
1package json
2
3import (
4 "bytes"
5 "sort"
6 "strconv"
7 "strings"
8 "testing"
9
10 "gno.land/p/demo/ufmt"
11)
12
13var (
14 nilKey *string
15 dummyKey = "key"
16)
17
18type _args struct {
19 prev *Node
20 buf *buffer
21 typ ValueType
22 key **string
23}
24
25type simpleNode struct {
26 name string
27 node *Node
28}
29
30func TestNode_CreateNewNode(t *testing.T) {
31 rel := &dummyKey
32
33 tests := []struct {
34 name string
35 args _args
36 expectCurr *Node
37 expectErr bool
38 expectPanic bool
39 }{
40 {
41 name: "child for non container type",
42 args: _args{
43 prev: BoolNode("", true),
44 buf: newBuffer(make([]byte, 10)),
45 typ: Boolean,
46 key: &rel,
47 },
48 expectCurr: nil,
49 expectErr: true,
50 },
51 }
52
53 for _, tt := range tests {
54 t.Run(tt.name, func(t *testing.T) {
55 defer func() {
56 if r := recover(); r != nil {
57 if tt.expectPanic {
58 return
59 }
60 t.Errorf("%s panic occurred when not expected: %v", tt.name, r)
61 } else if tt.expectPanic {
62 t.Errorf("%s expected panic but didn't occur", tt.name)
63 }
64 }()
65
66 got, err := NewNode(tt.args.prev, tt.args.buf, tt.args.typ, tt.args.key)
67 if (err != nil) != tt.expectErr {
68 t.Errorf("%s error = %v, expect error %v", tt.name, err, tt.expectErr)
69 return
70 }
71
72 if tt.expectErr {
73 return
74 }
75
76 if !compareNodes(got, tt.expectCurr) {
77 t.Errorf("%s got = %v, want %v", tt.name, got, tt.expectCurr)
78 }
79 })
80 }
81}
82
83func TestNode_Value(t *testing.T) {
84 tests := []struct {
85 name string
86 data []byte
87 _type ValueType
88 expected any
89 errExpected bool
90 }{
91 {name: "null", data: []byte("null"), _type: Null, expected: nil},
92 {name: "1", data: []byte("1"), _type: Number, expected: float64(1)},
93 {name: ".1", data: []byte(".1"), _type: Number, expected: float64(.1)},
94 {name: "-.1e1", data: []byte("-.1e1"), _type: Number, expected: float64(-1)},
95 {name: "string", data: []byte("\"foo\""), _type: String, expected: "foo"},
96 {name: "space", data: []byte("\"foo bar\""), _type: String, expected: "foo bar"},
97 {name: "true", data: []byte("true"), _type: Boolean, expected: true},
98 {name: "invalid true", data: []byte("tru"), _type: Unknown, errExpected: true},
99 {name: "invalid false", data: []byte("fals"), _type: Unknown, errExpected: true},
100 {name: "false", data: []byte("false"), _type: Boolean, expected: false},
101 {name: "e1", data: []byte("e1"), _type: Unknown, errExpected: true},
102 {name: "1a", data: []byte("1a"), _type: Unknown, errExpected: true},
103 {name: "string error", data: []byte("\"foo\nbar\""), _type: String, errExpected: true},
104 }
105
106 for _, tt := range tests {
107 t.Run(tt.name, func(t *testing.T) {
108 curr := &Node{
109 data: tt.data,
110 nodeType: tt._type,
111 borders: [2]int{0, len(tt.data)},
112 }
113
114 got, err := curr.Value()
115 if err != nil {
116 if !tt.errExpected {
117 t.Errorf("%s error = %v, expect error %v", tt.name, err, tt.errExpected)
118 }
119 return
120 }
121
122 if got != tt.expected {
123 t.Errorf("%s got = %v, want %v", tt.name, got, tt.expected)
124 }
125 })
126 }
127}
128
129func TestNode_Delete(t *testing.T) {
130 root := Must(Unmarshal([]byte(`{"foo":"bar"}`)))
131 if err := root.Delete(); err != nil {
132 t.Errorf("Delete returns error: %v", err)
133 }
134
135 if value, err := Marshal(root); err != nil {
136 t.Errorf("Marshal returns error: %v", err)
137 } else if string(value) != `{"foo":"bar"}` {
138 t.Errorf("Marshal returns wrong value: %s", string(value))
139 }
140
141 foo := root.MustKey("foo")
142 if err := foo.Delete(); err != nil {
143 t.Errorf("Delete returns error while handling foo: %v", err)
144 }
145
146 if value, err := Marshal(root); err != nil {
147 t.Errorf("Marshal returns error: %v", err)
148 } else if string(value) != `{}` {
149 t.Errorf("Marshal returns wrong value: %s", string(value))
150 }
151
152 if value, err := Marshal(foo); err != nil {
153 t.Errorf("Marshal returns error: %v", err)
154 } else if string(value) != `"bar"` {
155 t.Errorf("Marshal returns wrong value: %s", string(value))
156 }
157
158 if foo.prev != nil {
159 t.Errorf("foo.prev should be nil")
160 }
161}
162
163func TestNode_ObjectNode(t *testing.T) {
164 objs := map[string]*Node{
165 "key1": NullNode("null"),
166 "key2": NumberNode("answer", 42),
167 "key3": StringNode("string", "foobar"),
168 "key4": BoolNode("bool", true),
169 }
170
171 node := ObjectNode("test", objs)
172
173 if len(node.next) != len(objs) {
174 t.Errorf("ObjectNode: want %v got %v", len(objs), len(node.next))
175 }
176
177 for k, v := range objs {
178 if node.next[k] == nil {
179 t.Errorf("ObjectNode: want %v got %v", v, node.next[k])
180 }
181 }
182}
183
184func TestNode_AppendObject(t *testing.T) {
185 if err := Must(Unmarshal([]byte(`{"foo":"bar","baz":null}`))).AppendObject("biz", NullNode("")); err != nil {
186 t.Errorf("AppendArray should return error")
187 }
188
189 root := Must(Unmarshal([]byte(`{"foo":"bar"}`)))
190 if err := root.AppendObject("baz", NullNode("")); err != nil {
191 t.Errorf("AppendObject should not return error: %s", err)
192 }
193
194 if value, err := Marshal(root); err != nil {
195 t.Errorf("Marshal returns error: %v", err)
196 } else if isSameObject(string(value), `"{"foo":"bar","baz":null}"`) {
197 t.Errorf("Marshal returns wrong value: %s", string(value))
198 }
199
200 // FIXME: this may fail if execute test in more than 3 times in a row.
201 if err := root.AppendObject("biz", NumberNode("", 42)); err != nil {
202 t.Errorf("AppendObject returns error: %v", err)
203 }
204
205 val, err := Marshal(root)
206 if err != nil {
207 t.Errorf("Marshal returns error: %v", err)
208 }
209
210 // FIXME: this may fail if execute test in more than 3 times in a row.
211 if isSameObject(string(val), `"{"foo":"bar","baz":null,"biz":42}"`) {
212 t.Errorf("Marshal returns wrong value: %s", string(val))
213 }
214}
215
216func TestNode_ArrayNode(t *testing.T) {
217 arr := []*Node{
218 NullNode("nil"),
219 NumberNode("num", 42),
220 StringNode("str", "foobar"),
221 BoolNode("bool", true),
222 }
223
224 node := ArrayNode("test", arr)
225
226 if len(node.next) != len(arr) {
227 t.Errorf("ArrayNode: want %v got %v", len(arr), len(node.next))
228 }
229
230 for i, v := range arr {
231 if node.next[strconv.Itoa(i)] == nil {
232 t.Errorf("ArrayNode: want %v got %v", v, node.next[strconv.Itoa(i)])
233 }
234 }
235}
236
237func TestNode_AppendArray(t *testing.T) {
238 if err := Must(Unmarshal([]byte(`[{"foo":"bar"}]`))).AppendArray(NullNode("")); err != nil {
239 t.Errorf("should return error")
240 }
241
242 root := Must(Unmarshal([]byte(`[{"foo":"bar"}]`)))
243 if err := root.AppendArray(NullNode("")); err != nil {
244 t.Errorf("should not return error: %s", err)
245 }
246
247 if value, err := Marshal(root); err != nil {
248 t.Errorf("Marshal returns error: %v", err)
249 } else if string(value) != `[{"foo":"bar"},null]` {
250 t.Errorf("Marshal returns wrong value: %s", string(value))
251 }
252
253 if err := root.AppendArray(
254 NumberNode("", 1),
255 StringNode("", "foo"),
256 Must(Unmarshal([]byte(`[0,1,null,true,"example"]`))),
257 Must(Unmarshal([]byte(`{"foo": true, "bar": null, "baz": 123}`))),
258 ); err != nil {
259 t.Errorf("AppendArray returns error: %v", err)
260 }
261
262 if value, err := Marshal(root); err != nil {
263 t.Errorf("Marshal returns error: %v", err)
264 } else if string(value) != `[{"foo":"bar"},null,1,"foo",[0,1,null,true,"example"],{"foo": true, "bar": null, "baz": 123}]` {
265 t.Errorf("Marshal returns wrong value: %s", string(value))
266 }
267}
268
269/******** value getter ********/
270
271func TestNode_GetBool(t *testing.T) {
272 root, err := Unmarshal([]byte(`true`))
273 if err != nil {
274 t.Errorf("Error on Unmarshal(): %s", err.Error())
275 return
276 }
277
278 value, err := root.GetBool()
279 if err != nil {
280 t.Errorf("Error on root.GetBool(): %s", err.Error())
281 }
282
283 if !value {
284 t.Errorf("root.GetBool() is corrupted")
285 }
286}
287
288func TestNode_GetBool_NotSucceed(t *testing.T) {
289 tests := []simpleNode{
290 {"nil node", (*Node)(nil)},
291 {"literally null node", NullNode("")},
292 }
293
294 for _, tt := range tests {
295 t.Run(tt.name, func(t *testing.T) {
296 if _, err := tt.node.GetBool(); err == nil {
297 t.Errorf("%s should be an error", tt.name)
298 }
299 })
300 }
301}
302
303func TestNode_IsBool(t *testing.T) {
304 tests := []simpleNode{
305 {"true", BoolNode("", true)},
306 {"false", BoolNode("", false)},
307 }
308
309 for _, tt := range tests {
310 t.Run(tt.name, func(t *testing.T) {
311 if !tt.node.IsBool() {
312 t.Errorf("%s should be a bool", tt.name)
313 }
314 })
315 }
316}
317
318func TestNode_IsBool_With_Unmarshal(t *testing.T) {
319 tests := []struct {
320 name string
321 json []byte
322 want bool
323 }{
324 {"true", []byte("true"), true},
325 {"false", []byte("false"), true},
326 }
327
328 for _, tt := range tests {
329 t.Run(tt.name, func(t *testing.T) {
330 root, err := Unmarshal(tt.json)
331 if err != nil {
332 t.Errorf("Error on Unmarshal(): %s", err.Error())
333 }
334
335 if root.IsBool() != tt.want {
336 t.Errorf("%s should be a bool", tt.name)
337 }
338 })
339 }
340}
341
342var nullJson = []byte(`null`)
343
344func TestNode_GetNull(t *testing.T) {
345 root, err := Unmarshal(nullJson)
346 if err != nil {
347 t.Errorf("Error on Unmarshal(): %s", err.Error())
348 }
349
350 value, err := root.GetNull()
351 if err != nil {
352 t.Errorf("error occurred while getting null, %s", err)
353 }
354
355 if value != nil {
356 t.Errorf("value is not matched. expected: nil, got: %v", value)
357 }
358}
359
360func TestNode_GetNull_NotSucceed(t *testing.T) {
361 tests := []simpleNode{
362 {"nil node", (*Node)(nil)},
363 {"number node is null", NumberNode("", 42)},
364 }
365
366 for _, tt := range tests {
367 t.Run(tt.name, func(t *testing.T) {
368 if _, err := tt.node.GetNull(); err == nil {
369 t.Errorf("%s should be an error", tt.name)
370 }
371 })
372 }
373}
374
375func TestNode_MustNull(t *testing.T) {
376 root, err := Unmarshal(nullJson)
377 if err != nil {
378 t.Errorf("Error on Unmarshal(): %s", err.Error())
379 }
380
381 value := root.MustNull()
382 if value != nil {
383 t.Errorf("value is not matched. expected: nil, got: %v", value)
384 }
385}
386
387func TestNode_GetNumeric_Float(t *testing.T) {
388 root, err := Unmarshal([]byte(`123.456`))
389 if err != nil {
390 t.Errorf("Error on Unmarshal(): %s", err)
391 return
392 }
393
394 value, err := root.GetNumeric()
395 if err != nil {
396 t.Errorf("Error on root.GetNumeric(): %s", err)
397 }
398
399 if value != float64(123.456) {
400 t.Errorf(ufmt.Sprintf("value is not matched. expected: 123.456, got: %v", value))
401 }
402}
403
404func TestNode_GetNumeric_Scientific_Notation(t *testing.T) {
405 root, err := Unmarshal([]byte(`1e3`))
406 if err != nil {
407 t.Errorf("Error on Unmarshal(): %s", err)
408 return
409 }
410
411 value, err := root.GetNumeric()
412 if err != nil {
413 t.Errorf("Error on root.GetNumeric(): %s", err)
414 }
415
416 if value != float64(1000) {
417 t.Errorf(ufmt.Sprintf("value is not matched. expected: 1000, got: %v", value))
418 }
419}
420
421func TestNode_GetNumeric_With_Unmarshal(t *testing.T) {
422 root, err := Unmarshal([]byte(`123`))
423 if err != nil {
424 t.Errorf("Error on Unmarshal(): %s", err)
425 return
426 }
427
428 value, err := root.GetNumeric()
429 if err != nil {
430 t.Errorf("Error on root.GetNumeric(): %s", err)
431 }
432
433 if value != float64(123) {
434 t.Errorf(ufmt.Sprintf("value is not matched. expected: 123, got: %v", value))
435 }
436}
437
438func TestNode_GetNumeric_NotSucceed(t *testing.T) {
439 tests := []simpleNode{
440 {"nil node", (*Node)(nil)},
441 {"null node", NullNode("")},
442 {"string node", StringNode("", "123")},
443 }
444
445 for _, tt := range tests {
446 t.Run(tt.name, func(t *testing.T) {
447 if _, err := tt.node.GetNumeric(); err == nil {
448 t.Errorf("%s should be an error", tt.name)
449 }
450 })
451 }
452}
453
454func TestNode_GetString(t *testing.T) {
455 root, err := Unmarshal([]byte(`"123foobar 3456"`))
456 if err != nil {
457 t.Errorf("Error on Unmarshal(): %s", err)
458 }
459
460 value, err := root.GetString()
461 if err != nil {
462 t.Errorf("Error on root.GetString(): %s", err)
463 }
464
465 if value != "123foobar 3456" {
466 t.Errorf(ufmt.Sprintf("value is not matched. expected: 123, got: %s", value))
467 }
468}
469
470func TestNode_GetString_NotSucceed(t *testing.T) {
471 tests := []simpleNode{
472 {"nil node", (*Node)(nil)},
473 {"null node", NullNode("")},
474 {"number node", NumberNode("", 123)},
475 }
476
477 for _, tt := range tests {
478 t.Run(tt.name, func(t *testing.T) {
479 if _, err := tt.node.GetString(); err == nil {
480 t.Errorf("%s should be an error", tt.name)
481 }
482 })
483 }
484}
485
486func TestNode_MustString(t *testing.T) {
487 tests := []struct {
488 name string
489 data []byte
490 }{
491 {"foo", []byte(`"foo"`)},
492 {"foo bar", []byte(`"foo bar"`)},
493 {"", []byte(`""`)},
494 {"์๋
ํ์ธ์", []byte(`"์๋
ํ์ธ์"`)},
495 {"ใใใซใกใฏ", []byte(`"ใใใซใกใฏ"`)},
496 {"ไฝ ๅฅฝ", []byte(`"ไฝ ๅฅฝ"`)},
497 {"one \"encoded\" string", []byte(`"one \"encoded\" string"`)},
498 }
499
500 for _, tt := range tests {
501 t.Run(tt.name, func(t *testing.T) {
502 root, err := Unmarshal(tt.data)
503 if err != nil {
504 t.Errorf("Error on Unmarshal(): %s", err)
505 }
506
507 value := root.MustString()
508 if value != tt.name {
509 t.Errorf("value is not matched. expected: %s, got: %s", tt.name, value)
510 }
511 })
512 }
513}
514
515func TestUnmarshal_Array(t *testing.T) {
516 root, err := Unmarshal([]byte(" [1,[\"1\",[1,[1,2,3]]]]\r\n"))
517 if err != nil {
518 t.Errorf("Error on Unmarshal: %s", err.Error())
519 }
520
521 if root == nil {
522 t.Errorf("Error on Unmarshal: root is nil")
523 }
524
525 if root.Type() != Array {
526 t.Errorf("Error on Unmarshal: wrong type")
527 }
528
529 array, err := root.GetArray()
530 if err != nil {
531 t.Errorf("error occurred while getting array, %s", err)
532 } else if len(array) != 2 {
533 t.Errorf("expected 2 elements, got %d", len(array))
534 } else if val, err := array[0].GetNumeric(); err != nil {
535 t.Errorf("value of array[0] is not numeric. got: %v", array[0].value)
536 } else if val != 1 {
537 t.Errorf("Error on array[0].GetNumeric(): expected to be '1', got: %v", val)
538 } else if val, err := array[1].GetArray(); err != nil {
539 t.Errorf("error occurred while getting array, %s", err.Error())
540 } else if len(val) != 2 {
541 t.Errorf("Error on array[1].GetArray(): expected 2 elements, got %d", len(val))
542 } else if el, err := val[0].GetString(); err != nil {
543 t.Errorf("error occurred while getting string, %s", err.Error())
544 } else if el != "1" {
545 t.Errorf("Error on val[0].GetString(): expected to be '1', got: %s", el)
546 }
547}
548
549var sampleArr = []byte(`[-1, 2, 3, 4, 5, 6]`)
550
551func TestNode_GetArray(t *testing.T) {
552 root, err := Unmarshal(sampleArr)
553 if err != nil {
554 t.Errorf("Error on Unmarshal(): %s", err)
555 return
556 }
557
558 array, err := root.GetArray()
559 if err != nil {
560 t.Errorf("Error on root.GetArray(): %s", err)
561 }
562
563 if len(array) != 6 {
564 t.Errorf(ufmt.Sprintf("length is not matched. expected: 3, got: %d", len(array)))
565 }
566
567 for i, node := range array {
568 for j, val := range []int{-1, 2, 3, 4, 5, 6} {
569 if i == j {
570 if v, err := node.GetNumeric(); err != nil {
571 t.Errorf(ufmt.Sprintf("Error on node.GetNumeric(): %s", err))
572 } else if v != float64(val) {
573 t.Errorf(ufmt.Sprintf("value is not matched. expected: %d, got: %v", val, v))
574 }
575 }
576 }
577 }
578}
579
580func TestNode_GetArray_NotSucceed(t *testing.T) {
581 tests := []simpleNode{
582 {"nil node", (*Node)(nil)},
583 {"null node", NullNode("")},
584 {"number node", NumberNode("", 123)},
585 }
586
587 for _, tt := range tests {
588 t.Run(tt.name, func(t *testing.T) {
589 if _, err := tt.node.GetArray(); err == nil {
590 t.Errorf("%s should be an error", tt.name)
591 }
592 })
593 }
594}
595
596func TestNode_IsArray(t *testing.T) {
597 root, err := Unmarshal(sampleArr)
598 if err != nil {
599 t.Errorf("Error on Unmarshal(): %s", err)
600 return
601 }
602
603 if root.Type() != Array {
604 t.Errorf(ufmt.Sprintf("Must be an array. got: %s", root.Type().String()))
605 }
606}
607
608func TestNode_ArrayEach(t *testing.T) {
609 tests := []struct {
610 name string
611 json string
612 expected []int
613 }{
614 {
615 name: "empty array",
616 json: `[]`,
617 expected: []int{},
618 },
619 {
620 name: "single element",
621 json: `[42]`,
622 expected: []int{42},
623 },
624 {
625 name: "multiple elements",
626 json: `[1, 2, 3, 4, 5]`,
627 expected: []int{1, 2, 3, 4, 5},
628 },
629 {
630 name: "multiple elements but all values are same",
631 json: `[1, 1, 1, 1, 1]`,
632 expected: []int{1, 1, 1, 1, 1},
633 },
634 {
635 name: "multiple elements with non-numeric values",
636 json: `["a", "b", "c", "d", "e"]`,
637 expected: []int{},
638 },
639 {
640 name: "non-array node",
641 json: `{"not": "an array"}`,
642 expected: []int{},
643 },
644 {
645 name: "array containing numeric and non-numeric elements",
646 json: `["1", 2, 3, "4", 5, "6"]`,
647 expected: []int{2, 3, 5},
648 },
649 }
650
651 for _, tc := range tests {
652 t.Run(tc.name, func(t *testing.T) {
653 root, err := Unmarshal([]byte(tc.json))
654 if err != nil {
655 t.Fatalf("Unmarshal failed: %v", err)
656 }
657
658 var result []int // callback result
659 root.ArrayEach(func(index int, element *Node) {
660 if val, err := strconv.Atoi(element.String()); err == nil {
661 result = append(result, val)
662 }
663 })
664
665 if len(result) != len(tc.expected) {
666 t.Errorf("%s: expected %d elements, got %d", tc.name, len(tc.expected), len(result))
667 return
668 }
669
670 for i, val := range result {
671 if val != tc.expected[i] {
672 t.Errorf("%s: expected value at index %d to be %d, got %d", tc.name, i, tc.expected[i], val)
673 }
674 }
675 })
676 }
677}
678
679func TestNode_Key(t *testing.T) {
680 root, err := Unmarshal([]byte(`{"foo": true, "bar": null, "baz": 123, "biz": [1,2,3]}`))
681 if err != nil {
682 t.Errorf("Error on Unmarshal(): %s", err.Error())
683 }
684
685 obj := root.MustObject()
686 for key, node := range obj {
687 if key != node.Key() {
688 t.Errorf("Key() = %v, want %v", node.Key(), key)
689 }
690 }
691
692 keys := []string{"foo", "bar", "baz", "biz"}
693 for _, key := range keys {
694 if obj[key].Key() != key {
695 t.Errorf("Key() = %v, want %v", obj[key].Key(), key)
696 }
697 }
698
699 // TODO: resolve stack overflow
700 // if root.MustKey("foo").Clone().Key() != "" {
701 // t.Errorf("wrong key found for cloned key")
702 // }
703
704 if (*Node)(nil).Key() != "" {
705 t.Errorf("wrong key found for nil node")
706 }
707}
708
709func TestNode_Size(t *testing.T) {
710 root, err := Unmarshal(sampleArr)
711 if err != nil {
712 t.Errorf("error occurred while unmarshal")
713 }
714
715 size := root.Size()
716 if size != 6 {
717 t.Errorf(ufmt.Sprintf("Size() must be 6. got: %v", size))
718 }
719
720 if (*Node)(nil).Size() != 0 {
721 t.Errorf(ufmt.Sprintf("Size() must be 0. got: %v", (*Node)(nil).Size()))
722 }
723}
724
725func TestNode_Index(t *testing.T) {
726 root, err := Unmarshal([]byte(`[1, 2, 3, 4, 5, 6]`))
727 if err != nil {
728 t.Error("error occurred while unmarshal")
729 }
730
731 arr := root.MustArray()
732 for i, node := range arr {
733 if i != node.Index() {
734 t.Errorf(ufmt.Sprintf("Index() must be nil. got: %v", i))
735 }
736 }
737}
738
739func TestNode_Index_NotSucceed(t *testing.T) {
740 tests := []struct {
741 name string
742 node *Node
743 want int
744 }{
745 {"nil node", (*Node)(nil), -1},
746 {"null node", NullNode(""), -1},
747 {"object node", ObjectNode("", nil), -1},
748 }
749
750 for _, tt := range tests {
751 t.Run(tt.name, func(t *testing.T) {
752 if got := tt.node.Index(); got != tt.want {
753 t.Errorf("Index() = %v, want %v", got, tt.want)
754 }
755 })
756 }
757}
758
759func TestNode_GetIndex(t *testing.T) {
760 root := Must(Unmarshal([]byte(`[1, 2, 3, 4, 5, 6]`)))
761 expected := []int{1, 2, 3, 4, 5, 6}
762
763 if len(expected) != root.Size() {
764 t.Errorf("length is not matched. expected: %d, got: %d", len(expected), root.Size())
765 }
766
767 // TODO: if length exceeds, stack overflow occurs. need to fix
768 for i, v := range expected {
769 val, err := root.GetIndex(i)
770 if err != nil {
771 t.Errorf("error occurred while getting index %d, %s", i, err)
772 }
773
774 if val.MustNumeric() != float64(v) {
775 t.Errorf("value is not matched. expected: %d, got: %v", v, val.MustNumeric())
776 }
777 }
778}
779
780func TestNode_GetIndex_InputIndex_Exceed_Original_Node_Index(t *testing.T) {
781 root, err := Unmarshal([]byte(`[1, 2, 3, 4, 5, 6]`))
782 if err != nil {
783 t.Errorf("error occurred while unmarshal")
784 }
785
786 _, err = root.GetIndex(10)
787 if err == nil {
788 t.Errorf("GetIndex should return error")
789 }
790}
791
792func TestNode_DeleteIndex(t *testing.T) {
793 tests := []struct {
794 name string
795 expected string
796 index int
797 ok bool
798 }{
799 {`null`, ``, 0, false},
800 {`1`, ``, 0, false},
801 {`{}`, ``, 0, false},
802 {`{"foo":"bar"}`, ``, 0, false},
803 {`true`, ``, 0, false},
804 {`[]`, ``, 0, false},
805 {`[]`, ``, -1, false},
806 {`[1]`, `[]`, 0, true},
807 {`[{}]`, `[]`, 0, true},
808 {`[{}, [], 42]`, `[{}, []]`, -1, true},
809 {`[{}, [], 42]`, `[[], 42]`, 0, true},
810 {`[{}, [], 42]`, `[{}, 42]`, 1, true},
811 {`[{}, [], 42]`, `[{}, []]`, 2, true},
812 {`[{}, [], 42]`, ``, 10, false},
813 {`[{}, [], 42]`, ``, -10, false},
814 }
815
816 for _, tt := range tests {
817 t.Run(tt.name, func(t *testing.T) {
818 root := Must(Unmarshal([]byte(tt.name)))
819 err := root.DeleteIndex(tt.index)
820 if err != nil && tt.ok {
821 t.Errorf("DeleteIndex returns error: %v", err)
822 }
823 })
824 }
825}
826
827func TestNode_GetKey(t *testing.T) {
828 root, err := Unmarshal([]byte(`{"foo": true, "bar": null}`))
829 if err != nil {
830 t.Error("error occurred while unmarshal")
831 }
832
833 value, err := root.GetKey("foo")
834 if err != nil {
835 t.Errorf("error occurred while getting key, %s", err)
836 }
837
838 if value.MustBool() != true {
839 t.Errorf("value is not matched. expected: true, got: %v", value.MustBool())
840 }
841
842 value, err = root.GetKey("bar")
843 if err != nil {
844 t.Errorf("error occurred while getting key, %s", err)
845 }
846
847 _, err = root.GetKey("baz")
848 if err == nil {
849 t.Errorf("key baz is not exist. must be failed")
850 }
851
852 if value.MustNull() != nil {
853 t.Errorf("value is not matched. expected: nil, got: %v", value.MustNull())
854 }
855}
856
857func TestNode_GetKey_NotSucceed(t *testing.T) {
858 tests := []simpleNode{
859 {"nil node", (*Node)(nil)},
860 {"null node", NullNode("")},
861 }
862
863 for _, tt := range tests {
864 t.Run(tt.name, func(t *testing.T) {
865 if _, err := tt.node.GetKey(""); err == nil {
866 t.Errorf("%s should be an error", tt.name)
867 }
868 })
869 }
870}
871
872func TestNode_GetUniqueKeyList(t *testing.T) {
873 tests := []struct {
874 name string
875 json string
876 expected []string
877 }{
878 {
879 name: "simple foo/bar",
880 json: `{"foo": true, "bar": null}`,
881 expected: []string{"foo", "bar"},
882 },
883 {
884 name: "empty object",
885 json: `{}`,
886 expected: []string{},
887 },
888 {
889 name: "nested object",
890 json: `{
891 "outer": {
892 "inner": {
893 "key": "value"
894 },
895 "array": [1, 2, 3]
896 },
897 "another": "item"
898 }`,
899 expected: []string{"outer", "inner", "key", "array", "another"},
900 },
901 {
902 name: "complex object",
903 json: `{
904 "Image": {
905 "Width": 800,
906 "Height": 600,
907 "Title": "View from 15th Floor",
908 "Thumbnail": {
909 "Url": "http://www.example.com/image/481989943",
910 "Height": 125,
911 "Width": 100
912 },
913 "Animated": false,
914 "IDs": [116, 943, 234, 38793]
915 }
916 }`,
917 expected: []string{"Image", "Width", "Height", "Title", "Thumbnail", "Url", "Animated", "IDs"},
918 },
919 }
920
921 for _, tt := range tests {
922 t.Run(tt.name, func(t *testing.T) {
923 root, err := Unmarshal([]byte(tt.json))
924 if err != nil {
925 t.Errorf("error occurred while unmarshal")
926 }
927
928 value := root.UniqueKeyLists()
929 if len(value) != len(tt.expected) {
930 t.Errorf("%s length must be %v. got: %v. retrieved keys: %s", tt.name, len(tt.expected), len(value), value)
931 }
932
933 for _, key := range value {
934 if !contains(tt.expected, key) {
935 t.Errorf("EachKey() must be in %v. got: %v", tt.expected, key)
936 }
937 }
938 })
939 }
940}
941
942// TODO: resolve stack overflow
943func TestNode_IsEmpty(t *testing.T) {
944 tests := []struct {
945 name string
946 node *Node
947 expected bool
948 }{
949 {"nil node", (*Node)(nil), false}, // nil node is not empty.
950 // {"null node", NullNode(""), true},
951 {"empty object", ObjectNode("", nil), true},
952 {"empty array", ArrayNode("", nil), true},
953 {"non-empty object", ObjectNode("", map[string]*Node{"foo": BoolNode("foo", true)}), false},
954 {"non-empty array", ArrayNode("", []*Node{BoolNode("0", true)}), false},
955 }
956
957 for _, tt := range tests {
958 t.Run(tt.name, func(t *testing.T) {
959 if got := tt.node.Empty(); got != tt.expected {
960 t.Errorf("%s = %v, want %v", tt.name, got, tt.expected)
961 }
962 })
963 }
964}
965
966func TestNode_Index_EmptyList(t *testing.T) {
967 root, err := Unmarshal([]byte(`[]`))
968 if err != nil {
969 t.Errorf("error occurred while unmarshal")
970 }
971
972 array := root.MustArray()
973 for i, node := range array {
974 if i != node.Index() {
975 t.Errorf(ufmt.Sprintf("Index() must be nil. got: %v", i))
976 }
977 }
978}
979
980func TestNode_GetObject(t *testing.T) {
981 root, err := Unmarshal([]byte(`{"foo": true,"bar": null}`))
982 if err != nil {
983 t.Errorf("Error on Unmarshal(): %s", err.Error())
984 return
985 }
986
987 value, err := root.GetObject()
988 if err != nil {
989 t.Errorf("Error on root.GetObject(): %s", err.Error())
990 }
991
992 if _, ok := value["foo"]; !ok {
993 t.Errorf("root.GetObject() is corrupted: foo")
994 }
995
996 if _, ok := value["bar"]; !ok {
997 t.Errorf("root.GetObject() is corrupted: bar")
998 }
999}
1000
1001func TestNode_GetObject_NotSucceed(t *testing.T) {
1002 tests := []simpleNode{
1003 {"nil node", (*Node)(nil)},
1004 {"get object from null node", NullNode("")},
1005 {"not object node", NumberNode("", 123)},
1006 }
1007
1008 for _, tt := range tests {
1009 t.Run(tt.name, func(t *testing.T) {
1010 if _, err := tt.node.GetObject(); err == nil {
1011 t.Errorf("%s should be an error", tt.name)
1012 }
1013 })
1014 }
1015}
1016
1017func TestNode_ObjectEach(t *testing.T) {
1018 tests := []struct {
1019 name string
1020 json string
1021 expected map[string]int
1022 }{
1023 {
1024 name: "empty object",
1025 json: `{}`,
1026 expected: make(map[string]int),
1027 },
1028 {
1029 name: "single key-value pair",
1030 json: `{"key": 42}`,
1031 expected: map[string]int{"key": 42},
1032 },
1033 {
1034 name: "multiple key-value pairs",
1035 json: `{"one": 1, "two": 2, "three": 3}`,
1036 expected: map[string]int{"one": 1, "two": 2, "three": 3},
1037 },
1038 {
1039 name: "multiple key-value pairs with some non-numeric values",
1040 json: `{"one": 1, "two": "2", "three": 3, "four": "4"}`,
1041 expected: map[string]int{"one": 1, "three": 3},
1042 },
1043 {
1044 name: "non-object node",
1045 json: `["not", "an", "object"]`,
1046 expected: make(map[string]int),
1047 },
1048 }
1049
1050 for _, tc := range tests {
1051 t.Run(tc.name, func(t *testing.T) {
1052 root, err := Unmarshal([]byte(tc.json))
1053 if err != nil {
1054 t.Fatalf("Unmarshal failed: %v", err)
1055 }
1056
1057 result := make(map[string]int)
1058 root.ObjectEach(func(key string, value *Node) {
1059 // extract integer values from the object
1060 if val, err := strconv.Atoi(value.String()); err == nil {
1061 result[key] = val
1062 }
1063 })
1064
1065 if len(result) != len(tc.expected) {
1066 t.Errorf("%s: expected %d key-value pairs, got %d", tc.name, len(tc.expected), len(result))
1067 return
1068 }
1069
1070 for key, val := range tc.expected {
1071 if result[key] != val {
1072 t.Errorf("%s: expected value for key %s to be %d, got %d", tc.name, key, val, result[key])
1073 }
1074 }
1075 })
1076 }
1077}
1078
1079func TestNode_ExampleMust(t *testing.T) {
1080 data := []byte(`{
1081 "Image": {
1082 "Width": 800,
1083 "Height": 600,
1084 "Title": "View from 15th Floor",
1085 "Thumbnail": {
1086 "Url": "http://www.example.com/image/481989943",
1087 "Height": 125,
1088 "Width": 100
1089 },
1090 "Animated" : false,
1091 "IDs": [116, 943, 234, 38793]
1092 }
1093 }`)
1094
1095 root := Must(Unmarshal(data))
1096 if root.Size() != 1 {
1097 t.Errorf("root.Size() must be 1. got: %v", root.Size())
1098 }
1099
1100 ufmt.Sprintf("Object has %d inheritors inside", root.Size())
1101 // Output:
1102 // Object has 1 inheritors inside
1103}
1104
1105// Calculate AVG price from different types of objects, JSON from: https://goessner.net/articles/JsonPath/index.html#e3
1106func TestExampleUnmarshal(t *testing.T) {
1107 data := []byte(`{ "store": {
1108 "book": [
1109 { "category": "reference",
1110 "author": "Nigel Rees",
1111 "title": "Sayings of the Century",
1112 "price": 8.95
1113 },
1114 { "category": "fiction",
1115 "author": "Evelyn Waugh",
1116 "title": "Sword of Honour",
1117 "price": 12.99
1118 },
1119 { "category": "fiction",
1120 "author": "Herman Melville",
1121 "title": "Moby Dick",
1122 "isbn": "0-553-21311-3",
1123 "price": 8.99
1124 },
1125 { "category": "fiction",
1126 "author": "J. R. R. Tolkien",
1127 "title": "The Lord of the Rings",
1128 "isbn": "0-395-19395-8",
1129 "price": 22.99
1130 }
1131 ],
1132 "bicycle": { "color": "red",
1133 "price": 19.95
1134 },
1135 "tools": null
1136 }
1137}`)
1138
1139 root, err := Unmarshal(data)
1140 if err != nil {
1141 t.Errorf("error occurred when unmarshal")
1142 }
1143
1144 store := root.MustKey("store").MustObject()
1145
1146 var prices float64
1147 size := 0
1148 for _, objects := range store {
1149 if objects.IsArray() && objects.Size() > 0 {
1150 size += objects.Size()
1151 for _, object := range objects.MustArray() {
1152 prices += object.MustKey("price").MustNumeric()
1153 }
1154 } else if objects.IsObject() && objects.HasKey("price") {
1155 size++
1156 prices += objects.MustKey("price").MustNumeric()
1157 }
1158 }
1159
1160 result := int(prices / float64(size))
1161 ufmt.Sprintf("AVG price: %d", result)
1162}
1163
1164func TestNode_ExampleMust_panic(t *testing.T) {
1165 defer func() {
1166 if r := recover(); r == nil {
1167 t.Errorf("The code did not panic")
1168 }
1169 }()
1170 data := []byte(`{]`)
1171 root := Must(Unmarshal(data))
1172 ufmt.Sprintf("Object has %d inheritors inside", root.Size())
1173}
1174
1175func TestNode_Path(t *testing.T) {
1176 data := []byte(`{
1177 "Image": {
1178 "Width": 800,
1179 "Height": 600,
1180 "Title": "View from 15th Floor",
1181 "Thumbnail": {
1182 "Url": "http://www.example.com/image/481989943",
1183 "Height": 125,
1184 "Width": 100
1185 },
1186 "Animated" : false,
1187 "IDs": [116, 943, 234, 38793]
1188 }
1189 }`)
1190
1191 root, err := Unmarshal(data)
1192 if err != nil {
1193 t.Errorf("Error on Unmarshal(): %s", err.Error())
1194 return
1195 }
1196
1197 if root.Path() != "$" {
1198 t.Errorf("Wrong root.Path()")
1199 }
1200
1201 element := root.MustKey("Image").MustKey("Thumbnail").MustKey("Url")
1202 if element.Path() != "$['Image']['Thumbnail']['Url']" {
1203 t.Errorf("Wrong path found: %s", element.Path())
1204 }
1205
1206 if (*Node)(nil).Path() != "" {
1207 t.Errorf("Wrong (nil).Path()")
1208 }
1209}
1210
1211func TestNode_Path2(t *testing.T) {
1212 tests := []struct {
1213 name string
1214 node *Node
1215 want string
1216 }{
1217 {
1218 name: "Node with key",
1219 node: &Node{
1220 prev: &Node{},
1221 key: func() *string { s := "key"; return &s }(),
1222 },
1223 want: "$['key']",
1224 },
1225 {
1226 name: "Node with index",
1227 node: &Node{
1228 prev: &Node{},
1229 index: func() *int { i := 1; return &i }(),
1230 },
1231 want: "$[1]",
1232 },
1233 }
1234
1235 for _, tt := range tests {
1236 t.Run(tt.name, func(t *testing.T) {
1237 if got := tt.node.Path(); got != tt.want {
1238 t.Errorf("Path() = %v, want %v", got, tt.want)
1239 }
1240 })
1241 }
1242}
1243
1244func TestNode_Root(t *testing.T) {
1245 root := &Node{}
1246 child := &Node{prev: root}
1247 grandChild := &Node{prev: child}
1248
1249 tests := []struct {
1250 name string
1251 node *Node
1252 want *Node
1253 }{
1254 {
1255 name: "Root node",
1256 node: root,
1257 want: root,
1258 },
1259 {
1260 name: "Child node",
1261 node: child,
1262 want: root,
1263 },
1264 {
1265 name: "Grandchild node",
1266 node: grandChild,
1267 want: root,
1268 },
1269 {
1270 name: "Node is nil",
1271 node: nil,
1272 want: nil,
1273 },
1274 }
1275
1276 for _, tt := range tests {
1277 t.Run(tt.name, func(t *testing.T) {
1278 if got := tt.node.root(); got != tt.want {
1279 t.Errorf("root() = %v, want %v", got, tt.want)
1280 }
1281 })
1282 }
1283}
1284
1285func contains(slice []string, item string) bool {
1286 for _, a := range slice {
1287 if a == item {
1288 return true
1289 }
1290 }
1291
1292 return false
1293}
1294
1295// ignore the sequence of keys by ordering them.
1296// need to avoid import encoding/json and reflect package.
1297// because gno does not support them for now.
1298// TODO: use encoding/json to compare the result after if possible in gno.
1299func isSameObject(a, b string) bool {
1300 aPairs := strings.Split(strings.Trim(a, "{}"), ",")
1301 bPairs := strings.Split(strings.Trim(b, "{}"), ",")
1302
1303 aMap := make(map[string]string)
1304 bMap := make(map[string]string)
1305 for _, pair := range aPairs {
1306 kv := strings.Split(pair, ":")
1307 key := strings.Trim(kv[0], `"`)
1308 value := strings.Trim(kv[1], `"`)
1309 aMap[key] = value
1310 }
1311 for _, pair := range bPairs {
1312 kv := strings.Split(pair, ":")
1313 key := strings.Trim(kv[0], `"`)
1314 value := strings.Trim(kv[1], `"`)
1315 bMap[key] = value
1316 }
1317
1318 aKeys := make([]string, 0, len(aMap))
1319 bKeys := make([]string, 0, len(bMap))
1320 for k := range aMap {
1321 aKeys = append(aKeys, k)
1322 }
1323
1324 for k := range bMap {
1325 bKeys = append(bKeys, k)
1326 }
1327
1328 sort.Strings(aKeys)
1329 sort.Strings(bKeys)
1330
1331 if len(aKeys) != len(bKeys) {
1332 return false
1333 }
1334
1335 for i := range aKeys {
1336 if aKeys[i] != bKeys[i] {
1337 return false
1338 }
1339
1340 if aMap[aKeys[i]] != bMap[bKeys[i]] {
1341 return false
1342 }
1343 }
1344
1345 return true
1346}
1347
1348func compareNodes(n1, n2 *Node) bool {
1349 if n1 == nil || n2 == nil {
1350 return n1 == n2
1351 }
1352
1353 if n1.key != n2.key {
1354 return false
1355 }
1356
1357 if !bytes.Equal(n1.data, n2.data) {
1358 return false
1359 }
1360
1361 if n1.index != n2.index {
1362 return false
1363 }
1364
1365 if n1.borders != n2.borders {
1366 return false
1367 }
1368
1369 if n1.modified != n2.modified {
1370 return false
1371 }
1372
1373 if n1.nodeType != n2.nodeType {
1374 return false
1375 }
1376
1377 if !compareNodes(n1.prev, n2.prev) {
1378 return false
1379 }
1380
1381 if len(n1.next) != len(n2.next) {
1382 return false
1383 }
1384
1385 for k, v := range n1.next {
1386 if !compareNodes(v, n2.next[k]) {
1387 return false
1388 }
1389 }
1390
1391 return true
1392}