1/* Copyright (c) 2016, MariaDB Corp. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "my_config.h"
17#include "config.h"
18#include <tap.h>
19#include <my_global.h>
20#include <my_sys.h>
21#include <json_lib.h>
22
23/* The character set used for JSON all over this test. */
24static CHARSET_INFO *ci;
25
26#define s_e(j) j, j + strlen((const char *) j)
27
28
29struct st_parse_result
30{
31 int n_keys;
32 int n_values;
33 int n_arrays;
34 int n_objects;
35 int n_steps;
36 int error;
37 uchar keyname_csum;
38};
39
40
41static void parse_json(const uchar *j, struct st_parse_result *result)
42{
43 json_engine_t je;
44
45 bzero(result, sizeof(*result));
46
47 if (json_scan_start(&je, ci, s_e(j)))
48 return;
49
50 do
51 {
52 result->n_steps++;
53 switch (je.state)
54 {
55 case JST_KEY:
56 result->n_keys++;
57 while (json_read_keyname_chr(&je) == 0)
58 {
59 result->keyname_csum^= je.s.c_next;
60 }
61 if (je.s.error)
62 return;
63 break;
64 case JST_VALUE:
65 result->n_values++;
66 break;
67 case JST_OBJ_START:
68 result->n_objects++;
69 break;
70 case JST_ARRAY_START:
71 result->n_arrays++;
72 break;
73 default:
74 break;
75 };
76 } while (json_scan_next(&je) == 0);
77
78 result->error= je.s.error;
79}
80
81
82static const uchar *js0= (const uchar *) "123";
83static const uchar *js1= (const uchar *) "[123, \"text\"]";
84static const uchar *js2= (const uchar *) "{\"key1\":123, \"key2\":\"text\"}";
85static const uchar *js3= (const uchar *) "{\"key1\":{\"ikey1\":321},"
86 "\"key2\":[\"text\", 321]}";
87
88/*
89 Test json_lib functions to parse JSON.
90*/
91static void
92test_json_parsing()
93{
94 struct st_parse_result r;
95 parse_json(js0, &r);
96 ok(r.n_steps == 1 && r.n_values == 1, "simple value");
97 parse_json(js1, &r);
98 ok(r.n_steps == 5 && r.n_values == 3 && r.n_arrays == 1, "array");
99 parse_json(js2, &r);
100 ok(r.n_steps == 5 && r.n_keys == 2 && r.n_objects == 1 && r.keyname_csum == 3,
101 "object");
102 parse_json(js3, &r);
103 ok(r.n_steps == 12 && r.n_keys == 3 && r.n_objects == 2 &&
104 r.n_arrays == 1 && r.keyname_csum == 44,
105 "complex json");
106}
107
108
109static const uchar *p0= (const uchar *) "$.key1[12].*[*]";
110/*
111 Test json_lib functions to parse JSON path.
112*/
113static void
114test_path_parsing()
115{
116 json_path_t p;
117 if (json_path_setup(&p, ci, s_e(p0)))
118 return;
119 ok(p.last_step - p.steps == 4 &&
120 p.steps[0].type == JSON_PATH_ARRAY_WILD &&
121 p.steps[1].type == JSON_PATH_KEY &&
122 p.steps[2].type == JSON_PATH_ARRAY && p.steps[2].n_item == 12 &&
123 p.steps[3].type == JSON_PATH_KEY_WILD &&
124 p.steps[4].type == JSON_PATH_ARRAY_WILD,
125 "path");
126}
127
128
129static const uchar *fj0=(const uchar *) "[{\"k0\":123, \"k1\":123, \"k1\":123},"
130 " {\"k3\":321, \"k4\":\"text\"},"
131 " {\"k1\":[\"text\"], \"k2\":123}]";
132static const uchar *fp0= (const uchar *) "$[*].k1";
133/*
134 Test json_lib functions to search through JSON.
135*/
136static void
137test_search()
138{
139 json_engine_t je;
140 json_path_t p;
141 json_path_step_t *cur_step;
142 int n_matches, scal_values;
143 uint array_counters[JSON_DEPTH_LIMIT];
144
145 if (json_scan_start(&je, ci, s_e(fj0)) ||
146 json_path_setup(&p, ci, s_e(fp0)))
147 return;
148
149 cur_step= p.steps;
150 n_matches= scal_values= 0;
151 while (json_find_path(&je, &p, &cur_step, array_counters) == 0)
152 {
153 n_matches++;
154 if (json_read_value(&je))
155 return;
156 if (json_value_scalar(&je))
157 {
158 scal_values++;
159 if (json_scan_next(&je))
160 return;
161 }
162 else
163 {
164 if (json_skip_level(&je) || json_scan_next(&je))
165 return;
166 }
167
168 }
169
170 ok(n_matches == 3, "search");
171}
172
173
174int main()
175{
176 ci= &my_charset_utf8_general_ci;
177
178 plan(6);
179 diag("Testing json_lib functions.");
180
181 test_json_parsing();
182 test_path_parsing();
183 test_search();
184
185 return exit_status();
186}
187