limbo/testing/json.test
2025-01-29 18:05:40 +02:00

633 lines
17 KiB
Tcl
Executable file

#!/usr/bin/env tclsh
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test json5-ecma-script-1 {
select json('{a:5,b:6}') ;
} {{{"a":5,"b":6}}}
do_execsql_test json5-ecma-script-2 {
select json('{a:5,a:3}') ;
} {{{"a":5,"a":3}}}
do_execsql_test json5-ecma-script-3 {
SELECT json('{ MNO_123$xyz : 789 }');
} {{{"MNO_123$xyz":789}}}
do_execsql_test json5-with-single-trailing-comma-valid {
select json('{"a":5, "b":6, }');
} {{{"a":5,"b":6}}}
do_execsql_test json5-single-quoted {
SELECT json('{"a": ''abcd''}');
} {{{"a":"abcd"}}}
do_execsql_test json5-hexadecimal-1 {
SELECT json('{a: 0x0}')
} {{{"a":0}}}
do_execsql_test json5-hexadecimal-2 {
SELECT json('{a: 0xabcdef}')
} {{{"a":11259375}}}
do_execsql_test json5-hexadecimal-2 {
SELECT json('{a: -0xabcdef}')
} {{{"a":-11259375}}}
do_execsql_test json5-number-1 {
SELECT json('{x: 4.}')
} {{{"x":4.0}}}
do_execsql_test json5-number-2 {
SELECT json('{x: +4.}')
} {{{"x":4.0}}}
do_execsql_test json5-number-3 {
SELECT json('{x: -4.}')
} {{{"x":-4.0}}}
do_execsql_test json5-number-5 {
SELECT json('{x: Infinity}')
} {{{"x":9e999}}}
do_execsql_test json5-number-6 {
SELECT json('{x: -Infinity}')
} {{{"x":-9e999}}}
do_execsql_test json5-multi-comment {
SELECT json(' /* abc */ { /*def*/ aaa /* xyz */ : // to the end of line
123 /* xyz */ , /* 123 */ }')
} {{{"aaa":123}}}
do_execsql_test json_array_str {
SELECT json_array('a')
} {{["a"]}}
do_execsql_test json_array_numbers {
SELECT json_array(1, 1.5)
} {{[1,1.5]}}
do_execsql_test json_array_numbers_2 {
SELECT json_array(1., +2., -2.)
} {{[1.0,2.0,-2.0]}}
do_execsql_test json_array_null {
SELECT json_array(null)
} {{[null]}}
do_execsql_test json_array_not_json {
SELECT json_array('{"a":1}')
} {{["{\"a\":1}"]}}
do_execsql_test json_array_json {
SELECT json_array(json('{"a":1}'))
} {{[{"a":1}]}}
do_execsql_test json_array_nested {
SELECT json_array(json_array(1,2,3), json('[1,2,3]'), '[1,2,3]')
} {{[[1,2,3],[1,2,3],"[1,2,3]"]}}
do_execsql_test json_extract_null {
SELECT json_extract(null, '$')
} {{}}
do_execsql_test json_extract_json_null_type {
SELECT typeof(json_extract('null', '$'))
} {{null}}
do_execsql_test json_arrow_json_null_type {
SELECT typeof('null' -> '$')
} {{text}}
do_execsql_test json_arrow_shift_json_null_type {
SELECT typeof('null' ->> '$')
} {{null}}
do_execsql_test json_extract_empty {
SELECT json_extract()
} {{}}
do_execsql_test json_extract_single_param {
SELECT json_extract(1)
} {{}}
do_execsql_test json_extract_null_invalid_path {
SELECT json_extract(null, 1)
} {{}}
do_execsql_test json_extract_null_invalid_path_2 {
SELECT json_extract(null, CAST(1 AS BLOB))
} {{}}
do_execsql_test json_extract_multiple_nulls {
SELECT json_extract(null, CAST(1 AS BLOB), null, 1, 2, 3)
} {{}}
do_execsql_test json_extract_number {
SELECT json_extract(1, '$')
} {{1}}
do_execsql_test json_extract_number_type {
SELECT typeof(json_extract(1, '$'))
} {{integer}}
do_execsql_test json_arrow_number {
SELECT 1 -> '$'
} {{1}}
do_execsql_test json_arrow_number_type {
SELECT typeof(1 -> '$')
} {{text}}
do_execsql_test json_arrow_shift_number {
SELECT 1 -> '$'
} {{1}}
do_execsql_test json_arrow_shift_number_type {
SELECT typeof(1 ->> '$')
} {{integer}}
do_execsql_test json_extract_object_1 {
SELECT json_extract('{"a": [1,2,3]}', '$.a')
} {{[1,2,3]}}
do_execsql_test json_arrow_object {
SELECT '{"a": [1,2,3]}' -> '$.a'
} {{[1,2,3]}}
do_execsql_test json_arrow_shift_object {
SELECT '{"a": [1,2,3]}' ->> '$.a'
} {{[1,2,3]}}
do_execsql_test json_extract_object_2 {
SELECT json_extract('{"a": [1,2,3]}', '$.a', '$.a[0]', '$.a[1]', '$.a[3]')
} {{[[1,2,3],1,2,null]}}
do_execsql_test json_extract_object_3 {
SELECT json_extract('{"a": [1,2,3]}', '$.a', '$.a[0]', '$.a[1]', null, '$.a[3]')
} {{}}
# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
# \x61 is the ASCII code for 'a'
# do_execsql_test json_extract_with_escaping {
# SELECT json_extract('{"\x61": 1}', '$.a')
# } {{1}}
# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
#do_execsql_test json_extract_with_escaping_2 {
# SELECT json_extract('{"\x61": 1}', '$.\x61')
#} {{1}}
do_execsql_test json_extract_null_path {
SELECT json_extract(1, null)
} {{}}
do_execsql_test json_arrow_null_path {
SELECT 1 -> null
} {{}}
do_execsql_test json_arrow_shift_null_path {
SELECT 1 ->> null
} {{}}
do_execsql_test json_extract_float {
SELECT typeof(json_extract(1.0, '$'))
} {{real}}
do_execsql_test json_arrow_float {
SELECT typeof(1.0 -> '$')
} {{text}}
do_execsql_test json_arrow_shift_float {
SELECT typeof(1.0 ->> '$')
} {{real}}
do_execsql_test json_extract_true {
SELECT json_extract('true', '$')
} {{1}}
do_execsql_test json_extract_true_type {
SELECT typeof(json_extract('true', '$'))
} {{integer}}
do_execsql_test json_arrow_true {
SELECT 'true' -> '$'
} {{true}}
do_execsql_test json_arrow_true_type {
SELECT typeof('true' -> '$')
} {{text}}
do_execsql_test json_arrow_shift_true {
SELECT 'true' ->> '$'
} {{1}}
do_execsql_test json_arrow_shift_true_type {
SELECT typeof('true' ->> '$')
} {{integer}}
do_execsql_test json_extract_false {
SELECT json_extract('false', '$')
} {{0}}
do_execsql_test json_extract_false_type {
SELECT typeof(json_extract('false', '$'))
} {{integer}}
do_execsql_test json_arrow_false {
SELECT 'false' -> '$'
} {{false}}
do_execsql_test json_arrow_false_type {
SELECT typeof('false' -> '$')
} {{text}}
do_execsql_test json_arrow_shift_false {
SELECT 'false' ->> '$'
} {{0}}
do_execsql_test json_arrow_shift_false_type {
SELECT typeof('false' ->> '$')
} {{integer}}
do_execsql_test json_extract_string {
SELECT json_extract('"string"', '$')
} {{string}}
do_execsql_test json_extract_string_type {
SELECT typeof(json_extract('"string"', '$'))
} {{text}}
do_execsql_test json_arrow_string {
SELECT '"string"' -> '$'
} {{"string"}}
do_execsql_test json_arrow_string_type {
SELECT typeof('"string"' -> '$')
} {{text}}
do_execsql_test json_arrow_shift_string {
SELECT '"string"' ->> '$'
} {{string}}
do_execsql_test json_arrow_shift_string_type {
SELECT typeof('"string"' ->> '$')
} {{text}}
do_execsql_test json_arrow_implicit_root_path {
SELECT '{"a":1}' -> 'a';
} {{1}}
do_execsql_test json_arrow_shift_implicit_root_path {
SELECT '{"a":1}' ->> 'a';
} {{1}}
# TODO: fix me after rebasing on top of https://github.com/tursodatabase/limbo/pull/631 - use the Option value in json_extract_single
#do_execsql_test json_arrow_implicit_root_path_undefined_key {
# SELECT '{"a":1}' -> 'x';
#} {{}}
do_execsql_test json_arrow_shift_implicit_root_path_undefined_key {
SELECT '{"a":1}' ->> 'x';
} {{}}
do_execsql_test json_arrow_implicit_root_path_array {
SELECT '[1,2,3]' -> 1;
} {{2}}
do_execsql_test json_arrow_shift_implicit_root_path_array {
SELECT '[1,2,3]' ->> 1;
} {{2}}
do_execsql_test json_arrow_implicit_root_path_array_negative_idx {
SELECT '[1,2,3]' -> -1;
} {{3}}
do_execsql_test json_arrow_shift_implicit_root_path_array_negative_idx {
SELECT '[1,2,3]' ->> -1;
} {{3}}
do_execsql_test json_arrow_implicit_real_cast {
SELECT '{"1.5":"abc"}' -> 1.5;
} {{"abc"}}
do_execsql_test json_arrow_shift_implicit_real_cast {
SELECT '{"1.5":"abc"}' -> 1.5;
} {{"abc"}}
do_execsql_test json_arrow_implicit_true_cast {
SELECT '[1,2,3]' -> true
} {{2}}
do_execsql_test json_arrow_shift_implicit_true_cast {
SELECT '[1,2,3]' ->> true
} {{2}}
do_execsql_test json_arrow_implicit_false_cast {
SELECT '[1,2,3]' -> false
} {{1}}
do_execsql_test json_arrow_shift_implicit_false_cast {
SELECT '[1,2,3]' ->> false
} {{1}}
do_execsql_test json_arrow_chained {
select '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' -> 2 ->> 'f'
} {{7}}
# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
do_execsql_test json_extract_multiple_null_paths {
SELECT json_extract(1, null, null, null)
} {{}}
do_execsql_test json_extract_array {
SELECT json_extract('[1,2,3]', '$')
} {{[1,2,3]}}
do_execsql_test json_arrow_array {
SELECT '[1,2,3]' -> '$'
} {{[1,2,3]}}
do_execsql_test json_arrow_shift_array {
SELECT '[1,2,3]' ->> '$'
} {{[1,2,3]}}
# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
#do_execsql_test json_extract_quote {
# SELECT json_extract('{"\"":1 }', '$.\"')
#} {{1}}
# Overflows 2**32 is equivalent to 0
do_execsql_test json_extract_overflow_int32_1 {
SELECT json_extract('[1,2,3]', '$[4294967296]')
} {{1}}
# Overflows 2**32 + 1 is equivalent to 1
do_execsql_test json_extract_overflow_int32_2 {
SELECT json_extract('[1,2,3]', '$[4294967297]')
} {{2}}
# Overflows -2**32 - 1 is equivalent to -1
do_execsql_test json_extract_overflow_int32_3 {
SELECT json_extract('[1,2,3]', '$[#-4294967297]')
} {{3}}
# Overflows -2**32 - 2 is equivalent to -2
do_execsql_test json_extract_overflow_int32_3 {
SELECT json_extract('[1,2,3]', '$[#-4294967298]')
} {{2}}
# pow(2,63) + 1 == 9223372036854775808
do_execsql_test json_extract_overflow_int64 {
SELECT json_extract('[1,2,3]', '$[9223372036854775808]');
} {{1}}
# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
# pow(2, 127) + 1 == 170141183460469231731687303715884105729
#do_execsql_test json_extract_overflow_int128 {
# SELECT json_extract('[1, 2, 3]', '$[170141183460469231731687303715884105729]');
#} {{2}}
# TODO: fix me - this passes on SQLite and needs to be fixed in Limbo.
#do_execsql_test json_extract_blob {
# select json_extract(CAST('[1,2,3]' as BLOB), '$[1]')
#} {{2}}
do_execsql_test json_array_length {
SELECT json_array_length('[1,2,3,4]');
} {{4}}
do_execsql_test json_array_length_empty {
SELECT json_array_length('[]');
} {{0}}
do_execsql_test json_array_length_root {
SELECT json_array_length('[1,2,3,4]', '$');
} {{4}}
do_execsql_test json_array_length_not_array {
SELECT json_array_length('{"one":[1,2,3]}');
} {{0}}
do_execsql_test json_array_length_via_prop {
SELECT json_array_length('{"one":[1,2,3]}', '$.one');
} {{3}}
do_execsql_test json_array_length_via_index {
SELECT json_array_length('[[1,2,3,4]]', '$[0]');
} {{4}}
do_execsql_test json_array_length_via_index_not_array {
SELECT json_array_length('[1,2,3,4]', '$[2]');
} {{0}}
do_execsql_test json_array_length_via_bad_prop {
SELECT json_array_length('{"one":[1,2,3]}', '$.two');
} {{}}
do_execsql_test json_array_length_nested {
SELECT json_array_length('{"one":[[1,2,3],2,3]}', '$.one[0]');
} {{3}}
do_execsql_test json_type_no_path {
select json_type('{"a":[2,3.5,true,false,null,"x"]}')
} {{object}}
do_execsql_test json_type_root_path {
select json_type('{"a":[2,3.5,true,false,null,"x"]}','$')
} {{object}}
do_execsql_test json_type_array {
select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a')
} {{array}}
do_execsql_test json_type_integer {
select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[0]')
} {{integer}}
do_execsql_test json_type_real {
select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[1]')
} {{real}}
do_execsql_test json_type_true {
select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[2]')
} {{true}}
do_execsql_test json_type_false {
select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[3]')
} {{false}}
do_execsql_test json_type_null {
select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[4]')
} {{null}}
do_execsql_test json_type_text {
select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[5]')
} {{text}}
do_execsql_test json_type_NULL {
select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[6]')
} {{}}
do_execsql_test json_type_cast {
select json_type(1)
} {{integer}}
do_execsql_test json_type_null_arg {
select json_type(null)
} {{}}
do_execsql_test json_error_position_valid {
SELECT json_error_position('{"a":55,"b":72,}');
} {{0}}
do_execsql_test json_error_position_valid_ws {
SELECT json_error_position('{"a":55,"b":72 , }');
} {{0}}
do_execsql_test json_error_position_object {
SELECT json_error_position('{"a":55,"b":72,,}');
} {{16}}
do_execsql_test json_error_position_array_valid {
SELECT json_error_position('["a",55,"b",72,]');
} {{0}}
do_execsql_test json_error_position_array_valid_ws {
SELECT json_error_position('["a",55,"b",72 , ]');
} {{0}}
do_execsql_test json_error_position_array {
SELECT json_error_position('["a",55,"b",72,,]');
} {{16}}
do_execsql_test json_error_position_null {
SELECT json_error_position(NULL);
} {{}}
do_execsql_test json_error_position_complex {
SELECT json_error_position('{a:null,{"h":[1,[1,2,3]],"j":"abc"}:true}');
} {{9}}
do_execsql_test json_object_simple {
SELECT json_object('key', 'value');
} {{{"key":"value"}}}
do_execsql_test json_object_nested {
SELECT json_object('grandparent',json_object('parent', json_object('child', 'value')));
} {{{"grandparent":{"parent":{"child":"value"}}}}}
do_execsql_test json_object_quoted_json {
SELECT json_object('parent', '{"child":"value"}');
} {{{"parent":"{\"child\":\"value\"}"}}}
do_execsql_test json_object_unquoted_json {
SELECT json_object('parent', json('{"child":"value"}'));
} {{{"parent":{"child":"value"}}}}
do_execsql_test json_object_multiple_values {
SELECT json_object('text', 'value', 'json', json_object('key', 'value'), 'int', 1, 'float', 1.5, 'null', null);
} {{{"text":"value","json":{"key":"value"},"int":1,"float":1.5,"null":null}}}
do_execsql_test json_object_empty {
SELECT json_object();
} {{{}}}
do_execsql_test json_object_json_array {
SELECT json_object('ex',json('[52,3]'));
} {{{"ex":[52,3]}}}
do_execsql_test json_from_json_object {
SELECT json(json_object('key','value'));
} {{{"key":"value"}}}
# FIXME: this behaviour differs from sqlite. Although, sqlite docs states
# that this could change in a "future enhancement" (https://www.sqlite.org/json1.html#jobj)
#do_execsql_test json_object_duplicated_keys {
# SELECT json_object('key', 'value', 'key', 'value2');
#} {{{"key":"value2"}}}
#
do_execsql_test json_valid_1 {
SELECT json_valid('{"a":55,"b":72}');
} {1}
do_execsql_test json_valid_2 {
SELECT json_valid('["a",55,"b",72]');
} {1}
do_execsql_test json_valid_3 {
SELECT json_valid( CAST('{"a":1}' AS BLOB) );
} {1}
do_execsql_test json_valid_4 {
SELECT json_valid(123);
} {1}
do_execsql_test json_valid_5 {
SELECT json_valid(12.3);
} {1}
do_execsql_test json_valid_6 {
SELECT json_valid('not a valid json');
} {0}
do_execsql_test json_valid_7 {
SELECT json_valid('{"a":"55,"b":72}');
} {0}
do_execsql_test json_valid_8 {
SELECT json_valid('{"a":55 "b":72}');
} {0}
do_execsql_test json_valid_3 {
SELECT json_valid( CAST('{"a":"1}' AS BLOB) );
} {0}
do_execsql_test json_valid_9 {
SELECT json_valid(NULL);
} {}
do_execsql_test json-patch-basic-1 {
select json_patch('{"a":1}', '{"b":2}');
} {{{"a":1,"b":2}}}
do_execsql_test json-patch-basic-2 {
select json_patch('{"x":100,"y":200}', '{"z":300}');
} {{{"x":100,"y":200,"z":300}}}
do_execsql_test json-patch-preserve-duplicates-1 {
select json_patch('{"x":100,"x":200}', '{"z":300}');
} {{{"x":100,"x":200,"z":300}}}
do_execsql_test json-patch-preserve-duplicates-2 {
select json_patch('{"x":100,"x":200}', '{"x":900}');
} {{{"x":900,"x":200}}}
do_execsql_test json-patch-first-update-wins {
select json_patch('{"x":100,"c":200}', '{"x":900, "x":null}');
} {{{"x":900,"c":200}}}
do_execsql_test json-patch-override-1 {
select json_patch('{"a":1,"b":2}', '{"b":3}');
} {{{"a":1,"b":3}}}
do_execsql_test json-patch-override-2 {
select json_patch('{"name":"john","age":25}', '{"age":26,"city":"NYC"}');
} {{{"name":"john","age":26,"city":"NYC"}}}
do_execsql_test json-patch-nested-1 {
select json_patch('{"user":{"name":"john"}}', '{"user":{"age":30}}');
} {{{"user":{"name":"john","age":30}}}}
do_execsql_test json-patch-nested-2 {
select json_patch('{"settings":{"theme":"dark"}}', '{"settings":{"theme":"light","font":"arial"}}');
} {{{"settings":{"theme":"light","font":"arial"}}}}
do_execsql_test json-patch-array-1 {
select json_patch('{"arr":[1,2,3]}', '{"arr":[4,5,6]}');
} {{{"arr":[4,5,6]}}}
do_execsql_test json-patch-array-2 {
select json_patch('{"list":["a","b"]}', '{"list":["c"]}');
} {{{"list":["c"]}}}
do_execsql_test json-patch-empty-1 {
select json_patch('{}', '{"a":1}');
} {{{"a":1}}}
do_execsql_test json-patch-empty-2 {
select json_patch('{"a":1}', '{}');
} {{{"a":1}}}
do_execsql_test json-patch-deep-nested-1 {
select json_patch(
'{"level1":{"level2":{"value":100}}}',
'{"level1":{"level2":{"newValue":200}}}'
);
} {{{"level1":{"level2":{"value":100,"newValue":200}}}}}
do_execsql_test json-patch-mixed-types-1 {
select json_patch(
'{"str":"hello","num":42,"bool":true}',
'{"arr":[1,2,3],"obj":{"x":1}}'
);
} {{{"str":"hello","num":42,"bool":true,"arr":[1,2,3],"obj":{"x":1}}}}