OILS / spec / ysh-json.test.sh View on Github | oils.pub

1288 lines, 299 significant
1## oils_failures_allowed: 1
2## tags: dev-minimal
3
4#### usage errors
5
6json read zz
7echo status=$?
8
9json write
10
11## status: 3
12## STDOUT:
13status=2
14## END
15
16#### json write STRING
17shopt --set parse_proc
18
19json write ('foo')
20var s = 'foo'
21json write (s)
22## STDOUT:
23"foo"
24"foo"
25## END
26
27#### json write ARRAY
28json write (:|foo.cc foo.h|)
29json write (['foo.cc', 'foo.h'], space=0)
30## STDOUT:
31[
32 "foo.cc",
33 "foo.h"
34]
35["foo.cc","foo.h"]
36## END
37
38#### json write Dict
39json write ({k: 'v', k2: [4, 5]})
40
41json write ([{k: 'v', k2: 'v2'}, {}])
42
43## STDOUT:
44{
45 "k": "v",
46 "k2": [
47 4,
48 5
49 ]
50}
51[
52 {
53 "k": "v",
54 "k2": "v2"
55 },
56 {}
57]
58## END
59
60#### json write space=0, space=4
61shopt --set parse_proc
62
63var mydict = {name: "bob", age: 30}
64
65json write (mydict, space=0)
66json write (mydict, space=4)
67## STDOUT:
68{"name":"bob","age":30}
69{
70 "name": "bob",
71 "age": 30
72}
73## END
74
75#### json write in command sub
76shopt -s oil:all # for echo
77var mydict = {name: "bob", age: 30}
78json write (mydict)
79var x = $(json write (mydict))
80echo $x
81## STDOUT:
82{
83 "name": "bob",
84 "age": 30
85}
86{
87 "name": "bob",
88 "age": 30
89}
90## END
91
92#### json read passed invalid args
93
94# EOF
95json read
96echo status=$?
97
98json read 'z z'
99echo status=$?
100
101json read a b c
102echo status=$?
103
104## STDOUT:
105status=1
106status=2
107status=2
108## END
109
110#### json read uses $_reply var
111
112# space before true
113echo ' true' | json read
114json write (_reply)
115
116## STDOUT:
117true
118## END
119
120#### json read then json write
121
122# BUG with space before true
123echo '{"name": "bob", "age": 42, "ok": true}' | json read
124json write (_reply)
125
126echo '{"name": "bob", "age": 42, "ok":true}' | json read
127json write (_reply)
128
129echo '{"name": {}, "age": {}, "x":-1, "y": -0}' | json read
130json write (_reply)
131
132## STDOUT:
133{
134 "name": "bob",
135 "age": 42,
136 "ok": true
137}
138{
139 "name": "bob",
140 "age": 42,
141 "ok": true
142}
143{
144 "name": {},
145 "age": {},
146 "x": -1,
147 "y": 0
148}
149## END
150
151#### json read with redirect
152echo '{"age": 42}' > $TMP/foo.txt
153json read (&x) < $TMP/foo.txt
154pp cell_ x
155## STDOUT:
156x = (Cell exported:F readonly:F nameref:F val:(value.Dict d:{age (value.Int i:42)}))
157## END
158
159#### json read at end of pipeline (relies on lastpipe)
160echo '{"age": 43}' | json read (&y)
161pp cell_ y
162## STDOUT:
163y = (Cell exported:F readonly:F nameref:F val:(value.Dict d:{age (value.Int i:43)}))
164## END
165
166#### invalid JSON
167echo '{' | json read (&y)
168echo pipeline status = $?
169pp test_ (y)
170## status: 1
171## STDOUT:
172pipeline status = 1
173## END
174
175#### Extra data after valid JSON
176
177# Trailing space is OK
178echo '42 ' | json read
179echo num space $?
180
181echo '{} ' | json read
182echo obj space $?
183
184echo '42 # comment' | json8 read
185echo num comment $?
186
187echo '{} # comment ' | json8 read
188echo obj comment $?
189
190echo '42]' | json read
191echo num bracket $?
192
193echo '{}]' | json read
194echo obj bracket $?
195
196## STDOUT:
197num space 0
198obj space 0
199num comment 0
200obj comment 0
201num bracket 1
202obj bracket 1
203## END
204
205#### json write expression
206json write ([1,2,3], space=0)
207echo status=$?
208
209json write (5, 6) # to many args
210echo status=$?
211
212## status: 3
213## STDOUT:
214[1,2,3]
215status=0
216## END
217
218#### json write evaluation error
219
220#var block = ^(echo hi)
221#json write (block)
222#echo status=$?
223
224# undefined var
225json write (a)
226echo 'should have failed'
227
228## status: 1
229## STDOUT:
230## END
231
232#### json write of List in cycle
233
234var L = [1, 2, 3]
235setvar L[0] = L
236pp test_ (L)
237
238json write (L)
239echo status=$?
240
241## status: 0
242## STDOUT:
243(List) [[...],2,3]
244status=1
245## END
246
247#### json write of Dict in cycle
248
249var d = {}
250setvar d.k = d
251
252pp test_ (d)
253
254json write (d)
255echo status=$?
256
257## STDOUT:
258(Dict) {"k":{...}}
259status=1
260## END
261
262#### json write of List/Dict referenced twice (bug fix)
263
264var mylist = [1,2,3]
265var mydict = {foo: "bar"}
266
267var top = {k: mylist, k2: mylist, k3: mydict, k4: mydict}
268
269# BUG!
270json write (top, space=0)
271
272## STDOUT:
273{"k":[1,2,3],"k2":[1,2,3],"k3":{"foo":"bar"},"k4":{"foo":"bar"}}
274## END
275
276#### json read doesn't accept u'' or b'' strings
277
278json read <<EOF
279{"key": u'val'}
280EOF
281echo status=$?
282
283#pp test_ (_reply)
284
285json read <<EOF
286{"key": b'val'}
287EOF
288echo status=$?
289
290## STDOUT:
291status=1
292status=1
293## END
294
295#### json read doesn't accept comments, but json8 does
296
297json8 read <<EOF
298{ # comment
299 "key": # zz
300 b'val', # yy
301 "k2": "v2" #
302}
303EOF
304echo status=$?
305
306json8 write (_reply)
307
308json read <<EOF
309{"key": "val"} # comment
310EOF
311echo status=$?
312## STDOUT:
313status=0
314{
315 "key": "val",
316 "k2": "v2"
317}
318status=1
319## END
320
321
322#### json write emits Unicode replacement char for binary data \yff
323
324json write ([3, "foo", $'-\xff\xfe---\xfd=']) > tmp.txt
325
326# Round trip it for good measure
327json read < tmp.txt
328
329json write (_reply)
330
331## STDOUT:
332[
333 3,
334 "foo",
335 "-��---�="
336]
337## END
338
339#### json8 accepts j"" prefix, but json doesn't
340
341var msg = r'j"foo\nbar"'
342
343echo "$msg" | json read
344echo json=$?
345echo
346
347echo "$msg" | json8 read
348echo json8=$?
349pp test_ (_reply)
350echo
351
352var msg = r'j"\u0041"'
353echo "$msg" | json8 read
354echo json8=$?
355pp test_ (_reply)
356
357
358## STDOUT:
359json=1
360
361json8=0
362(Str) "foo\nbar"
363
364json8=0
365(Str) "A"
366## END
367
368#### j"" prefix not accepted in YSH (could be added later)
369
370shopt -s ysh:all
371
372# denied by YSH
373# echo j"\u{7f}"
374
375var s = j"\u{7f}"
376
377## status: 2
378## STDOUT:
379## END
380
381
382#### json8 write emits b'' strings for binary data \yff
383
384json8 write ([3, "foo", $'-\xff\xfe-\xfd='])
385
386## STDOUT:
387[
388 3,
389 "foo",
390 b'-\yff\yfe-\yfd='
391]
392## END
393
394
395#### json8 write bytes vs unicode string
396
397u=$'mu \u03bc \x01 \" \\ \b\f\n\r\t'
398u2=$'\x01\x1f' # this is a valid unicode string
399
400b=$'\xff' # this isn't valid unicode
401
402json8 write (u)
403json8 write (u2)
404
405json8 write (b)
406
407## STDOUT:
408"mu μ \u0001 \" \\ \b\f\n\r\t"
409"\u0001\u001f"
410b'\yff'
411## END
412
413#### JSON \/ escapes supported
414
415msg='"\/"'
416
417echo "$msg" | python3 -c 'import json, sys; print(json.load(sys.stdin))'
418
419echo "$msg" | json read
420echo reply=$_reply
421
422j8="b'\\/'"
423echo "$msg" | json read
424echo reply=$_reply
425
426
427## STDOUT:
428/
429reply=/
430reply=/
431## END
432
433#### JSON string can have unescaped ' and J8 string can have unescaped "
434
435json read <<EOF
436"'"
437EOF
438
439pp test_ (_reply)
440
441json8 read <<EOF
442u'"'
443EOF
444
445pp test_ (_reply)
446
447## STDOUT:
448(Str) "'"
449(Str) "\""
450## END
451
452
453#### J8 supports superfluous \" escapes, but JSON doesn't support \' escapes
454
455json8 read <<'EOF'
456b'\"'
457EOF
458echo reply=$_reply
459
460json8 read <<'EOF'
461b'\'\'\b\f\n\r\t\"\\'
462EOF
463pp test_ (_reply)
464
465# Suppress traceback
466python3 -c 'import json, sys; print(json.load(sys.stdin))' 2>/dev/null <<'EOF'
467"\'"
468EOF
469echo python3=$?
470
471json read <<'EOF'
472"\'"
473EOF
474echo json=$?
475
476## STDOUT:
477reply="
478(Str) "''\b\f\n\r\t\"\\"
479python3=1
480json=1
481## END
482
483#### Escaping uses \u0001 in "", but \u{1} in b''
484
485s1=$'\x01'
486s2=$'\x01\xff\x1f' # byte string
487
488json8 write (s1)
489json8 write (s2)
490
491## STDOUT:
492"\u0001"
493b'\u{1}\yff\u{1f}'
494## END
495
496
497#### json8 read
498
499echo '{ }' | json8 read
500pp test_ (_reply)
501
502echo '[ ]' | json8 read
503pp test_ (_reply)
504
505echo '[42]' | json8 read
506pp test_ (_reply)
507
508echo '[true, false]' | json8 read
509pp test_ (_reply)
510
511echo '{"k": "v"}' | json8 read
512pp test_ (_reply)
513
514echo '{"k": null}' | json8 read
515pp test_ (_reply)
516
517echo '{"k": 1, "k2": 2}' | json8 read
518pp test_ (_reply)
519
520echo "{u'k': {b'k2': null}}" | json8 read
521pp test_ (_reply)
522
523echo '{"k": {"k2": "v2"}, "k3": "backslash \\ \" \n line 2 \u03bc "}' | json8 read
524pp test_ (_reply)
525
526json8 read (&x) <<'EOF'
527{u'k': {u'k2': u'v2'}, u'k3': u'backslash \\ \" \n line 2 \u{3bc} '}
528EOF
529pp test_ (x)
530
531## STDOUT:
532(Dict) {}
533(List) []
534(List) [42]
535(List) [true,false]
536(Dict) {"k":"v"}
537(Dict) {"k":null}
538(Dict) {"k":1,"k2":2}
539(Dict) {"k":{"k2":null}}
540(Dict) {"k":{"k2":"v2"},"k3":"backslash \\ \" \n line 2 μ "}
541(Dict) {"k":{"k2":"v2"},"k3":"backslash \\ \" \n line 2 μ "}
542## END
543
544#### json8 round trip
545
546var obj = [42, 1.5, null, true, "hi", b'\yff\yfe\b\n""']
547
548json8 write (obj, space=0) > j
549
550cat j
551
552json8 read < j
553
554json8 write (_reply)
555
556## STDOUT:
557[42,1.5,null,true,"hi",b'\yff\yfe\b\n""']
558[
559 42,
560 1.5,
561 null,
562 true,
563 "hi",
564 b'\yff\yfe\b\n""'
565]
566## END
567
568#### json round trip (regression)
569
570var d = {
571 short: '-v', long: '--verbose', type: null, default: '', help: 'Enable verbose logging'
572}
573
574json write (d) | json read
575
576pp test_ (_reply)
577
578## STDOUT:
579(Dict) {"short":"-v","long":"--verbose","type":null,"default":"","help":"Enable verbose logging"}
580## END
581
582#### round trip: decode surrogate pair and encode
583
584var j = r'"\ud83e\udd26"'
585echo $j | json read (&c1)
586
587json write (c1)
588
589var j = r'"\uD83E\uDD26"'
590echo $j | json read (&c2)
591
592json write (c2)
593
594# Not a surrogate pair
595var j = r'"\u0001\u0002"'
596echo $j | json read (&c3)
597
598json write (c3)
599
600var j = r'"\u0100\u0101\u0102"'
601echo $j | json read (&c4)
602
603json write (c4)
604
605## STDOUT:
606"🤦"
607"🤦"
608"\u0001\u0002"
609"ĀāĂ"
610## END
611
612#### round trip: decode surrogate half and encode
613
614shopt -s ysh:upgrade
615
616for j in '"\ud83e"' '"\udd26"' {
617 var s = fromJson(j)
618 write -- "$j"
619 pp test_ (s)
620
621 write -n 'json '; json write (s)
622
623 write -n 'json8 '; json8 write (s)
624
625 echo
626}
627
628## STDOUT:
629"\ud83e"
630(Str) b'\yed\ya0\ybe'
631json "\ud83e"
632json8 b'\yed\ya0\ybe'
633
634"\udd26"
635(Str) b'\yed\yb4\ya6'
636json "\udd26"
637json8 b'\yed\yb4\ya6'
638
639## END
640
641#### toJson() toJson8()
642shopt --set parse_ysh_expr_sub
643
644var obj = [42, 1.5, null, true, "hi", b'\yf0']
645
646echo $[toJson(obj)]
647echo $[toJson8(obj)]
648
649var obj2 = [3, 4]
650echo $[toJson(obj2, space=0)] # same as the default
651echo $[toJson8(obj2, space=0)]
652
653echo $[toJson(obj2, space=2)]
654echo $[toJson8(obj2, space=2)]
655
656# fully specify this behavior
657echo $[toJson(obj2, space=-2)]
658echo $[toJson8(obj2, space=-2)]
659
660## STDOUT:
661[42,1.5,null,true,"hi",""]
662[42,1.5,null,true,"hi",b'\yf0']
663[3,4]
664[3,4]
665[
666 3,
667 4
668]
669[
670 3,
671 4
672]
673[3,4]
674[3,4]
675## END
676
677#### fromJson() fromJson8()
678
679var m1 = '[42,1.5,null,true,"hi"]'
680
681# JSON8 message
682var m2 = '[42,1.5,null,true,"hi",' ++ "u''" ++ ']'
683
684pp test_ (fromJson8(m1))
685pp test_ (fromJson(m1))
686
687pp test_ (fromJson8(m2))
688pp test_ (fromJson(m2)) # fails
689
690## status: 4
691## STDOUT:
692(List) [42,1.5,null,true,"hi"]
693(List) [42,1.5,null,true,"hi"]
694(List) [42,1.5,null,true,"hi",""]
695## END
696
697#### User can handle errors - toJson() toJson8()
698shopt -s ysh:upgrade
699
700var obj = []
701call obj->append(obj)
702
703try {
704 echo $[toJson(obj)]
705}
706echo status=$_status
707echo "encode error $[_error.message]" | sed 's/0x[a-f0-9]\+/(object id)/'
708
709try { # use different style
710 echo $[toJson8( /d+/ )]
711}
712echo status=$_status
713echo "encode error $[_error.message]"
714
715# This makes the interpreter fail with a message
716echo $[toJson(obj)]
717
718## status: 4
719## STDOUT:
720status=4
721encode error Can't encode List (object id) in object cycle
722status=4
723encode error Can't serialize object of type Eggex
724## END
725
726#### User can handle errors - fromJson() fromJson8()
727shopt -s ysh:upgrade
728
729var message ='[42,1.5,null,true,"hi"'
730
731try {
732 var obj = fromJson(message)
733}
734echo status=$_status
735echo "decode error $[_error.message]" | egrep -o '.*Expected.*RBracket'
736
737try {
738 var obj = fromJson8(message)
739}
740echo status=$_status
741echo "decode error $[_error.message]" | egrep -o '.*Expected.*RBracket'
742
743try {
744 var obj = fromJson('[+]')
745}
746echo "positions $[_error.start_pos] - $[_error.end_pos]"
747
748# This makes the interpreter fail with a message
749var obj = fromJson(message)
750
751## status: 4
752## STDOUT:
753status=4
754decode error Expected Id.J8_RBracket
755status=4
756decode error Expected Id.J8_RBracket
757positions 1 - 2
758## END
759
760
761#### ASCII control chars can't appear literally in messages
762shopt -s ysh:upgrade
763
764var message=$'"\x01"'
765#echo $message | od -c
766
767try {
768 var obj = fromJson(message)
769}
770echo status=$_status
771echo "$[_error.message]" | egrep -o 'ASCII control chars'
772
773## STDOUT:
774status=4
775ASCII control chars
776## END
777
778
779#### \yff can't appear in u'' code strings (command)
780
781shopt -s ysh:upgrade
782
783echo -n b'\yfd' | od -A n -t x1
784echo -n u'\yfd' | od -A n -t x1
785
786## status: 2
787## STDOUT:
788 fd
789## END
790
791#### \yff can't appear in u'' code strings (expr)
792
793var x = b'\yfe'
794write -n -- $x | od -A n -t x1
795
796var x = u'\yfe'
797write -n -- $x | od -A n -t x1
798
799## status: 2
800## STDOUT:
801 fe
802## END
803
804#### \yff can't appear in u'' multiline code strings
805
806shopt -s ysh:upgrade
807
808echo -n b'''\yfc''' | od -A n -t x1
809echo -n u'''\yfd''' | od -A n -t x1
810
811## status: 2
812## STDOUT:
813 fc
814## END
815
816#### \yff can't appear in u'' data strings
817
818#shopt -s ysh:upgrade
819
820json8 read (&b) <<'EOF'
821b'\yfe'
822EOF
823pp test_ (b)
824
825json8 read (&u) <<'EOF'
826u'\yfe'
827EOF
828pp test_ (u) # undefined
829
830## status: 1
831## STDOUT:
832(Str) b'\yfe'
833## END
834
835#### \u{dc00} can't be in surrogate range in code (command)
836
837shopt -s ysh:upgrade
838
839echo -n u'\u{dc00}' | od -A n -t x1
840
841## status: 2
842## STDOUT:
843## END
844
845#### \u{dc00} can't be in surrogate range in code (expr)
846
847shopt -s ysh:upgrade
848
849var x = u'\u{dc00}'
850echo $x | od -A n -t x1
851
852## status: 2
853## STDOUT:
854## END
855
856#### \u{dc00} can't be in surrogate range in data
857
858json8 read <<'EOF'
859["long string", u'hello \u{d7ff}', "other"]
860EOF
861echo status=$?
862
863json8 read <<'EOF'
864["long string", u'hello \u{d800}', "other"]
865EOF
866echo status=$?
867
868json8 read <<'EOF'
869["long string", u'hello \u{dfff}', "other"]
870EOF
871echo status=$?
872
873json8 read <<'EOF'
874["long string", u'hello \u{e000}', "other"]
875EOF
876echo status=$?
877
878
879## STDOUT:
880status=0
881status=1
882status=1
883status=0
884## END
885
886
887#### Inf is encoded as null, like JavaScript
888
889# WRONG LOCATION! Gah
890#var x = fromJson(repeat('123', 20))
891
892shopt --set ysh:upgrade
893
894source $LIB_YSH/list.ysh
895
896# Create inf
897var big = repeat('12345678', 100) ++ '.0'
898#pp test_ (s)
899var inf = fromJson(big)
900var neg_inf = fromJson('-' ++ big)
901
902# Can be printed
903pp test_ (inf)
904pp test_ (neg_inf)
905echo --
906
907# Can't be serialized
908try {
909 json write (inf)
910}
911echo error=$[_error.code]
912
913try {
914 json write (neg_inf)
915}
916echo error=$[_error.code]
917
918echo --
919echo $[toJson(inf)]
920echo $[toJson(neg_inf)]
921
922## STDOUT:
923(Float) INFINITY
924(Float) -INFINITY
925--
926null
927error=0
928null
929error=0
930--
931null
932null
933## END
934
935#### NaN is encoded as null, like JavaScript
936shopt --set parse_ysh_expr_sub
937
938pp test_ (NAN)
939
940json write (NAN)
941
942echo $[toJson(NAN)]
943
944## STDOUT:
945(Float) NAN
946null
947null
948## END
949
950
951#### Invalid UTF-8 in JSON is rejected
952
953echo $'"\xff"' | json read
954echo status=$?
955
956echo $'"\xff"' | json8 read
957echo status=$?
958
959echo $'\xff' | json read
960echo status=$?
961
962echo $'\xff' | json8 read
963echo status=$?
964
965## STDOUT:
966status=1
967status=1
968status=1
969status=1
970## END
971
972#### Invalid JSON in J8 is rejected
973
974json8 read <<EOF
975b'$(echo -e -n '\xff')'
976EOF
977echo status=$?
978
979json8 read <<EOF
980u'$(echo -e -n '\xff')'
981EOF
982echo status=$?
983
984## STDOUT:
985status=1
986status=1
987## END
988
989#### '' means the same thing as u''
990
991echo "''" | json8 read
992pp test_ (_reply)
993
994echo "'\u{3bc}'" | json8 read
995pp test_ (_reply)
996
997echo "'\yff'" | json8 read
998echo status=$?
999
1000## STDOUT:
1001(Str) ""
1002(Str) "μ"
1003status=1
1004## END
1005
1006#### decode integer larger than 2^32
1007
1008json=$(( 1 << 33 ))
1009echo $json
1010
1011echo $json | json read
1012pp test_ (_reply)
1013
1014## STDOUT:
10158589934592
1016(Int) 8589934592
1017## END
1018
1019#### decode integer larger than 2^64
1020
1021$SH <<'EOF'
1022json read <<< '123456789123456789123456789'
1023echo status=$?
1024pp test_ (_reply)
1025EOF
1026
1027$SH <<'EOF'
1028json read <<< '-123456789123456789123456789'
1029echo status=$?
1030pp test_ (_reply)
1031EOF
1032
1033echo ok
1034
1035## STDOUT:
1036status=1
1037status=1
1038ok
1039## END
1040
1041
1042#### round trip: read/write with ysh
1043
1044var file = "$REPO_ROOT/spec/testdata/bug.json"
1045#cat $file
1046cat $file | json read (&cfg)
1047json write (cfg) > ysh-json
1048
1049diff -u $file ysh-json
1050echo diff=$?
1051
1052## STDOUT:
1053diff=0
1054## END
1055
1056#### round trip: read/write with ysh, read/write with Python 3 (bug regression)
1057
1058var file = "$REPO_ROOT/spec/testdata/bug.json"
1059#cat $file
1060cat $file | json read (&cfg)
1061json write (cfg) > ysh-json
1062
1063cat ysh-json | python3 -c \
1064 'import json, sys; obj = json.load(sys.stdin); json.dump(obj, sys.stdout, indent=2); print()' \
1065 > py-json
1066
1067diff -u $file py-json
1068echo diff=$?
1069
1070## STDOUT:
1071diff=0
1072## END
1073
1074#### Encoding bytes that don't hit UTF8_REJECT immediately (bug fix)
1075
1076var x = $'\xce'
1077json8 write (x)
1078declare -p x
1079echo
1080
1081var y = $'\xbc'
1082json8 write (y)
1083declare -p y
1084echo
1085
1086var z = $'\xf0\x9f\xa4\xff'
1087json8 write (z)
1088declare -p z
1089
1090## STDOUT:
1091b'\yce'
1092declare -- x=$'\xce'
1093
1094b'\ybc'
1095declare -- y=$'\xbc'
1096
1097b'\yf0\y9f\ya4\yff'
1098declare -- z=$'\xf0\x9f\xa4\xff'
1099## END
1100
1101#### NIL8 token in JSON / JSON8
1102
1103echo "(" | json read
1104echo status=$?
1105
1106echo ")" | json8 read
1107echo status=$?
1108
1109## STDOUT:
1110status=1
1111status=1
1112## END
1113
1114#### Data after internal NUL (issue #2026)
1115
1116$SH <<'EOF'
1117pp test_ (fromJson(b'123\y00abc'))
1118EOF
1119echo status=$?
1120
1121$SH <<'EOF'
1122pp test_ (fromJson(b'123\y01abc'))
1123EOF
1124echo status=$?
1125
1126$SH <<'EOF'
1127shopt --set ysh:upgrade # b'' syntax
1128json read <<< b'123\y00abc'
1129EOF
1130echo status=$?
1131
1132$SH <<'EOF'
1133shopt --set ysh:upgrade # b'' syntax
1134json read <<< b'123\y01abc'
1135EOF
1136echo status=$?
1137
1138## STDOUT:
1139status=4
1140status=4
1141status=1
1142status=1
1143## END
1144
1145#### Float too big
1146
1147$SH <<'EOF'
1148json read <<< '123456789123456789123456789.12345e67890'
1149echo status=$?
1150pp test_ (_reply)
1151EOF
1152
1153$SH <<'EOF'
1154json read <<< '-123456789123456789123456789.12345e67890'
1155echo status=$?
1156pp test_ (_reply)
1157EOF
1158
1159## STDOUT:
1160status=0
1161(Float) INFINITY
1162status=0
1163(Float) -INFINITY
1164## END
1165
1166#### Many [[[ , but not too many
1167
1168shopt -s ysh:upgrade
1169
1170proc pairs(n) {
1171 var m = int(n) # TODO: 1 .. n should auto-convert?
1172
1173 for i in (1 ..< m) {
1174 write -n -- '['
1175 }
1176 for i in (1 ..< m) {
1177 write -n -- ']'
1178 }
1179}
1180
1181# This is all Python can handle; C++ can handle more
1182msg=$(pairs 50)
1183
1184#echo $msg
1185
1186echo "$msg" | json read
1187pp test_ (_reply)
1188echo len=$[len(_reply)]
1189
1190## STDOUT:
1191(List) [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
1192len=1
1193## END
1194
1195
1196#### Too many opening [[[ - blocking stack
1197
1198python2 -c 'print("[" * 10000)' | json read
1199pp test_ (_reply)
1200
1201python2 -c 'print("{" * 10000)' | json read
1202pp test_ (_reply)
1203
1204## STDOUT:
1205## END
1206
1207#### BashArray can be serialized
1208
1209declare -a empty_array
1210
1211declare -a array=(x y)
1212array[5]=z
1213
1214json write (empty_array)
1215json write (array)
1216
1217## STDOUT:
1218{
1219 "type": "BashArray",
1220 "data": {}
1221}
1222{
1223 "type": "BashArray",
1224 "data": {
1225 "0": "x",
1226 "1": "y",
1227 "5": "z"
1228 }
1229}
1230## END
1231
1232#### BashAssoc can be serialized
1233
1234declare -A empty_assoc
1235
1236declare -A assoc=([foo]=bar [42]=43)
1237
1238json write (empty_assoc)
1239json write (assoc)
1240
1241## STDOUT:
1242{
1243 "type": "BashAssoc",
1244 "data": {}
1245}
1246{
1247 "type": "BashAssoc",
1248 "data": {
1249 "foo": "bar",
1250 "42": "43"
1251 }
1252}
1253## END
1254
1255#### type_errors=false
1256shopt --set parse_ysh_expr_sub
1257
1258var o = Obj.new({}, null)
1259
1260#json write (o)
1261json write (o, type_errors=false)
1262
1263var pat = /d+/
1264#json write (pat)
1265json write (pat, type_errors=false)
1266
1267var d = {key: pat, key2: o}
1268json write (d, type_errors=false)
1269
1270echo
1271
1272echo $[toJson(o, type_errors=false)]
1273echo $[toJson8(o, type_errors=false)]
1274echo $[toJson8(d, type_errors=false)]
1275
1276## STDOUT:
1277null
1278null
1279{
1280 "key": null,
1281 "key2": null
1282}
1283
1284null
1285null
1286{"key":null,"key2":null}
1287## END
1288