summaryrefslogtreecommitdiffstats
path: root/unittest/json_lib
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:24:36 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:24:36 +0000
commit06eaf7232e9a920468c0f8d74dcf2fe8b555501c (patch)
treee2c7b5777f728320e5b5542b6213fd3591ba51e2 /unittest/json_lib
parentInitial commit. (diff)
downloadmariadb-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.txt22
-rw-r--r--unittest/json_lib/json_lib-t.c186
-rw-r--r--unittest/json_lib/json_normalize-t.c280
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();
+}