diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:24:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:24:36 +0000 |
commit | 06eaf7232e9a920468c0f8d74dcf2fe8b555501c (patch) | |
tree | e2c7b5777f728320e5b5542b6213fd3591ba51e2 /unittest/json_lib | |
parent | Initial commit. (diff) | |
download | mariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.tar.xz mariadb-06eaf7232e9a920468c0f8d74dcf2fe8b555501c.zip |
Adding upstream version 1:10.11.6.upstream/1%10.11.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'unittest/json_lib')
-rw-r--r-- | unittest/json_lib/CMakeLists.txt | 22 | ||||
-rw-r--r-- | unittest/json_lib/json_lib-t.c | 186 | ||||
-rw-r--r-- | unittest/json_lib/json_normalize-t.c | 280 |
3 files changed, 488 insertions, 0 deletions
diff --git a/unittest/json_lib/CMakeLists.txt b/unittest/json_lib/CMakeLists.txt new file mode 100644 index 00000000..157f3729 --- /dev/null +++ b/unittest/json_lib/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +# +# This program 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; version 2 of the License. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/regex + ${CMAKE_SOURCE_DIR}/unittest/mytap) + +# +MY_ADD_TESTS(json_lib json_normalize LINK_LIBRARIES strings dbug) diff --git a/unittest/json_lib/json_lib-t.c b/unittest/json_lib/json_lib-t.c new file mode 100644 index 00000000..c5a6df54 --- /dev/null +++ b/unittest/json_lib/json_lib-t.c @@ -0,0 +1,186 @@ +/* Copyright (c) 2016, MariaDB Corp. All rights reserved. + + This program 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; version 2 of the License. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "my_config.h" +#include "config.h" +#include <tap.h> +#include <my_global.h> +#include <my_sys.h> +#include <json_lib.h> + +/* The character set used for JSON all over this test. */ +static CHARSET_INFO *ci; + +#define s_e(j) j, j + strlen((const char *) j) + + +struct st_parse_result +{ + int n_keys; + int n_values; + int n_arrays; + int n_objects; + int n_steps; + int error; + uchar keyname_csum; +}; + + +static void parse_json(const uchar *j, struct st_parse_result *result) +{ + json_engine_t je; + + bzero(result, sizeof(*result)); + + if (json_scan_start(&je, ci, s_e(j))) + return; + + do + { + result->n_steps++; + switch (je.state) + { + case JST_KEY: + result->n_keys++; + while (json_read_keyname_chr(&je) == 0) + { + result->keyname_csum^= je.s.c_next; + } + if (je.s.error) + return; + break; + case JST_VALUE: + result->n_values++; + break; + case JST_OBJ_START: + result->n_objects++; + break; + case JST_ARRAY_START: + result->n_arrays++; + break; + default: + break; + }; + } while (json_scan_next(&je) == 0); + + result->error= je.s.error; +} + + +static const uchar *js0= (const uchar *) "123"; +static const uchar *js1= (const uchar *) "[123, \"text\"]"; +static const uchar *js2= (const uchar *) "{\"key1\":123, \"key2\":\"text\"}"; +static const uchar *js3= (const uchar *) "{\"key1\":{\"ikey1\":321}," + "\"key2\":[\"text\", 321]}"; + +/* + Test json_lib functions to parse JSON. +*/ +static void +test_json_parsing() +{ + struct st_parse_result r; + parse_json(js0, &r); + ok(r.n_steps == 1 && r.n_values == 1, "simple value"); + parse_json(js1, &r); + ok(r.n_steps == 5 && r.n_values == 3 && r.n_arrays == 1, "array"); + parse_json(js2, &r); + ok(r.n_steps == 5 && r.n_keys == 2 && r.n_objects == 1 && r.keyname_csum == 3, + "object"); + parse_json(js3, &r); + ok(r.n_steps == 12 && r.n_keys == 3 && r.n_objects == 2 && + r.n_arrays == 1 && r.keyname_csum == 44, + "complex json"); +} + + +static const uchar *p0= (const uchar *) "$.key1[12].*[*]"; +/* + Test json_lib functions to parse JSON path. +*/ +static void +test_path_parsing() +{ + json_path_t p; + if (json_path_setup(&p, ci, s_e(p0))) + return; + ok(p.last_step - p.steps == 4 && + p.steps[0].type == JSON_PATH_ARRAY_WILD && + p.steps[1].type == JSON_PATH_KEY && + p.steps[2].type == JSON_PATH_ARRAY && p.steps[2].n_item == 12 && + p.steps[3].type == JSON_PATH_KEY_WILD && + p.steps[4].type == JSON_PATH_ARRAY_WILD, + "path"); +} + + +static const uchar *fj0=(const uchar *) "[{\"k0\":123, \"k1\":123, \"k1\":123}," + " {\"k3\":321, \"k4\":\"text\"}," + " {\"k1\":[\"text\"], \"k2\":123}]"; +static const uchar *fp0= (const uchar *) "$[*].k1"; +/* + Test json_lib functions to search through JSON. +*/ +static void +test_search() +{ + json_engine_t je; + json_path_t p; + json_path_step_t *cur_step; + int n_matches, scal_values; + int array_counters[JSON_DEPTH_LIMIT]; + + if (json_scan_start(&je, ci, s_e(fj0)) || + json_path_setup(&p, ci, s_e(fp0))) + return; + + cur_step= p.steps; + n_matches= scal_values= 0; + while (json_find_path(&je, &p, &cur_step, array_counters) == 0) + { + n_matches++; + if (json_read_value(&je)) + return; + if (json_value_scalar(&je)) + { + scal_values++; + if (json_scan_next(&je)) + return; + } + else + { + if (json_skip_level(&je) || json_scan_next(&je)) + return; + } + + } + + ok(n_matches == 3, "search"); +} + + +int main() +{ + ci= &my_charset_utf8mb3_general_ci; + + plan(6); + diag("Testing json_lib functions."); + + test_json_parsing(); + test_path_parsing(); + test_search(); + + return exit_status(); +} diff --git a/unittest/json_lib/json_normalize-t.c b/unittest/json_lib/json_normalize-t.c new file mode 100644 index 00000000..f72e9017 --- /dev/null +++ b/unittest/json_lib/json_normalize-t.c @@ -0,0 +1,280 @@ +/* Copyright (c) 2021 Eric Herman and MariaDB Foundation. + + This program 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; version 2 of the License. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "my_config.h" +#include "config.h" +#include <tap.h> +#include <my_global.h> +#include <json_lib.h> + + +static void +check_json_normalize(const char *in, const char *expected) +{ + int err; + DYNAMIC_STRING result; + + CHARSET_INFO *cs= &my_charset_utf8mb4_general_ci; + + init_dynamic_string(&result, NULL, 0, 0); + + err= json_normalize(&result, in, strlen(in), cs); + + ok(err == 0, "normalize err?"); + + ok(strcmp(expected, result.str) == 0, + "expected '%s' from '%s' but was '%s'", + expected, in, result.str); + + dynstr_free(&result); +} + + +static void +test_json_normalize_invalid(void) +{ + DYNAMIC_STRING result; + + CHARSET_INFO *cs= &my_charset_utf8mb4_general_ci; + + init_dynamic_string(&result, NULL, 0, 0); + ok(json_normalize(&result, STRING_WITH_LEN(""), cs) != 0, + "expected normalized error"); + dynstr_free(&result); + + init_dynamic_string(&result, NULL, 0, 0); + ok(json_normalize(&result, STRING_WITH_LEN("["), cs) != 0, + "expected normalized error"); + dynstr_free(&result); + + init_dynamic_string(&result, NULL, 0, 0); + ok(json_normalize(&result, STRING_WITH_LEN("}"), cs) != 0, + "expected normalized error"); + dynstr_free(&result); + + init_dynamic_string(&result, NULL, 0, 0); + ok(json_normalize(&result, NULL, 0, cs) != 0, + "expected normalized error"); + dynstr_free(&result); +} + + +static void +test_json_normalize_single_kv(void) +{ + const char *in= "" + "{\n" + " \"foo\": \"value\"\n" + "}\n"; + + const char *expected= "{\"foo\":\"value\"}"; + check_json_normalize(in, expected); +} + + +static void +test_json_normalize_multi_kv(void) +{ + const char *in= "" + "{\n" + " \"bar\": \"baz\",\n" + " \"foo\": \"value\"\n" + "}\n"; + + const char *expected= "{\"bar\":\"baz\",\"foo\":\"value\"}"; + check_json_normalize(in, expected); +} + + +static void +test_json_normalize_array(void) +{ + const char *in= "[ \"a\", \"b\", true, false, null ]"; + const char *expected= "[\"a\",\"b\",true,false,null]"; + check_json_normalize(in, expected); +} + + +static void +test_json_normalize_values(void) +{ + check_json_normalize("\"foo\"", "\"foo\""); + check_json_normalize("true", "true"); + check_json_normalize("false", "false"); + check_json_normalize("null", "null"); + check_json_normalize("\"\"", "\"\""); + check_json_normalize("{}", "{}"); + check_json_normalize("[]", "[]"); + check_json_normalize("5", "5.0E0"); + check_json_normalize("5.1", "5.1E0"); + check_json_normalize("-5.1", "-5.1E0"); + check_json_normalize("12345.67890", "1.23456789E4"); + check_json_normalize("2.99792458e8", "2.99792458E8"); + check_json_normalize("6.02214076e23", "6.02214076E23"); + check_json_normalize("6.62607015e-34", "6.62607015E-34"); + check_json_normalize("-6.62607015e-34", "-6.62607015E-34"); +} + + +static void +test_json_normalize_nested_objects(void) +{ + const char *in = "" + "{\n" + " \"wiz\": {\n" + "\t\t\"bang\": \"a\",\n\t\t\"alpha\": false\n\t},\n" + " \"foo\": {\"value\":true}\n" + "}"; + + const char *expected= "{\"foo\":{\"value\":true}," + "\"wiz\":{\"alpha\":false,\"bang\":\"a\"}}"; + check_json_normalize(in, expected); +} + + +static void +test_json_normalize_nested_arrays(void) +{ + const char *in = "" + "[\n" + " \"wiz\",\n" + " [\"bang\", \t\t\"alpha\"\t]\n" + "]"; + + const char *expected= "[\"wiz\",[\"bang\",\"alpha\"]]"; + check_json_normalize(in, expected); +} + + +static void +test_json_normalize_nested_deep(void) +{ + const char *in = "" + "{\n" + " \"foo\": \"value\",\n" + " \"wiz\": [true, false, {\n" + "\t\t\"bang\": \"a\",\n\t\t\"alpha\": 12345.67890\n\t},\n \"string\",\n" + "\t{ \"b\": \"one\", \"a\": \"two\", \"c\": \"three\"}, false,\n" + "\t\t[-1.20, \"w\", \"x\"]],\n" + " \"bar\": \"value2\"\n" + "}\n"; + + const char *expected= "" + "{" + "\"bar\":\"value2\"," + "\"foo\":\"value\"," + "\"wiz\":[" + "true,false," + "{\"alpha\":1.23456789E4,\"bang\":\"a\"}," + "\"string\"," + "{\"a\":\"two\",\"b\":\"one\",\"c\":\"three\"}," + "false," + "[-1.2E0,\"w\",\"x\"]" + "]" + "}"; + check_json_normalize(in, expected); +} + + +/* a "friend" function */ +int +json_normalize_number(DYNAMIC_STRING *out, const char *str, size_t str_len); + + +static void +test_json_normalize_non_utf8(void) +{ + int err; + const char utf8[]= { 0x22, 0xC3, 0x8A, 0x22, 0x00 }; + const char latin[] = { 0x22, 0xCA, 0x22, 0x00 }; + DYNAMIC_STRING result; + CHARSET_INFO *cs_utf8= &my_charset_utf8mb4_bin; + CHARSET_INFO *cs_latin= &my_charset_latin1; + + init_dynamic_string(&result, NULL, 0, 0); + err= json_normalize(&result, utf8, strlen(utf8), cs_utf8); + ok(err == 0, "normalize err?"); + ok((strcmp(utf8, result.str) == 0), "utf8 round trip"); + dynstr_free(&result); + + init_dynamic_string(&result, NULL, 0, 0); + err= json_normalize(&result, latin, strlen(latin), cs_latin); + ok(err == 0, "normalize err?"); + ok((strcmp(utf8, result.str) == 0), "latin to utf8 round trip"); + dynstr_free(&result); +} + + +void +check_number_normalize(const char *in, const char *expected) +{ + int err; + DYNAMIC_STRING buf; + + init_dynamic_string(&buf, NULL, 0, 0); + + err= json_normalize_number(&buf, in, strlen(in)); + ok(err == 0, "normalize number err?"); + + ok(strcmp(buf.str, expected) == 0, + "expected: %s\n" + " but was: %s\n" + " from: %s\n", + expected, + buf.str, + in); + + dynstr_free(&buf); +} + + +int +main(void) +{ + plan(88); + diag("Testing json_normalization."); + + check_number_normalize("0", "0.0E0"); + check_number_normalize("-0.0", "0.0E0"); + check_number_normalize("0E100", "0.0E0"); + check_number_normalize("0.000000E100", "0.0E0"); + check_number_normalize("-0E100", "0.0E0"); + check_number_normalize("-0.000E100", "0.0E0"); + check_number_normalize("1", "1.0E0"); + check_number_normalize("-1", "-1.0E0"); + check_number_normalize("36", "3.6E1"); + check_number_normalize("37.000", "3.7E1"); + check_number_normalize("3.000", "3.0E0"); + check_number_normalize("0.00012345", "1.2345E-4"); + check_number_normalize("32.14e234", "3.214E235"); + check_number_normalize("0.00357e-23", "3.57E-26"); + check_number_normalize("0.00357e23", "3.57E20"); + check_number_normalize("123.456e10", "1.23456E12"); + check_number_normalize("123.456e-9", "1.23456E-7"); + check_number_normalize("0000123.456000000e-9", "1.23456E-7"); + check_number_normalize("0000123.456000000e+9", "1.23456E11"); + + test_json_normalize_invalid(); + test_json_normalize_values(); + test_json_normalize_single_kv(); + test_json_normalize_multi_kv(); + test_json_normalize_array(); + test_json_normalize_nested_objects(); + test_json_normalize_nested_arrays(); + test_json_normalize_nested_deep(); + test_json_normalize_non_utf8(); + + return exit_status(); +} |