# Copyright (C) 2016, 2017, 2018, 2019, 2020  Stefan Vargyas
# 
# This file is part of Json-Type.
# 
# Json-Type is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# Json-Type is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Json-Type.  If not, see <http://www.gnu.org/licenses/>.

--------------------------------------------------------------------------------

# This file contains the list of bugs found, in reverse chronological order. For
# each of these bugs there is a corresponding test case, in the 'json-bugs' test
# suite in the 'test' directory, which records the way the bug got fixed.

--------------------------------------------------------------------------------

$ date
Fri Oct 30 16:19:56 EET 2020

$ json() { local n=''; [ "$1" == '--null' ] && { n=' >/dev/null'; shift; }; eval "set -o pipefail && LD_LIBRARY_PATH=lib src/json --verbose $@$n"; }

$ echo -e 't\xc2\xa0'|json -S -uV
t\u00a0\n
$ echo -e 't\xc2'|json --null -S -uV
json: error: <stdin>:1:3: invalid utf-8 encoding
json: error: <stdin>:1:3: t\xc2
json: error: <stdin>:1:3:      ^
$ echo -e 't\xa0'|json --null -S -uV
json: error: <stdin>:1:2: invalid utf-8 encoding
json: error: <stdin>:1:2: t\xa0
json: error: <stdin>:1:2:  ^
$

$ echo -e '\t\xc2\xa0'|json -S -uV
\t\u00a0\n
$ echo -e '\t\xc2'|json --null -S -uV
json: error: <stdin>:1:3: invalid utf-8 encoding
json: error: <stdin>:1:3: \t\xc2
json: error: <stdin>:1:3:       ^
$ echo -e '\t\xa0'|json --null -S -uV
json: error: <stdin>:1:2: invalid utf-8 encoding
json: error: <stdin>:1:2: \t\xa0
json: error: <stdin>:1:2:   ^
$

$ echo -e '\xe2\x80\xa0\xc3\xa0'|json -S -uV
\u2020\u00e0\n
$ echo -e '\xe2\x80\xa0\xc3'|json --null -S -uV
json: error: <stdin>:1:5: invalid utf-8 encoding
json: error: <stdin>:1:5: \xe2\x80\xa0\xc3
json: error: <stdin>:1:5:                 ^
$ echo -e '\xe2\x80\xa0\xa0'|json --null -S -uV
json: error: <stdin>:1:4: invalid utf-8 encoding
json: error: <stdin>:1:4: \xe2\x80\xa0\xa0
json: error: <stdin>:1:4:             ^
$

$ echo -e '\xf0\x90\x80\x80\xc3\xa0'|json -S -uV
json: error: <stdin>:1:1: non-BMP utf-8 encoding
json: error: <stdin>:1:1: \xf0\x90\x80\x80\xc3\xa0
json: error: <stdin>:1:1: ^
$ echo -e '\xf0\x90\x80\x80\xc3\xa0'|json -S -uV -s
\ud800\udc00\u00e0\n
$ echo -e '\xf0\x90\x80\x80\xc3'|json --null -S -uV -s
json: error: <stdin>:1:6: invalid utf-8 encoding
json: error: <stdin>:1:6: \xf0\x90\x80\x80\xc3
json: error: <stdin>:1:6:                     ^
$ echo -e '\xf0\x90\x80\x80\xa0'|json --null -S -uV -s
json: error: <stdin>:1:5: invalid utf-8 encoding
json: error: <stdin>:1:5: \xf0\x90\x80\x80\xa0
json: error: <stdin>:1:5:                 ^
$ 

$ echo -e '"t\xc2\xa0"'|json -O -luV && echo OK
OK
$ echo -e '"t\xc2"'|json -O -luV
json: error: <stdin>:1:4: lex error: invalid utf-8 encoding
json: error: <stdin>:1:4: "t\xc2"
json: error: <stdin>:1:4:       ^
$ echo -e '"t\xa0"'|json -O -luV
json: error: <stdin>:1:3: lex error: invalid utf-8 encoding
json: error: <stdin>:1:3: "t\xa0"
json: error: <stdin>:1:3:   ^
$

$ echo -e '"\\t\xc2\xa0"'|json -O -luV && echo OK
OK
# stev: BUG: 'json' should indicate the error position at 1:5 not 1:4:
$ echo -e '"\\t\xc2"'|json -O -luV
json: error: <stdin>:1:4: lex error: invalid utf-8 encoding
json: error: <stdin>:1:4: "\\t\xc2"
json: error: <stdin>:1:4:     ^
# stev: BUG: 'json' should indicate the error position at 1:4 not 1:3:
$ echo -e '"\\t\xa0"'|json -O -luV
json: error: <stdin>:1:3: lex error: invalid utf-8 encoding
json: error: <stdin>:1:3: "\\t\xa0"
json: error: <stdin>:1:3:    ^
$

$ echo -e '"\\u2020\xc3\xa0"'|json -O -luV && echo OK
OK
# stev: BUG: 'json' should indicate the error position at 1:9 not 1:4:
$ echo -e '"\\u2020\xc3"'|json -O -luV
json: error: <stdin>:1:4: lex error: invalid utf-8 encoding
json: error: <stdin>:1:4: "\\u2020\xc3"
json: error: <stdin>:1:4:     ^
# stev: BUG: 'json' should indicate the error position at 1:8 not 1:3:
$ echo -e '"\\u2020\xa0"'|json -O -luV
json: error: <stdin>:1:3: lex error: invalid utf-8 encoding
json: error: <stdin>:1:3: "\\u2020\xa0"
json: error: <stdin>:1:3:    ^
$

$ echo -e '"\\ud800\\udc00\xc3\xa0"'|json -O -luV -s && echo OK
OK
# stev: BUG: 'json' should indicate the error position at 1:15 not 1:7:
$ echo -e '"\\ud800\\udc00\xc3"'|json -O -luV -s
json: error: <stdin>:1:7: lex error: invalid utf-8 encoding
json: error: <stdin>:1:7: "\\ud800\\udc00\xc3"
json: error: <stdin>:1:7:        ^
# stev: BUG: 'json' should indicate the error position at 1:14 not 1:6:
$ echo -e '"\\ud800\\udc00\xa0"'|json -O -luV -s
json: error: <stdin>:1:6: lex error: invalid utf-8 encoding
json: error: <stdin>:1:6: "\\ud800\\udc00\xa0"
json: error: <stdin>:1:6:       ^
$

--------------------------------------------------------------------------------

$ date
Fri Dec  6 18:55:17 EET 2019

$ json -F -- json-litex.so -D <<< '{"abc":"0","xyz":"1"}' >/dev/null && echo OK
OK
$

# stev: BUG: the command below shouldn't produce any failed assertion:
$ json -F -- json-litex.so -D -q strcmp <<< '{"abc":"0","xyz":"1"}' >/dev/null && echo OK
json-litex.so: fatal error: assertion failed: json-litex.c:8948:json_litex_object_attr_gen_def: a == b
$

--------------------------------------------------------------------------------

$ date
Fri Feb  8 08:38:33 EET 2019

# stev: BUG: as per RFC7159, Section 7, strings must allow plain ASCII DEL chars:
$ echo -e '"\x7f"'|json -VOl
json: error: <stdin>:1:2: lex error: invalid string literal
json: error: <stdin>:1:2: "\x7f"
json: error: <stdin>:1:2:  ^
$

--------------------------------------------------------------------------------

$ date
Tue Nov 27 20:06:07 EET 2018

# stev: BUG: the expected error position is 1:70:
$ json -V -Tc <<< '{"type":"dict","args":[{"name":"\tfoo","type":"null"}],"expr":"`\tfoo"}'
json: error: <stdin>:1:69: meta error: invalid dict expression: unexpected end of expression
json: error: <stdin>:1:69: o","type":"null"}],"expr":"`\\tfoo"}
json: error: <stdin>:1:69:                                  ^
# stev: BUG: the expected error position is 1:74:
$ json -V -Tc <<< '{"type":"dict","args":[{"name":"\t\tfoo","type":"null"}],"expr":"`\t\tfoo"}'
json: error: <stdin>:1:72: meta error: invalid dict expression: unexpected end of expression
json: error: <stdin>:1:72: ","type":"null"}],"expr":"`\\t\\tfoo"}
json: error: <stdin>:1:72:                                   ^
# stev: BUG: the expected error position is 1:78:
$ json -V -Tc <<< '{"type":"dict","args":[{"name":"\t\t\tfoo","type":"null"}],"expr":"`\t\t\tfoo"}'
json: error: <stdin>:1:75: meta error: invalid dict expression: unexpected end of expression
json: error: <stdin>:1:75: ,"type":"null"}],"expr":"`\\t\\t\\tfoo"}
json: error: <stdin>:1:75:                                    ^
$

--------------------------------------------------------------------------------

$ date
Thu Apr 26 10:52:44 EEST 2018

# stev: note that this entry is a refined version of that above which is dated
# 'Sun Dec 31 12:07:39 EET 2017'

$ echo -n|json -Vt <(echo '{"type":"object",}') --echo
json: error: /dev/fd/63:1:18: type lib error: parse error: unexpected token
$

$ echo -n|json -Vt <(echo -e '{"type":"object",\n}') --parse
json: error: /dev/fd/63:2:1: type lib error: parse error: unexpected token
$ echo -n|json -Vt <(echo -e '{"type":"object",\n}') --pretty
json: error: /dev/fd/63:2:1: type lib error: parse error: unexpected token
$ echo -n|json -Vt <(echo -e '{"type":"object",\n}') --terse
json: error: /dev/fd/63:2:1: type lib error: parse error: unexpected token
$

# stev: BUG: the assertion below shouldn't have failed!
$ echo -n|json -Vt <(echo -e '{"type":"object",\n}') --echo
json: error: /dev/fd/63:2:1: type lib error: parse error: unexpected token
json: fatal error: assertion failed: json-base.c:492:text_address_get_offset: false
$

--------------------------------------------------------------------------------

$ date
Sun Dec  3 20:45:34 EET 2017

$ json -VO -u <<< $'{"plain":"\xef\xbf\xc0"}'
json: error: <stdin>:1:13: lex error: invalid utf-8 encoding
json: error: <stdin>:1:13: {"plain":"\xef\xbf\xc0"}
json: error: <stdin>:1:13:                   ^
$

# stev: BUG: the byte sequence '\xef\xbf\xc0' is invalid UTF8 and was correctly
# rejected by the command above; the following command should also reject it:
$ json -VT -u <<< $'{"plain":"\xef\xbf\xc0"}' && echo OK
OK
$

--------------------------------------------------------------------------------

$ date
Wed Nov  8 15:14:32 EET 2017

$ cd test

$ norm-err() { sed -r 's|json\.so: fatal error:|\n\0|'; }
$ dict-gen() { ../lib/test-gen --dict --depth=1 "$@"; }

# stev: important note: the platform running 'json' commands below is such that
# BIT_SET_VAL_BITS in 'lib/bit_set.h' -- i.e. the width of 'uintptr_t' -- is 64.

$ json -t <(dict-gen -T -k64 -e '~`63`') -OV <<< '{}'
json: error: <stdin>:1:2: type check error: "dict" expression falsified: missing required args: "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61" and "62"
json: error: <stdin>:1:2: {}
json: error: <stdin>:1:2:  ^
$

# stev: BUG: the command below shouldn't produce any failed assertion:
$ json -t <(dict-gen -T -k65 -e '~`64`') -OV <<< '{}' 2>&1|norm-err
json: error: <stdin>:1:2: type check error: "dict" expression falsified: missing required args: "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63"
json.so: fatal error: assertion failed: json-type.c:9387:json_type_check_error_printer_done: prt->i == prt->count
$

$ dict-gen -V -k63|json -t <(dict-gen -T -k64 -e '~`63`') -OV && echo OK
OK
$

# stev: BUG: the command below shouldn't fail, since the input provided to 'json'
# matches the type definition given; the root of this issue is -- similarly to
# the previous failed command above -- the macro BIT_SET_VAL_MASK_ in 'lib/bit-set.h':
$ set -o pipefail && dict-gen -V -k64|json -t <(dict-gen -T -k65 -e '~`64`') -OV && echo OK
json: error: <stdin>:1:493: type check error: "dict" expression falsified: missing required args: json.so: fatal error: assertion failed: json-type.c:9387:json_type_check_error_printer_done: prt->i == prt->count
$

--------------------------------------------------------------------------------

$ date
Fri Jun 16 16:52:54 EEST 2017

# stev: BUG: the error position below should have been 2:5, indicating the '+' char:
$ json -V -Tc <<< $'{"type":"dict","args":[{"name":"a","type":"number"}],"expr":\n"a\\t+"}'
json: error: <stdin>:2:6: meta error: invalid dict expression: unexpected char
json: error: <stdin>:2:6: ,"type":"number"}],"expr":\n"a\\t+"}
json: error: <stdin>:2:6:                                   ^
$

--------------------------------------------------------------------------------

$ date
Sat May  6 16:19:48 EEST 2017

# stev: yet another bug in lib/json.c:json_validate_utf8:

# stev: BUG: the following UTF-8 sequence is invalid, yet accepted by 'json':
$ echo -ne '"\xed\xa0\x80"'|json -luOV && echo OK
OK
$

--------------------------------------------------------------------------------

$ date
Fri Apr 28 01:23:23 EEST 2017

# stev: the following bug was introduced in 'src/json2.c' by commit dae87fb9

# stev: correct output:
$ json -J <<< '{"a":{"x":"foo"}}'
/a/x=foo
# stev: BUG: the expected output is "/a/x=foo":
$ json -J <<< '{"a":{"b":{},"x":"foo"}}'
/x=foo
# stev: BUG: the expected output is "/a/x=foo":
$ json -J <<< '{"a":{"b":{"c":{}},"x":"foo"}}'
/x=foo
$

--------------------------------------------------------------------------------

$ date
Mon Feb 20 11:13:22 EET 2017

# stev: lib/json.c:json_validate_utf8 is *not* getting a NUL-terminated buffer:
# therefore the macro INC must preincrement the pointer arg before checking for
# it being in range!!!

# stev: input correctly rejected:
$ echo -e '"\xe1\x80"'|json -luV -O
json: error: <stdin>:1:4: lex error: invalid utf-8 encoding
json: error: <stdin>:1:4: "\xe1\x80"
json: error: <stdin>:1:4:          ^
# stev: BUG: input cannot be accepted, since "\xe1\x80" is invalid UTF8:
$ echo -e '"\xf1\x80\x80\x80""a\xe1\x80"'|json -luV -mO
$

--------------------------------------------------------------------------------

$ date
Sun Feb 19 10:54:05 EET 2017

# stev: yet again a bug in lib/json.c:json_validate_utf8: the macro INC issues a
# 'break' when input buffer was exceeded instead of 'return false'!!!

# stev: input correctly rejected, but for the wrong reason (this is very tricky!):
$ echo -e '"\xe2"'|json -luV -O
json: error: <stdin>:1:3: lex error: invalid utf-8 encoding
json: error: <stdin>:1:3: "\xe2"
json: error: <stdin>:1:3:      ^
# stev: BUG: input cannot be accepted, since "\xe2" is invalid UTF8:
$ echo -e '"\xe1\x80\x80""\xe2"'|json -luV -mO
$

--------------------------------------------------------------------------------

$ date
Sun Sep 18 10:08:59 EEST 2016

# stev: BUG: 'json' should indicate the error position at 1:3 not 1:4:
$ echo -e '"\xf4\xbf"'|json -O -luV
json: error: <stdin>:1:4: lex error: invalid utf-8 encoding
json: error: <stdin>:1:4: "\xf4\xbf"
json: error: <stdin>:1:4:          ^
# stev: BUG: 'json' should indicate the error position at 1:3 not 1:5:
$ echo -e '"\xf4\xbf\xbf"'|json -O -luV
json: error: <stdin>:1:5: lex error: invalid utf-8 encoding
json: error: <stdin>:1:5: "\xf4\xbf\xbf"
json: error: <stdin>:1:5:              ^
# stev: BUG: the following input is invalid UTF8 yet accepted by 'json':
$ echo -e '"\xf4\xbf\xbf\xbf"'|json -O -luV
$ echo $?
0
$

--------------------------------------------------------------------------------

$ date
Thu Jun 16 08:26:26 EEST 2016

$ json -O <<< '{"a":1;}' --no-verbose
json: error: <stdin>:1:7: lex error: invalid char
$ json -O <<< '{"a":1;}' -V
json: error: <stdin>:1:7: lex error: invalid char
json: error: <stdin>:1:7: {"a":1;}
json: error: <stdin>:1:7:       ^
$ json -Tc <<< '{"a":1;}' --no-verbose
json: error: <stdin>:1:7: parse error: invalid char
# stev: BUG: the front end shouldn't fail to print out the error context:
$ json -Tc <<< '{"a":1;}' -V
json: error: <stdin>:1:7: parse error: invalid char
json: error: <stdin>: 'error-context-size' is too small for printing out input error context
$

--------------------------------------------------------------------------------

$ date
Mon May  9 13:04:30 EEST 2016

$ json -d '"type"' <<< '1'
1
$ json <<< ''
json: error: <stdin>:2:1: parse error: unexpected token
json: error: <stdin>:2:1: 
json: error: <stdin>:2:1: ^
# stev: BUG: the following failed assertion occur in the front-end on '\n' input
# when specifying a type in the command line:
$ json -d '"type"' <<< ''
json: error: <stdin>:2:1: parse error: unexpected token
json: fatal error: assertion failed: json-base.c:218:pos_error_verbose: x < e
$

# stev: note that the bug above occurs in the source file 'json-base.c' in
# the function 'pos_error_verbose' upon the second call of it in the function
# 'obj_json_base_run'; the bug popes out if and only if 'keep_mem_buf' is set
# to 'true'

--------------------------------------------------------------------------------

$ date
Mon Apr 18 10:12:14 EEST 2016

# stev: BUG: incorrect error message; it should have been: expected an object of type `"null"' or `"number"'
$ json -d '{"type":"list","args":[{"type":"array","args":"null"},{"type":"array","args":["number"]}]}' <<< '[false]'
json: error: <stdin>:1:2: type check error: type mismatch: expected an object of type `"number"'
json: error: <stdin>:1:2: [false]
json: error: <stdin>:1:2:  ^
[
$

# stev: BUG: rejected correct JSON input:
$ json -d '{"type":"list","args":[{"type":"object","args":[{"name":"faa","type":"null"}]},{"type":"object","args":[]}]}' <<< '{}'
json: error: <stdin>:1:2: type check error: too few arguments
json: error: <stdin>:1:2: {}
json: error: <stdin>:1:2:  ^
{
$

# stev: BUG: incorrect JSON input which is not rejected:
$ json -d '{"type":"list","args":[{"type":"array","args":"null"},{"type":"array","args":["number","number"]}]}' <<< '[null,1]'
[null,1]
$

# stev: BUG: rejected correct JSON input:
$ json -d '{"type":"list","args":[{"type":"array","args":["null"]},{"type":"array","args":{"plain":null}}]}' <<< '[null,null]'
json: error: <stdin>:1:6: type check error: too many arguments
json: error: <stdin>:1:6: [null,null]
json: error: <stdin>:1:6:      ^
[null
$

# stev: BUG: invalid JSON input: too few arguments
$ json -d '{"type":"list","args":[{"type":"array","args":["null"]}]}' <<< '[]'
[]
$

# stev: BUG: invalid JSON input: too few arguments
$ json -d '{"type":"list","args":[{"type":"array","args":["null","null"]}]}' <<< '[null]'
[null]
$

--------------------------------------------------------------------------------

$ date
Sat Apr 16 16:30:25 EEST 2016

$ json -d '{"type":"list","args":[{"type":"array","args":{"type":"list","args":["number"]}},{"type":"array","args":["number"]}]}' <<< '[1]'
[1]
$

# stev: BUG: the type def below should have been rejected as ambiguous:
$ json -Tc <<< '{"type":"list","args":[{"type":"array","args":{"type":"list","args":["number"]}},{"type":"array","args":["number"]}]}'
$

# stev: BUG: the type def below should have been rejected as ambiguous:
$ json -d '{"type":"list","args":[{"type":"array","args":{"type":"array","args":"number"}},{"type":"array","args":{"type":"list","args":["number"]}}]}' <<< '[0]'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"array","args":{"type":"array","args":"number"}},{"type":"array","args":{"type":"list","args":["number"]}}]}' -- the mismatched arg is at 1:2
json: error: <stdin>:1:1: [0]
json: error: <stdin>:1:1: ^
[
$

# stev: BUG: correctly typed JSON input, yet
$ json -d '{"type":"list","args":[{"type":"array","args":{"type":"list","args":["number"]}}]}' <<< '[0]'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"array","args":{"type":"list","args":["number"]}}]}' -- the mismatched arg is at 1:2
json: error: <stdin>:1:1: [0]
json: error: <stdin>:1:1: ^
[
$

# stev: BUG: correctly types JSON input, yet
$ json -d '{"type":"list","args":[{"type":"array","args":{"type":"list","args":["number"]}}]}' <<< '[0,1]'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"array","args":{"type":"list","args":["number"]}}]}' -- the mismatched arg is at 1:2
json: error: <stdin>:1:1: [0,1]
json: error: <stdin>:1:1: ^
[
$

--------------------------------------------------------------------------------

$ date
Sat Apr 16 08:42:29 EEST 2016

# stev: BUG: apparently correct JSON input yet it is rejected; this is in fact an ambiguity issue:
$ json -d '{"type":"list","args":[{"type":"array","args":{"type":"list","args":["number"]}},{"type":"array","args":["number","number"]}]}' <<< '[1]'
json: error: <stdin>:1:3: type check error: too few arguments
json: error: <stdin>:1:3: [1]
json: error: <stdin>:1:3:   ^
[1
$

--------------------------------------------------------------------------------

$ date
Sun Apr 10 09:51:56 EEST 2016

$ json -d '{"type":"list","args":[{"type":"array","args":{"type":"array","args":"number"}},{"type":"array","args":{"type":"array","args":"string"}}]}' <<< '[[false]]'
json: error: <stdin>:1:3: type check error: type mismatch: expected an object of type `"number"'
json: error: <stdin>:1:3: [[false]]
json: error: <stdin>:1:3:   ^
[[
$ json -d '{"type":"list","args":[{"type":"array","args":{"type":"array","args":"number"}},{"type":"array","args":{"type":"array","args":"string"}}]}' <<< '[[0]]'
[[0]]
# stev: BUG: the type def below is not ambiguous, yet the type checking fails:
$ json -d '{"type":"list","args":[{"type":"array","args":{"type":"array","args":"number"}},{"type":"array","args":{"type":"array","args":"string"}}]}' <<< '[[""]]'
json: error: <stdin>:1:3: type check error: type mismatch: expected an object of type `"number"'
json: error: <stdin>:1:3: [[""]]
json: error: <stdin>:1:3:   ^
[[
# stev: a partial solution to this problem is to reject for the time being these
# kinds of type definitions with the error message *type def not yet supported*
$

--------------------------------------------------------------------------------

$ date
Sat Apr  9 14:48:12 EEST 2016

$ json -d '{"type":"list","args":[{"type":"array","args":"type"},{"type":"array","args":"array"}]}' <<< '[null,null]'
[null,null]
$ json -d '{"type":"list","args":[{"type":"array","args":"type"},{"type":"array","args":"array"}]}' <<< '[{},null]'
[{},null]
# stev: the following JSON input appears to be correctly typed, yet the type
# checking rejects it: this is so because the type definition is ambiguous:
$ json -d '{"type":"list","args":[{"type":"array","args":"type"},{"type":"array","args":"array"}]}' <<< '[[],null]'
json: error: <stdin>:1:5: type check error: type mismatch: expected an object of type `"array"'
json: error: <stdin>:1:5: [[],null]
json: error: <stdin>:1:5:     ^
[[],
$

# stev: BUG: the following type definition is ambiguous and must be rejected:
$ json -Ta <<< '{"type":"list","args":[{"type":"array","args":"type"},{"type":"array","args":"array"}]}' >/dev/null && echo OK
OK
$

# stev: the same as above, but with the open array replaced with a closed one:
$ json -d '{"type":"list","args":[{"type":"array","args":["type","boolean"]},{"type":"array","args":["array","number"]}]}' <<< '[[],0]'
[[],0]
# the JSON input appears to be correctly typed, yet the type checking rejects it:
# this is so because the type definition is ambiguous:
$ json -d '{"type":"list","args":[{"type":"array","args":["type","boolean"]},{"type":"array","args":["array","number"]}]}' <<< '[[],false]'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"array","args":["type","boolean"]},{"type":"array","args":["array","number"]}]}' -- the mismatched arg is at 1:5
json: error: <stdin>:1:1: [[],false]
json: error: <stdin>:1:1: ^
[[],
$

# stev: BUG: the following type definition is ambiguous and must be rejected:
$ json -Ta <<< '{"type":"list","args":[{"type":"array","args":["type","boolean"]},{"type":"array","args":["array","number"]}]}' >/dev/null && echo OK
OK
$

# stev: the same as above, but with the closed array replaced with an object:
$ json -d '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"type"},{"name":"bar","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":"array"},{"name":"bar","type":"number"}]}]}' <<< '{"foo":[],"bar":0}'
{"foo":[],"bar":0}
# the JSON input appears to be correctly typed, yet the type checking rejects it:
# this is so because the type definition is ambiguous:
$ json -d '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"type"},{"name":"bar","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":"array"},{"name":"bar","type":"number"}]}]}' <<< '{"foo":[],"bar":false}'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"type"},{"name":"bar","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":"array"},{"name":"bar","type":"number"}]}]}' -- the mismatched arg is at 1:17
json: error: <stdin>:1:1: {"foo":[],"bar":false}
json: error: <stdin>:1:1: ^
{"foo":[],"bar":
$

# stev: BUG: the following type definition is ambiguous and must be rejected:
$ json -Ta <<< '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"type"},{"name":"bar","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":"array"},{"name":"bar","type":"number"}]}]}' >/dev/null && echo OK
OK
$

--------------------------------------------------------------------------------

$ date
Wed Apr  6 12:31:26 EEST 2016

# stev: BUG: the JSON input below should have passed the type checking successfully:
$ json -d '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"number"}]},{"type":"object","args":[{"name":"foo","type":"number"},{"name":"bar","type":"number"}]}]}' <<< '{"foo":0,"bar":1}'
json: error: <stdin>:1:9: type check error: too many arguments
json: error: <stdin>:1:9: {"foo":0,"bar":1}
json: error: <stdin>:1:9:         ^
{"foo":0
$

# bug correction:
$ json -d '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"number"}]},{"type":"object","args":[{"name":"foo","type":"number"},{"name":"bar","type":"number"}]}]}' <<< '{"foo":0,"bar":1}'
{"foo":0,"bar":1}
$

--------------------------------------------------------------------------------

$ date
Sun Apr  3 15:55:06 EEST 2016

$ json -F <<< '{"type":"object","args":[{"name":"foo","type":{"type":"list","args":[{"type":"array","args":[]},{"type":"array","args":["number"]}]}}]}'
{
    "type": "object",
    "args": [
        {
            "name": "foo",
            "type": {
                "type": "list",
                "args": [
                    {
                        "type": "array",
                        "args": []
                    },
                    {
                        "type": "array",
                        "args": [
                            "number"
                        ]
                    }
                ]
            }
        }
    ]
}
$

# stev: BUG: the JSON input below should have passed the type checking successfully:
$ json -d '{"type":"object","args":[{"name":"foo","type":{"type":"list","args":[{"type":"array","args":[]},{"type":"array","args":["number"]}]}}]}' <<< '{"foo":[1]}'
json: error: <stdin>:1:9: type check error: too many arguments
json: error: <stdin>:1:9: {"foo":[1]}
json: error: <stdin>:1:9:         ^
{"foo":[
# stev: BUG: the bug above can be narrowed down to the following invocation:
$ json -d '{"type":"list","args":[{"type":"array","args":[]},{"type":"array","args":["number"]}]}' <<< '[1]'
json: error: <stdin>:1:2: type check error: too many arguments
json: error: <stdin>:1:2: [1]
json: error: <stdin>:1:2:  ^
[
$

# the bug above is due to '(p->closed || ...)' below:
$ diff -u json-type.c{~,}
--- json-type.c~	2016-04-03 16:07:52.000000000 +0300
+++ json-type.c	2016-04-03 16:08:17.000000000 +0300
@@ -6977,7 +6977,8 @@
 				const struct json_type_trie_node_t* n = NULL;
 				const struct json_type_node_t* r;
 
-				if (a.array_trie->sym == NULL && o.args->n_arg > 1) { //!!!???
+				if (a.array_trie->sym == NULL
+					&& (p->is_closed || o.args->n_arg > 1)) { //!!!???
 					if (p->open != NULL) {
 						o.args->array_trie = NULL; //!!!ARRAY_TRIE_NULL
 						return JSON_TYPE_CHECK_NODE_RESULT(
$

$ json -d '{"type":"list","args":[{"type":"array","args":["number"]},{"type":"array","args":["number","number"]}]}' <<< '[1]'
[1]
# stev: BUG: this one belongs to the same category as the above:
$ json -d '{"type":"list","args":[{"type":"array","args":["number"]},{"type":"array","args":["number","number"]}]}' <<< '[1,2]'
json: error: <stdin>:1:3: type check error: too many arguments
json: error: <stdin>:1:3: [1,2]
json: error: <stdin>:1:3:   ^
[1
$

# stev: BUG: the JSON input shouldn't have passed type checking:
$ json -d '{"type":"list","args":[{"type":"array","args":"number"},{"type":"array","args":"string"}]}' <<< '[1,""]'
[1,""]
$

# bug correction:
$ json -d '{"type":"list","args":[{"type":"array","args":"number"},{"type":"array","args":"string"}]}' <<< '[1,""]'
json: error: <stdin>:1:4: type check error: type mismatch: expected an object of type `"number"'
json: error: <stdin>:1:4: [1,""]
json: error: <stdin>:1:4:    ^
[1,
$

# stev: BUG: the JSON input below should have passed the type checking successfully:
$ json -d '{"type":"list","args":[{"type":"array","args":"number"},{"type":"array","args":"string"},{"type":"array","args":["number","string"]}]}' <<< '[1,2]'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"array","args":"number"},{"type":"array","args":"string"},{"type":"array","args":["number","string"]}]}' -- the mismatched arg is at 1:4
json: error: <stdin>:1:1: [1,2]
json: error: <stdin>:1:1: ^
[1,
$

# bug correction:
$ json -d '{"type":"list","args":[{"type":"array","args":"number"},{"type":"array","args":"string"},{"type":"array","args":["number","string"]}]}' <<< '[1,2]'
[1,2]
$ json -d '{"type":"list","args":[{"type":"array","args":"number"},{"type":"array","args":"string"},{"type":"array","args":["number","string"]}]}' <<< '[1,""]'
[1,""]
$ json -d '{"type":"list","args":[{"type":"array","args":"number"},{"type":"array","args":"string"},{"type":"array","args":["number","string"]}]}' <<< '["",""]'
["",""]
$

# stev: BUG: the following type definition is ambiguous and must be rejected:
$ json -Ta <<< '{"type":"list","args":[{"type":"array","args":"number"},{"type":"array","args":{"plain":1}}]}' >/dev/null && echo OK
OK
$

--------------------------------------------------------------------------------

$ date
Mon Mar 21 09:06:54 EET 2016

# stev: BUGS of the same category as above due to incomplete implementation of
# type checking of "list" types:

$ json -Tp <<< '{"type":"list","args":[{"type":"array","args":[{"plain":0}]}]}'|json -Po
{
.   "type": "list",
.   "args": [
.   .   {
.   .   .   "type": "array",
.   .   .   "args": [
.   .   .   .   {
.   .   .   .   .   "plain": 0
.   .   .   .   }
.   .   .   ]
.   .   }
.   ]
}
# stev: BUG: the JSON input has a correct type yet the type checking fails:
$ json -t <(echo '{"type":"list","args":[{"type":"array","args":[{"plain":0}]}]}') <<< '[0]'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"array","args":[{"plain":0}]}]}' -- the mismatched arg is at 1:2
json: error: <stdin>:1:1: [0]
json: error: <stdin>:1:1: ^
[
$

$ json -Tp <<< '{"type":"list","args":[{"type":"array","args":[{"plain":0},{"plain":1}]}]}'|json -Po
{
.   "type": "list",
.   "args": [
.   .   {
.   .   .   "type": "array",
.   .   .   "args": [
.   .   .   .   {
.   .   .   .   .   "plain": 0
.   .   .   .   },
.   .   .   .   {
.   .   .   .   .   "plain": 1
.   .   .   .   }
.   .   .   ]
.   .   }
.   ]
}
# stev: BUG: the JSON input has a correct type yet the type checking fails:
$ json -t <(echo '{"type":"list","args":[{"type":"array","args":[{"plain":0},{"plain":1}]}]}') <<< '[0,1]'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"array","args":[{"plain":0},{"plain":1}]}]}' -- the mismatched arg is at 1:2
json: error: <stdin>:1:1: [0,1]
json: error: <stdin>:1:1: ^
[
$

--------------------------------------------------------------------------------

$ date
Sat Mar 19 22:12:49 EET 2016

# stev: incomplete implementation:

$ json -t <(echo '{"type":"list","args":["number",{"type":"array","args":"number"}]}') <<< '1'
1
# stev: BUG: the JSON input has a correct type yet the type checking fails:
$ json -t <(echo '{"type":"list","args":["number",{"type":"array","args":"number"}]}') <<< '[1]'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":["number",{"type":"array","args":"number"}]}'
json: error: <stdin>:1:1: [1]
json: error: <stdin>:1:1: ^
$ json -t <(echo '{"type":"list","args":["number",{"type":"array","args":["number"]}]}') <<< '[1]'
[1]
$

$ json --pretty -o <<< '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":{"type":"object","args":[]}}]}]}'
{
.   "type": "list",
.   "args": [
.   .   {
.   .   .   "type": "object",
.   .   .   "args": [
.   .   .   .   {
.   .   .   .   .   "name": "foo",
.   .   .   .   .   "type": "boolean"
.   .   .   .   }
.   .   .   ]
.   .   },
.   .   {
.   .   .   "type": "object",
.   .   .   "args": [
.   .   .   .   {
.   .   .   .   .   "name": "foo",
.   .   .   .   .   "type": {
.   .   .   .   .   .   "type": "object",
.   .   .   .   .   .   "args": [
.   .   .   .   .   .   ]
.   .   .   .   .   }
.   .   .   .   }
.   .   .   ]
.   .   }
.   ]
}
# stev: BUG: the JSON input has a correct type yet the type checking fails:
$ json -t <(echo '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":{"type":"object","args":[]}}]}]}') <<< '{"foo":{}}'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":{"type":"object","args":[]}}]}]}' -- the mismatched arg is at 1:8
json: error: <stdin>:1:1: {"foo":{}}
json: error: <stdin>:1:1: ^
{"foo":
$

$ json --pretty -o <<< '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":{"type":"array","args":[]}}]}]}'
{
.   "type": "list",
.   "args": [
.   .   {
.   .   .   "type": "object",
.   .   .   "args": [
.   .   .   .   {
.   .   .   .   .   "name": "foo",
.   .   .   .   .   "type": "boolean"
.   .   .   .   }
.   .   .   ]
.   .   },
.   .   {
.   .   .   "type": "object",
.   .   .   "args": [
.   .   .   .   {
.   .   .   .   .   "name": "foo",
.   .   .   .   .   "type": {
.   .   .   .   .   .   "type": "array",
.   .   .   .   .   .   "args": [
.   .   .   .   .   .   ]
.   .   .   .   .   }
.   .   .   .   }
.   .   .   ]
.   .   }
.   ]
}
# stev: BUG: the JSON input has a correct type yet the type checking fails:
$ json -t <(echo '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":{"type":"array","args":[]}}]}]}') <<< '{"foo":[]}'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":{"type":"array","args":[]}}]}]}' -- the mismatched arg is at 1:8
json: error: <stdin>:1:1: {"foo":[]}
json: error: <stdin>:1:1: ^
{"foo":
$

$ json --pretty -o <<< '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":{"type":"array","args":[]}}]},{"type":"object","args":[{"name":"foo","type":{"type":"array","args":["number"]}}]}]}'
{
.   "type": "list",
.   "args": [
.   .   {
.   .   .   "type": "object",
.   .   .   "args": [
.   .   .   .   {
.   .   .   .   .   "name": "foo",
.   .   .   .   .   "type": "boolean"
.   .   .   .   }
.   .   .   ]
.   .   },
.   .   {
.   .   .   "type": "object",
.   .   .   "args": [
.   .   .   .   {
.   .   .   .   .   "name": "foo",
.   .   .   .   .   "type": {
.   .   .   .   .   .   "type": "array",
.   .   .   .   .   .   "args": [
.   .   .   .   .   .   ]
.   .   .   .   .   }
.   .   .   .   }
.   .   .   ]
.   .   },
.   .   {
.   .   .   "type": "object",
.   .   .   "args": [
.   .   .   .   {
.   .   .   .   .   "name": "foo",
.   .   .   .   .   "type": {
.   .   .   .   .   .   "type": "array",
.   .   .   .   .   .   "args": [
.   .   .   .   .   .   .   "number"
.   .   .   .   .   .   ]
.   .   .   .   .   }
.   .   .   .   }
.   .   .   ]
.   .   }
.   ]
}
# stev: BUG: the JSON input has a correct type yet the type checking fails:
$ json -t <(echo '{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":{"type":"array","args":[]}}]},{"type":"object","args":[{"name":"foo","type":{"type":"array","args":["number"]}}]}]}') <<< '{"foo":[1]}'
json: error: <stdin>:1:1: type check error: type mismatch: expected an object of type `{"type":"list","args":[{"type":"object","args":[{"name":"foo","type":"boolean"}]},{"type":"object","args":[{"name":"foo","type":{"type":"array","args":[]}}]},{"type":"object","args":[{"name":"foo","type":{"type":"array","args":["number"]}}]}]}' -- the mismatched arg is at 1:8
json: error: <stdin>:1:1: {"foo":[1]}
json: error: <stdin>:1:1: ^
{"foo":
$

