1 /* Copyright (c) 2015, 2020, Oracle and/or its affiliates.
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, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include <gtest/gtest.h>
24 #include <cstring>
25 #include <memory>
26 #include <string>
27
28 #include "my_byteorder.h"
29 #include "my_inttypes.h"
30 #include "sql/error_handler.h"
31 #include "sql/json_binary.h"
32 #include "sql/json_dom.h"
33 #include "sql/sql_class.h"
34 #include "sql/sql_time.h"
35 #include "sql_string.h"
36 #include "unittest/gunit/benchmark.h"
37 #include "unittest/gunit/test_utils.h"
38
39 namespace json_binary_unittest {
40
41 using namespace json_binary;
42
43 class JsonBinaryTest : public ::testing::Test {
44 protected:
SetUp()45 virtual void SetUp() { initializer.SetUp(); }
TearDown()46 virtual void TearDown() { initializer.TearDown(); }
47 my_testing::Server_initializer initializer;
thd() const48 THD *thd() const { return initializer.thd(); }
49 };
50
51 /**
52 Get a copy of the string value represented by val.
53 */
get_string(const Value & val)54 static std::string get_string(const Value &val) {
55 return std::string(val.get_data(), val.get_data_length());
56 }
57
create_decimal(double d)58 static my_decimal create_decimal(double d) {
59 my_decimal dec;
60 EXPECT_EQ(E_DEC_OK, double2my_decimal(E_DEC_FATAL_ERROR, d, &dec));
61 return dec;
62 }
63
parse_json(const char * json_text)64 static Json_dom_ptr parse_json(const char *json_text) {
65 auto dom = Json_dom::parse(json_text, strlen(json_text), nullptr, nullptr);
66 EXPECT_NE(nullptr, dom);
67 return dom;
68 }
69
TEST_F(JsonBinaryTest,BasicTest)70 TEST_F(JsonBinaryTest, BasicTest) {
71 Json_dom_ptr dom = parse_json("false");
72 String buf;
73 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
74 Value val1 = parse_binary(buf.ptr(), buf.length());
75 EXPECT_TRUE(val1.is_valid());
76 EXPECT_EQ(Value::LITERAL_FALSE, val1.type());
77
78 dom = parse_json("-123");
79 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
80 Value val2 = parse_binary(buf.ptr(), buf.length());
81 EXPECT_TRUE(val2.is_valid());
82 EXPECT_EQ(Value::INT, val2.type());
83 EXPECT_EQ(-123LL, val2.get_int64());
84
85 dom = parse_json("3.14");
86 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
87 Value val3 = parse_binary(buf.ptr(), buf.length());
88 EXPECT_TRUE(val3.is_valid());
89 EXPECT_EQ(Value::DOUBLE, val3.type());
90 EXPECT_EQ(3.14, val3.get_double());
91
92 dom = parse_json("18446744073709551615");
93 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
94 Value val4 = parse_binary(buf.ptr(), buf.length());
95 EXPECT_TRUE(val4.is_valid());
96 EXPECT_EQ(Value::UINT, val4.type());
97 EXPECT_EQ(18446744073709551615ULL, val4.get_uint64());
98
99 dom = parse_json("\"abc\"");
100 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
101 Value val5 = parse_binary(buf.ptr(), buf.length());
102 EXPECT_TRUE(val5.is_valid());
103 EXPECT_EQ(Value::STRING, val5.type());
104 EXPECT_EQ("abc", get_string(val5));
105
106 dom = parse_json("[ 1, 2, 3 ]");
107 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
108 Value val6 = parse_binary(buf.ptr(), buf.length());
109 EXPECT_TRUE(val6.is_valid());
110 EXPECT_EQ(Value::ARRAY, val6.type());
111 EXPECT_FALSE(val6.large_format());
112 EXPECT_EQ(3U, val6.element_count());
113 for (int i = 0; i < 3; i++) {
114 Value v = val6.element(i);
115 EXPECT_EQ(Value::INT, v.type());
116 EXPECT_EQ(i + 1, v.get_int64());
117 }
118 EXPECT_EQ(Value::ERROR, val6.element(3).type());
119
120 dom = parse_json("[ 1, [ \"a\", [ 3.14 ] ] ]");
121 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
122 // Top-level doc is an array of size 2.
123 Value val7 = parse_binary(buf.ptr(), buf.length());
124 EXPECT_TRUE(val7.is_valid());
125 EXPECT_EQ(Value::ARRAY, val7.type());
126 EXPECT_EQ(2U, val7.element_count());
127 // First element is the integer 1.
128 Value v7_1 = val7.element(0);
129 EXPECT_TRUE(v7_1.is_valid());
130 EXPECT_EQ(Value::INT, v7_1.type());
131 EXPECT_EQ(1, v7_1.get_int64());
132 // The second element is a nested array of size 2.
133 Value v7_2 = val7.element(1);
134 EXPECT_TRUE(v7_2.is_valid());
135 EXPECT_EQ(Value::ARRAY, v7_2.type());
136 EXPECT_EQ(2U, v7_2.element_count());
137 // The first element of the nested array is the string "a".
138 Value v7_3 = v7_2.element(0);
139 EXPECT_TRUE(v7_3.is_valid());
140 EXPECT_EQ(Value::STRING, v7_3.type());
141 EXPECT_EQ("a", get_string(v7_3));
142 // The second element of the nested array is yet another array.
143 Value v7_4 = v7_2.element(1);
144 EXPECT_TRUE(v7_4.is_valid());
145 EXPECT_EQ(Value::ARRAY, v7_4.type());
146 // The second nested array has one element, the double 3.14.
147 EXPECT_EQ(1U, v7_4.element_count());
148 Value v7_5 = v7_4.element(0);
149 EXPECT_TRUE(v7_5.is_valid());
150 EXPECT_EQ(Value::DOUBLE, v7_5.type());
151 EXPECT_EQ(3.14, v7_5.get_double());
152
153 dom = parse_json("{\"key\" : \"val\"}");
154 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
155 Value val8 = parse_binary(buf.ptr(), buf.length());
156 EXPECT_TRUE(val8.is_valid());
157 EXPECT_EQ(Value::OBJECT, val8.type());
158 EXPECT_FALSE(val8.large_format());
159 EXPECT_EQ(1U, val8.element_count());
160 Value val8_k = val8.key(0);
161 EXPECT_TRUE(val8_k.is_valid());
162 EXPECT_EQ(Value::STRING, val8_k.type());
163 EXPECT_EQ("key", get_string(val8_k));
164 Value val8_v = val8.element(0);
165 EXPECT_TRUE(val8_v.is_valid());
166 EXPECT_EQ(Value::STRING, val8_v.type());
167 EXPECT_EQ("val", get_string(val8_v));
168 EXPECT_EQ(Value::ERROR, val8.key(1).type());
169 EXPECT_EQ(Value::ERROR, val8.element(1).type());
170
171 Value v8_v1 = val8.lookup("key");
172 EXPECT_EQ(Value::STRING, v8_v1.type());
173 EXPECT_TRUE(v8_v1.is_valid());
174 EXPECT_EQ("val", get_string(v8_v1));
175
176 dom = parse_json("{ \"a\" : \"b\", \"c\" : [ \"d\" ] }");
177 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
178 Value val9 = parse_binary(buf.ptr(), buf.length());
179 EXPECT_TRUE(val9.is_valid());
180 EXPECT_EQ(Value::OBJECT, val9.type());
181 EXPECT_EQ(2U, val9.element_count());
182 Value v9_k1 = val9.key(0);
183 EXPECT_EQ(Value::STRING, v9_k1.type());
184 EXPECT_EQ("a", get_string(v9_k1));
185 Value v9_v1 = val9.element(0);
186 EXPECT_EQ(Value::STRING, v9_v1.type());
187 EXPECT_EQ("b", get_string(v9_v1));
188 Value v9_k2 = val9.key(1);
189 EXPECT_EQ(Value::STRING, v9_k2.type());
190 EXPECT_EQ("c", get_string(v9_k2));
191 Value v9_v2 = val9.element(1);
192 EXPECT_EQ(Value::ARRAY, v9_v2.type());
193 EXPECT_EQ(1U, v9_v2.element_count());
194 Value v9_v2_1 = v9_v2.element(0);
195 EXPECT_EQ(Value::STRING, v9_v2_1.type());
196 EXPECT_EQ("d", get_string(v9_v2_1));
197
198 EXPECT_EQ("b", get_string(val9.lookup("a")));
199 Value v9_c = val9.lookup("c");
200 EXPECT_EQ(Value::ARRAY, v9_c.type());
201 EXPECT_EQ(1U, v9_c.element_count());
202 Value v9_c1 = v9_c.element(0);
203 EXPECT_EQ(Value::STRING, v9_c1.type());
204 EXPECT_EQ("d", get_string(v9_c1));
205
206 char blob[4];
207 int4store(blob, 0xCAFEBABEU);
208 Json_opaque opaque(MYSQL_TYPE_TINY_BLOB, blob, 4);
209 EXPECT_FALSE(serialize(thd(), &opaque, &buf));
210 Value val10 = parse_binary(buf.ptr(), buf.length());
211 EXPECT_TRUE(val10.is_valid());
212 EXPECT_EQ(Value::OPAQUE, val10.type());
213 EXPECT_EQ(MYSQL_TYPE_TINY_BLOB, val10.field_type());
214 EXPECT_EQ(4U, val10.get_data_length());
215 EXPECT_EQ(0xCAFEBABEU, uint4korr(val10.get_data()));
216
217 dom = parse_json("[true,false,null,0,\"0\",\"\",{},[]]");
218 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
219 Value val11 = parse_binary(buf.ptr(), buf.length());
220 EXPECT_TRUE(val11.is_valid());
221 EXPECT_EQ(Value::ARRAY, val11.type());
222 EXPECT_EQ(8U, val11.element_count());
223 EXPECT_EQ(Value::LITERAL_TRUE, val11.element(0).type());
224 EXPECT_EQ(Value::LITERAL_FALSE, val11.element(1).type());
225 EXPECT_EQ(Value::LITERAL_NULL, val11.element(2).type());
226 EXPECT_EQ(Value::INT, val11.element(3).type());
227 EXPECT_EQ(Value::STRING, val11.element(4).type());
228 EXPECT_EQ(Value::STRING, val11.element(5).type());
229 EXPECT_EQ(Value::OBJECT, val11.element(6).type());
230 EXPECT_EQ(Value::ARRAY, val11.element(7).type());
231 EXPECT_EQ(0, val11.element(3).get_int64());
232 EXPECT_EQ("0", get_string(val11.element(4)));
233 EXPECT_EQ("", get_string(val11.element(5)));
234 EXPECT_EQ(0U, val11.element(6).element_count());
235 EXPECT_EQ(0U, val11.element(7).element_count());
236
237 dom = parse_json("{}");
238 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
239 Value val12 = parse_binary(buf.ptr(), buf.length());
240 EXPECT_TRUE(val12.is_valid());
241 EXPECT_EQ(Value::OBJECT, val12.type());
242 EXPECT_EQ(0U, val12.element_count());
243 EXPECT_EQ(Value::ERROR, val12.lookup("").type());
244 EXPECT_EQ(Value::ERROR, val12.lookup("key").type());
245 EXPECT_FALSE(val12.lookup("no such key").is_valid());
246
247 dom = parse_json("[]");
248 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
249 Value val13 = parse_binary(buf.ptr(), buf.length());
250 EXPECT_TRUE(val13.is_valid());
251 EXPECT_EQ(Value::ARRAY, val13.type());
252 EXPECT_EQ(0U, val13.element_count());
253
254 dom = parse_json(
255 "{\"key1\":1, \"key2\":2, \"key1\":3, \"key1\\u0000x\":4, "
256 "\"key1\\u0000y\":5, \"a\":6, \"ab\":7, \"b\":8, \"\":9, "
257 "\"\":10}");
258 const std::string expected_keys[] = {"",
259 "a",
260 "b",
261 "ab",
262 "key1",
263 "key2",
264 std::string("key1\0x", 6),
265 std::string("key1\0y", 6)};
266 const int64 expected_values[] = {10, 6, 8, 7, 3, 2, 4, 5};
267 EXPECT_FALSE(serialize(thd(), dom.get(), &buf));
268 Value val14 = parse_binary(buf.ptr(), buf.length());
269 EXPECT_TRUE(val14.is_valid());
270 EXPECT_EQ(Value::OBJECT, val14.type());
271 EXPECT_EQ(8U, val14.element_count());
272 for (size_t i = 0; i < val14.element_count(); i++) {
273 EXPECT_EQ(expected_keys[i], get_string(val14.key(i)));
274
275 Value val = val14.element(i);
276 EXPECT_EQ(Value::INT, val.type());
277 EXPECT_EQ(expected_values[i], val.get_int64());
278
279 Value val_lookup = val14.lookup(expected_keys[i]);
280 EXPECT_EQ(Value::INT, val_lookup.type());
281 EXPECT_EQ(expected_values[i], val_lookup.get_int64());
282 }
283
284 // Store a decimal.
285 my_decimal md = create_decimal(123.45);
286 EXPECT_EQ(5U, md.precision());
287 EXPECT_EQ(2, md.frac);
288
289 Json_decimal jd(md);
290 EXPECT_FALSE(serialize(thd(), &jd, &buf));
291 Value val15 = parse_binary(buf.ptr(), buf.length());
292 EXPECT_TRUE(val15.is_valid());
293 EXPECT_EQ(Value::OPAQUE, val15.type());
294 EXPECT_EQ(MYSQL_TYPE_NEWDECIMAL, val15.field_type());
295
296 my_decimal md_out;
297 EXPECT_FALSE(Json_decimal::convert_from_binary(
298 val15.get_data(), val15.get_data_length(), &md_out));
299 EXPECT_EQ(5U, md_out.precision());
300 EXPECT_EQ(2, md_out.frac);
301 double d_out;
302 EXPECT_EQ(E_DEC_OK, my_decimal2double(E_DEC_FATAL_ERROR, &md_out, &d_out));
303 EXPECT_EQ(123.45, d_out);
304 }
305
TEST_F(JsonBinaryTest,EmptyDocument)306 TEST_F(JsonBinaryTest, EmptyDocument) {
307 /*
308 An empty binary document is interpreted as the JSON null literal.
309 This is a special case to handle NULL values inserted into NOT
310 NULL columns using INSERT IGNORE or similar mechanisms.
311 */
312 Value val = parse_binary("", 0);
313 EXPECT_EQ(Value::LITERAL_NULL, val.type());
314 }
315
create_time()316 static MYSQL_TIME create_time() {
317 const char *tstr = "13:14:15.654321";
318 MYSQL_TIME t;
319 MYSQL_TIME_STATUS status;
320 EXPECT_FALSE(
321 str_to_time(&my_charset_utf8mb4_bin, tstr, strlen(tstr), &t, 0, &status));
322 return t;
323 }
324
create_date()325 static MYSQL_TIME create_date() {
326 const char *dstr = "20140517";
327 MYSQL_TIME d;
328 MYSQL_TIME_STATUS status;
329 EXPECT_FALSE(str_to_datetime(&my_charset_utf8mb4_bin, dstr, strlen(dstr), &d,
330 0, &status));
331 return d;
332 }
333
create_datetime()334 static MYSQL_TIME create_datetime() {
335 const char *dtstr = "2015-01-15 15:16:17.123456";
336 MYSQL_TIME dt;
337 MYSQL_TIME_STATUS status;
338 EXPECT_FALSE(str_to_datetime(&my_charset_utf8mb4_bin, dtstr, strlen(dtstr),
339 &dt, 0, &status));
340 return dt;
341 }
342
343 /*
344 Test storing of TIME, DATE and DATETIME.
345 */
TEST_F(JsonBinaryTest,DateAndTimeTest)346 TEST_F(JsonBinaryTest, DateAndTimeTest) {
347 // Create an array that contains a TIME, a DATE and a DATETIME.
348 Json_array array;
349 Json_datetime tt(create_time(), MYSQL_TYPE_TIME);
350 Json_datetime td(create_date(), MYSQL_TYPE_DATE);
351 Json_datetime tdt(create_datetime(), MYSQL_TYPE_DATETIME);
352 array.append_clone(&tt);
353 array.append_clone(&td);
354 array.append_clone(&tdt);
355
356 // Store the array ...
357 String buf;
358 EXPECT_FALSE(serialize(thd(), &array, &buf));
359
360 // ... and read it back.
361 Value val = parse_binary(buf.ptr(), buf.length());
362 EXPECT_TRUE(val.is_valid());
363 EXPECT_EQ(Value::ARRAY, val.type());
364 EXPECT_EQ(3U, val.element_count());
365
366 // The first element should be the TIME "13:14:15.654321".
367 Value t_val = val.element(0);
368 EXPECT_EQ(Value::OPAQUE, t_val.type());
369 EXPECT_EQ(MYSQL_TYPE_TIME, t_val.field_type());
370 const size_t json_datetime_packed_size = Json_datetime::PACKED_SIZE;
371 EXPECT_EQ(json_datetime_packed_size, t_val.get_data_length());
372 MYSQL_TIME t_out;
373 Json_datetime::from_packed(t_val.get_data(), t_val.field_type(), &t_out);
374 EXPECT_EQ(13U, t_out.hour);
375 EXPECT_EQ(14U, t_out.minute);
376 EXPECT_EQ(15U, t_out.second);
377 EXPECT_EQ(654321U, t_out.second_part);
378 EXPECT_FALSE(t_out.neg);
379 EXPECT_EQ(MYSQL_TIMESTAMP_TIME, t_out.time_type);
380
381 // The second element should be the DATE "2014-05-17".
382 Value d_val = val.element(1);
383 EXPECT_EQ(Value::OPAQUE, d_val.type());
384 EXPECT_EQ(MYSQL_TYPE_DATE, d_val.field_type());
385 EXPECT_EQ(json_datetime_packed_size, d_val.get_data_length());
386 MYSQL_TIME d_out;
387 Json_datetime::from_packed(d_val.get_data(), d_val.field_type(), &d_out);
388 EXPECT_EQ(2014U, d_out.year);
389 EXPECT_EQ(5U, d_out.month);
390 EXPECT_EQ(17U, d_out.day);
391 EXPECT_FALSE(d_out.neg);
392 EXPECT_EQ(MYSQL_TIMESTAMP_DATE, d_out.time_type);
393
394 // The third element should be the DATETIME "2015-01-15 15:16:17.123456".
395 Value dt_val = val.element(2);
396 EXPECT_EQ(Value::OPAQUE, dt_val.type());
397 EXPECT_EQ(MYSQL_TYPE_DATETIME, dt_val.field_type());
398 EXPECT_EQ(json_datetime_packed_size, dt_val.get_data_length());
399 MYSQL_TIME dt_out;
400 Json_datetime::from_packed(dt_val.get_data(), dt_val.field_type(), &dt_out);
401 EXPECT_EQ(2015U, dt_out.year);
402 EXPECT_EQ(1U, dt_out.month);
403 EXPECT_EQ(15U, dt_out.day);
404 EXPECT_EQ(15U, dt_out.hour);
405 EXPECT_EQ(16U, dt_out.minute);
406 EXPECT_EQ(17U, dt_out.second);
407 EXPECT_EQ(123456U, dt_out.second_part);
408 EXPECT_FALSE(dt_out.neg);
409 EXPECT_EQ(MYSQL_TIMESTAMP_DATETIME, dt_out.time_type);
410 }
411
412 /*
413 Validate that the contents of an array are as expected. The array
414 should contain values that alternate between literal true, literal
415 false, literal null and the string "a".
416 */
validate_array_contents(const Value & array,size_t expected_size)417 void validate_array_contents(const Value &array, size_t expected_size) {
418 EXPECT_EQ(Value::ARRAY, array.type());
419 EXPECT_TRUE(array.is_valid());
420 EXPECT_EQ(expected_size, array.element_count());
421 for (size_t i = 0; i < array.element_count(); i++) {
422 Value val = array.element(i);
423 EXPECT_TRUE(val.is_valid());
424 Value::enum_type t = val.type();
425 if (i % 4 == 0)
426 EXPECT_EQ(Value::LITERAL_TRUE, t);
427 else if (i % 4 == 1)
428 EXPECT_EQ(Value::LITERAL_FALSE, t);
429 else if (i % 4 == 2)
430 EXPECT_EQ(Value::LITERAL_NULL, t);
431 else {
432 EXPECT_EQ(Value::STRING, t);
433 EXPECT_EQ("a", get_string(val));
434 }
435 }
436 }
437
438 /*
439 Test some arrays and objects that exceed 64KB. Arrays and objects
440 are stored in a different format if more than two bytes are required
441 for the internal offsets.
442 */
TEST_F(JsonBinaryTest,LargeDocumentTest)443 TEST_F(JsonBinaryTest, LargeDocumentTest) {
444 Json_array array;
445 Json_boolean literal_true(true);
446 Json_boolean literal_false(false);
447 Json_null literal_null;
448 Json_string string("a");
449
450 for (int i = 0; i < 20000; i++) {
451 array.append_clone(&literal_true);
452 array.append_clone(&literal_false);
453 array.append_clone(&literal_null);
454 array.append_clone(&string);
455 }
456 EXPECT_EQ(80000U, array.size());
457
458 String buf;
459 EXPECT_FALSE(serialize(thd(), &array, &buf));
460 Value val1 = parse_binary(buf.ptr(), buf.length());
461 EXPECT_TRUE(val1.large_format());
462 {
463 SCOPED_TRACE("");
464 validate_array_contents(val1, array.size());
465 }
466
467 /*
468 Extract the raw binary representation of the large array, and verify
469 that it is valid.
470 */
471 String raw;
472 EXPECT_FALSE(val1.raw_binary(thd(), &raw));
473 {
474 SCOPED_TRACE("");
475 validate_array_contents(parse_binary(raw.ptr(), raw.length()),
476 array.size());
477 }
478
479 Json_array array2;
480 array2.append_clone(&array);
481 array2.append_clone(&array);
482 EXPECT_FALSE(serialize(thd(), &array2, &buf));
483 Value val2 = parse_binary(buf.ptr(), buf.length());
484 EXPECT_TRUE(val2.is_valid());
485 EXPECT_EQ(Value::ARRAY, val2.type());
486 EXPECT_EQ(2U, val2.element_count());
487 {
488 SCOPED_TRACE("");
489 validate_array_contents(val2.element(0), array.size());
490 }
491 {
492 SCOPED_TRACE("");
493 validate_array_contents(val2.element(1), array.size());
494 }
495
496 Json_object object;
497 object.add_clone("a", &array);
498 Json_string s_c("c");
499 object.add_clone("b", &s_c);
500 EXPECT_FALSE(serialize(thd(), &object, &buf));
501 Value val3 = parse_binary(buf.ptr(), buf.length());
502 EXPECT_TRUE(val3.is_valid());
503 EXPECT_TRUE(val3.large_format());
504 EXPECT_EQ(Value::OBJECT, val3.type());
505 EXPECT_EQ(2U, val3.element_count());
506 EXPECT_EQ("a", get_string(val3.key(0)));
507 {
508 SCOPED_TRACE("");
509 validate_array_contents(val3.element(0), array.size());
510 }
511 EXPECT_EQ("b", get_string(val3.key(1)));
512 EXPECT_EQ(Value::STRING, val3.element(1).type());
513 EXPECT_EQ("c", get_string(val3.element(1)));
514
515 {
516 SCOPED_TRACE("");
517 validate_array_contents(val3.lookup("a"), array.size());
518 }
519 EXPECT_EQ("c", get_string(val3.lookup("b")));
520
521 /*
522 Extract the raw binary representation of the large object, and verify
523 that it is valid.
524 */
525 EXPECT_FALSE(val3.raw_binary(thd(), &raw));
526 {
527 SCOPED_TRACE("");
528 Value val_a = parse_binary(raw.ptr(), raw.length()).lookup("a");
529 validate_array_contents(val_a, array.size());
530 }
531
532 /*
533 Bug#23031146: INSERTING 64K SIZE RECORDS TAKE TOO MUCH TIME
534
535 If a big (>64KB) sub-document was located at a deep nesting level,
536 serialization used to be very slow.
537 */
538 {
539 SCOPED_TRACE("");
540 // Wrap "array" in 50 more levels of arrays.
541 constexpr size_t depth = 50;
542 Json_array deeply_nested_array;
543 Json_array *current_array = &deeply_nested_array;
544 for (size_t i = 1; i < depth; i++) {
545 Json_array *a = new (std::nothrow) Json_array();
546 ASSERT_FALSE(current_array->append_alias(a));
547 current_array = a;
548 }
549 current_array->append_clone(&array);
550 // Serialize it. This used to take "forever".
551 ASSERT_FALSE(serialize(thd(), &deeply_nested_array, &buf));
552 // Parse the serialized DOM and verify its contents.
553 Value val = parse_binary(buf.ptr(), buf.length());
554 for (size_t i = 0; i < depth; i++) {
555 ASSERT_EQ(Value::ARRAY, val.type());
556 ASSERT_EQ(1U, val.element_count());
557 val = val.element(0);
558 }
559 validate_array_contents(val, array.size());
560
561 // Now test the same with object.
562 Json_object deeply_nested_object;
563 Json_object *current_object = &deeply_nested_object;
564 for (size_t i = 1; i < depth; i++) {
565 Json_object *o = new (std::nothrow) Json_object();
566 ASSERT_FALSE(current_object->add_alias("key", o));
567 current_object = o;
568 }
569 current_object->add_clone("key", &array);
570 ASSERT_FALSE(serialize(thd(), &deeply_nested_object, &buf));
571 val = parse_binary(buf.ptr(), buf.length());
572 for (size_t i = 0; i < depth; i++) {
573 ASSERT_EQ(Value::OBJECT, val.type());
574 ASSERT_EQ(1U, val.element_count());
575 ASSERT_EQ("key", get_string(val.key(0)));
576 val = val.element(0);
577 }
578 validate_array_contents(val, array.size());
579 }
580 }
581
582 /*
583 Various tests for the Value::raw_binary() function.
584 */
TEST_F(JsonBinaryTest,RawBinaryTest)585 TEST_F(JsonBinaryTest, RawBinaryTest) {
586 Json_array array;
587 Json_string as("a string");
588 array.append_clone(&as);
589 Json_int ji(-123);
590 array.append_clone(&ji);
591 Json_uint jui(42);
592 array.append_clone(&jui);
593 Json_double jd(1.5);
594 array.append_clone(&jd);
595 Json_null jn;
596 array.append_clone(&jn);
597 Json_boolean jbt(true);
598 array.append_clone(&jbt);
599 Json_boolean jbf(false);
600 array.append_clone(&jbf);
601 Json_opaque jo(MYSQL_TYPE_BLOB, "abcd", 4);
602 array.append_clone(&jo);
603
604 Json_object object;
605 object.add_clone("key", &jbt);
606 array.append_clone(&object);
607
608 Json_array array2;
609 array2.append_clone(&jbf);
610 array.append_clone(&array2);
611
612 String buf;
613 EXPECT_FALSE(json_binary::serialize(thd(), &array, &buf));
614 Value v1 = parse_binary(buf.ptr(), buf.length());
615
616 String raw;
617 EXPECT_FALSE(v1.raw_binary(thd(), &raw));
618 Value v1_copy = parse_binary(raw.ptr(), raw.length());
619 EXPECT_EQ(Value::ARRAY, v1_copy.type());
620 EXPECT_EQ(array.size(), v1_copy.element_count());
621
622 EXPECT_FALSE(v1.element(0).raw_binary(thd(), &raw));
623 Value v1_0 = parse_binary(raw.ptr(), raw.length());
624 EXPECT_EQ(Value::STRING, v1_0.type());
625 EXPECT_EQ("a string", std::string(v1_0.get_data(), v1_0.get_data_length()));
626
627 EXPECT_FALSE(v1.element(1).raw_binary(thd(), &raw));
628 Value v1_1 = parse_binary(raw.ptr(), raw.length());
629 EXPECT_EQ(Value::INT, v1_1.type());
630 EXPECT_EQ(-123, v1_1.get_int64());
631
632 EXPECT_FALSE(v1.element(2).raw_binary(thd(), &raw));
633 Value v1_2 = parse_binary(raw.ptr(), raw.length());
634 EXPECT_EQ(Value::UINT, v1_2.type());
635 EXPECT_EQ(42U, v1_2.get_uint64());
636
637 EXPECT_FALSE(v1.element(3).raw_binary(thd(), &raw));
638 Value v1_3 = parse_binary(raw.ptr(), raw.length());
639 EXPECT_EQ(Value::DOUBLE, v1_3.type());
640 EXPECT_EQ(1.5, v1_3.get_double());
641
642 EXPECT_FALSE(v1.element(4).raw_binary(thd(), &raw));
643 Value v1_4 = parse_binary(raw.ptr(), raw.length());
644 EXPECT_EQ(Value::LITERAL_NULL, v1_4.type());
645
646 EXPECT_FALSE(v1.element(5).raw_binary(thd(), &raw));
647 Value v1_5 = parse_binary(raw.ptr(), raw.length());
648 EXPECT_EQ(Value::LITERAL_TRUE, v1_5.type());
649
650 EXPECT_FALSE(v1.element(6).raw_binary(thd(), &raw));
651 Value v1_6 = parse_binary(raw.ptr(), raw.length());
652 EXPECT_EQ(Value::LITERAL_FALSE, v1_6.type());
653
654 EXPECT_FALSE(v1.element(7).raw_binary(thd(), &raw));
655 Value v1_7 = parse_binary(raw.ptr(), raw.length());
656 EXPECT_EQ(Value::OPAQUE, v1_7.type());
657 EXPECT_EQ(MYSQL_TYPE_BLOB, v1_7.field_type());
658 EXPECT_EQ("abcd", std::string(v1_7.get_data(), v1_7.get_data_length()));
659
660 EXPECT_FALSE(v1.element(8).raw_binary(thd(), &raw));
661 Value v1_8 = parse_binary(raw.ptr(), raw.length());
662 EXPECT_EQ(Value::OBJECT, v1_8.type());
663 EXPECT_EQ(object.cardinality(), v1_8.element_count());
664 EXPECT_EQ(Value::LITERAL_TRUE, v1_8.lookup("key").type());
665
666 EXPECT_FALSE(v1.element(8).key(0).raw_binary(thd(), &raw));
667 Value v1_8_key = parse_binary(raw.ptr(), raw.length());
668 EXPECT_EQ(Value::STRING, v1_8_key.type());
669 EXPECT_EQ("key",
670 std::string(v1_8_key.get_data(), v1_8_key.get_data_length()));
671
672 EXPECT_FALSE(v1.element(8).element(0).raw_binary(thd(), &raw));
673 Value v1_8_val = parse_binary(raw.ptr(), raw.length());
674 EXPECT_EQ(Value::LITERAL_TRUE, v1_8_val.type());
675
676 EXPECT_FALSE(v1.element(9).raw_binary(thd(), &raw));
677 Value v1_9 = parse_binary(raw.ptr(), raw.length());
678 EXPECT_EQ(Value::ARRAY, v1_9.type());
679 EXPECT_EQ(array2.size(), v1_9.element_count());
680 EXPECT_EQ(Value::LITERAL_FALSE, v1_9.element(0).type());
681
682 EXPECT_FALSE(v1.element(9).element(0).raw_binary(thd(), &raw));
683 Value v1_9_0 = parse_binary(raw.ptr(), raw.length());
684 EXPECT_EQ(Value::LITERAL_FALSE, v1_9_0.type());
685 }
686
687 /*
688 Create a JSON string of the given size, serialize it as a JSON binary, and
689 then deserialize it and verify that we get the same string back.
690 */
serialize_deserialize_string(const THD * thd,size_t size)691 void serialize_deserialize_string(const THD *thd, size_t size) {
692 SCOPED_TRACE(testing::Message() << "size = " << size);
693 char *str = new char[size];
694 memset(str, 'a', size);
695 Json_string jstr(str, size);
696
697 String buf;
698 EXPECT_FALSE(json_binary::serialize(thd, &jstr, &buf));
699 Value v = parse_binary(buf.ptr(), buf.length());
700 EXPECT_EQ(Value::STRING, v.type());
701 EXPECT_EQ(size, v.get_data_length());
702 EXPECT_EQ(0, memcmp(str, v.get_data(), size));
703
704 delete[] str;
705 }
706
707 /*
708 Test strings of variable length. Test especially around the boundaries
709 where the representation of the string length changes:
710
711 - Strings of length 0-127 use 1 byte length fields.
712 - Strings of length 128-16383 use 2 byte length fields.
713 - Strings of length 16384-2097151 use 3 byte length fields.
714 - Strings of length 2097152-268435455 use 4 byte length fields.
715 - Strings of length 268435456-... use 5 byte length fields.
716
717 We probably don't have enough memory to test the last category here...
718 */
TEST_F(JsonBinaryTest,StringLengthTest)719 TEST_F(JsonBinaryTest, StringLengthTest) {
720 const THD *thd = this->thd();
721 serialize_deserialize_string(thd, 0);
722 serialize_deserialize_string(thd, 1);
723 serialize_deserialize_string(thd, 127);
724 serialize_deserialize_string(thd, 128);
725 serialize_deserialize_string(thd, 16383);
726 serialize_deserialize_string(thd, 16384);
727 serialize_deserialize_string(thd, 2097151);
728 serialize_deserialize_string(thd, 2097152);
729 serialize_deserialize_string(thd, 3000000);
730 }
731
732 /**
733 Error handler which registers if an error has been raised. If an error is
734 raised, it asserts that the error is ER_INVALID_JSON_BINARY_DATA.
735 */
736 class Invalid_binary_handler : public Internal_error_handler {
737 public:
Invalid_binary_handler(THD * thd)738 Invalid_binary_handler(THD *thd)
739 : m_thd(thd), m_called(false), m_orig_handler(error_handler_hook) {
740 error_handler_hook = my_message_sql;
741 thd->push_internal_handler(this);
742 }
743
~Invalid_binary_handler()744 ~Invalid_binary_handler() override {
745 EXPECT_EQ(this, m_thd->pop_internal_handler());
746 error_handler_hook = m_orig_handler;
747 }
748
handle_condition(THD *,uint err,const char *,Sql_condition::enum_severity_level *,const char *)749 bool handle_condition(THD *, uint err, const char *,
750 Sql_condition::enum_severity_level *,
751 const char *) override {
752 uint expected = ER_INVALID_JSON_BINARY_DATA;
753 EXPECT_EQ(expected, err);
754 m_called = true;
755 return true;
756 }
757
is_called() const758 bool is_called() const { return m_called; }
759
760 private:
761 THD *m_thd;
762 bool m_called;
763 decltype(error_handler_hook) m_orig_handler;
764 };
765
766 /**
767 Run various operations on a corrupted binary value, to see that the
768 json_binary library doesn't fall over when encountering a corrupted value.
769 */
check_corrupted_binary(THD * thd,const char * data,size_t length)770 static void check_corrupted_binary(THD *thd, const char *data, size_t length) {
771 /*
772 A corrupted value may still be valid, so we cannot assert on the return
773 value. Just exercise the code to see that nothing very bad happens.
774 */
775 Value val = parse_binary(data, length);
776 val.is_valid();
777
778 {
779 /*
780 Value::get_free_space() may or may not raise an error. If there is an
781 error, we expect it to be ER_INVALID_JSON_BINARY_DATA.
782 */
783 Invalid_binary_handler handler(thd);
784 size_t space;
785 bool err = val.get_free_space(thd, &space);
786 // If it returns true, an error should have been raised.
787 EXPECT_EQ(err, handler.is_called());
788 }
789
790 /*
791 Call Value::has_space() on every element if it is an array or object.
792 */
793 if (val.type() == Value::ARRAY || val.type() == Value::OBJECT) {
794 for (size_t i = 0; i < val.element_count(); ++i) {
795 size_t offset;
796 val.has_space(i, 100, &offset);
797 }
798 }
799 }
800
801 /**
802 Check that a corrupted binary value doesn't upset the parser in any serious
803 way.
804
805 @param thd THD handle
806 @param dom a JSON DOM from which corrupted binary values are created
807 */
check_corruption(THD * thd,const Json_dom * dom)808 static void check_corruption(THD *thd, const Json_dom *dom) {
809 // First create a valid binary representation of the DOM.
810 String buf;
811 EXPECT_FALSE(json_binary::serialize(thd, dom, &buf));
812 EXPECT_TRUE(json_binary::parse_binary(buf.ptr(), buf.length()).is_valid());
813
814 /*
815 Truncated values should always be detected by is_valid(). Except
816 if it's truncated to an empty string, since parse_binary()
817 interprets the empty string as the JSON null literal.
818 */
819 for (size_t i = 1; i < buf.length() - 1; ++i) {
820 EXPECT_FALSE(json_binary::parse_binary(buf.ptr(), i).is_valid());
821 check_corrupted_binary(thd, buf.ptr(), i);
822 }
823
824 /*
825 Test various 1, 2 and 3 byte data corruptions. is_valid() may return true
826 or false (not all corrupted documents are ill-formed), but we should not
827 have any crashes or valgrind/asan warnings.
828 */
829 for (size_t i = 0; i < buf.length(); ++i) {
830 String copy;
831 copy.append(buf);
832 char *data = copy.c_ptr_safe();
833 for (size_t j = 1; j < 3 && i + j < buf.length(); ++j) {
834 memset(data + i, 0x00, j);
835 check_corrupted_binary(thd, data, copy.length());
836 memset(data + i, 0x80, j);
837 check_corrupted_binary(thd, data, copy.length());
838 memset(data + i, 0xff, j);
839 check_corrupted_binary(thd, data, copy.length());
840 }
841 }
842 }
843
844 /**
845 Test that the parser is well-behaved when a binary value is corrupted.
846 */
TEST_F(JsonBinaryTest,CorruptedBinaryTest)847 TEST_F(JsonBinaryTest, CorruptedBinaryTest) {
848 Json_array a;
849 a.append_alias(new (std::nothrow) Json_null);
850 a.append_alias(new (std::nothrow) Json_boolean(true));
851 a.append_alias(new (std::nothrow) Json_boolean(false));
852 a.append_alias(new (std::nothrow) Json_uint(0));
853 a.append_alias(new (std::nothrow) Json_uint(123));
854 a.append_alias(new (std::nothrow) Json_uint(123000));
855 a.append_alias(new (std::nothrow) Json_uint(123000000));
856 a.append_alias(new (std::nothrow) Json_int(0));
857 a.append_alias(new (std::nothrow) Json_int(123));
858 a.append_alias(new (std::nothrow) Json_int(123000));
859 a.append_alias(new (std::nothrow) Json_int(123000000));
860 a.append_alias(new (std::nothrow) Json_int(-123000000));
861 a.append_alias(new (std::nothrow) Json_string());
862 a.append_alias(new (std::nothrow) Json_string(300, 'a'));
863 a.append_alias(new (std::nothrow) Json_decimal(create_decimal(3.14)));
864 Json_object *o = new (std::nothrow) Json_object;
865 a.append_alias(o);
866 o->add_clone("a1", &a);
867 o->add_alias("s", new (std::nothrow) Json_opaque(MYSQL_TYPE_BLOB, 32, 'x'));
868 o->add_alias("d", new (std::nothrow) Json_double(3.14));
869 a.append_clone(&a);
870 o->add_clone("a2", &a);
871
872 check_corruption(thd(), &a);
873 for (size_t i = 0; i < a.size(); ++i) {
874 SCOPED_TRACE("");
875 check_corruption(thd(), a[i]);
876 }
877 }
878
879 /// How big is the serialized version of a Json_dom?
binary_size(const THD * thd,const Json_dom * dom)880 static size_t binary_size(const THD *thd, const Json_dom *dom) {
881 StringBuffer<256> buf;
882 EXPECT_FALSE(json_binary::serialize(thd, dom, &buf));
883 return buf.length();
884 }
885
886 /// A tuple used by SpaceNeededTest for testing json_binary::space_needed().
887 struct SpaceNeededTuple {
888 /**
889 Constructor for test case with different space requirements in the
890 large and small storage formats.
891 */
SpaceNeededTuplejson_binary_unittest::SpaceNeededTuple892 SpaceNeededTuple(Json_dom *dom, bool result, size_t needed_small,
893 size_t needed_large)
894 : m_value(dom),
895 m_result(result),
896 m_needed_small(needed_small),
897 m_needed_large(needed_large) {}
898 /**
899 Constructor for test case with same space requirement in the large
900 and small storage formats.
901 */
SpaceNeededTuplejson_binary_unittest::SpaceNeededTuple902 SpaceNeededTuple(Json_dom *dom, bool result, size_t needed)
903 : SpaceNeededTuple(dom, result, needed, needed) {}
904 /// The value to pass to space_needed().
905 Json_wrapper m_value;
906 /// The expected return value from the function.
907 bool m_result;
908 /// The expected bytes needed to store the value in the small storage format.
909 size_t m_needed_small;
910 /// The expected bytes needed to store the value in the large storage format.
911 size_t m_needed_large;
912 };
913
914 /// A class used for testing json_binary::space_needed().
915 class SpaceNeededTest : public ::testing::TestWithParam<SpaceNeededTuple> {
916 my_testing::Server_initializer initializer;
917
918 protected:
SetUp()919 void SetUp() override { initializer.SetUp(); }
TearDown()920 void TearDown() override { initializer.TearDown(); }
thd() const921 THD *thd() const { return initializer.thd(); }
922 };
923
924 /*
925 Define our own PrintTo because Google Test's default implementation causes
926 valgrind warnings for reading uninitialized memory. (It reads every byte of
927 the struct, but the struct contains some uninitialized bytes because of
928 alignment.)
929 */
PrintTo(SpaceNeededTuple const & tuple,std::ostream * os)930 void PrintTo(SpaceNeededTuple const &tuple, std::ostream *os) {
931 *os << '{' << static_cast<uint>(tuple.m_value.type()) << ", "
932 << tuple.m_result << ", " << tuple.m_needed_small << ", "
933 << tuple.m_needed_large << '}';
934 }
935
936 /// Test json_binary::space_needed() for a given input.
TEST_P(SpaceNeededTest,SpaceNeeded)937 TEST_P(SpaceNeededTest, SpaceNeeded) {
938 SpaceNeededTuple param = GetParam();
939
940 /*
941 If the large and small storage size differ, it must mean that the
942 value can be inlined in the large storage format.
943 */
944 if (param.m_needed_small != param.m_needed_large) {
945 EXPECT_EQ(0U, param.m_needed_large);
946 }
947
948 size_t needed = 0;
949 if (param.m_result) {
950 for (bool large : {true, false}) {
951 Invalid_binary_handler handler(thd());
952 EXPECT_TRUE(space_needed(thd(), ¶m.m_value, large, &needed));
953 EXPECT_TRUE(handler.is_called());
954 }
955 return;
956 }
957
958 needed = 0;
959 EXPECT_FALSE(space_needed(thd(), ¶m.m_value, false, &needed));
960 EXPECT_EQ(param.m_needed_small, needed);
961
962 needed = 0;
963 EXPECT_FALSE(space_needed(thd(), ¶m.m_value, true, &needed));
964 EXPECT_EQ(param.m_needed_large, needed);
965
966 const auto dom = param.m_value.to_dom(thd());
967
968 if (param.m_needed_small > 0) {
969 /*
970 Not inlined. The size does not include the type byte, so expect
971 one more byte.
972 */
973 EXPECT_EQ(param.m_needed_small + 1, binary_size(thd(), dom));
974 } else {
975 /*
976 Inlined in the small storage format. Find the difference in size
977 between an empty array and one with the value added. Expect the
978 size of a small value entry, which is 3 bytes (1 byte for the
979 type, 2 bytes for the inlined value).
980 */
981 Json_array a;
982 size_t base_size = binary_size(thd(), &a);
983 a.append_clone(dom);
984 size_t full_size = binary_size(thd(), &a);
985 EXPECT_EQ(base_size + 3, full_size);
986 }
987
988 if (param.m_needed_small > 0 && param.m_needed_large == 0) {
989 /*
990 Inlined in the large storage format only. See how much space is
991 added. Expect the size of a large value entry, which is 5 bytes
992 (1 byte for the type, 4 bytes for the inlined value).
993 */
994 Json_array a;
995 a.append_alias(new (std::nothrow) Json_string(64 * 1024, 'a'));
996 size_t base_size = binary_size(thd(), &a);
997 a.append_clone(dom);
998 size_t full_size = binary_size(thd(), &a);
999 EXPECT_EQ(base_size + 5, full_size);
1000 }
1001 }
1002
1003 static const SpaceNeededTuple space_needed_tuples[] = {
1004 /*
1005 Strings need space for the actual data and a variable length field
1006 that holds the length of the string. Each byte in the variable
1007 length field holds seven bits of the length value, so testing
1008 lengths around 2^(7*N) is important.
1009 */
1010 {new (std::nothrow) Json_string(""), false, 1}, // 2^0-1
1011 {new (std::nothrow) Json_string("a"), false, 2}, // 2^0
1012 {new (std::nothrow) Json_string(127, 'a'), false, 128}, // 2^7-1
1013 {new (std::nothrow) Json_string(128, 'a'), false, 130}, // 2^7
1014 {new (std::nothrow) Json_string(16383, 'a'), false, 16385}, // 2^14-1
1015 {new (std::nothrow) Json_string(16384, 'a'), false, 16387}, // 2^14
1016 {new (std::nothrow) Json_string(2097151, 'a'), false, 2097154}, // 2^21-1
1017 {new (std::nothrow) Json_string(2097152, 'a'), false, 2097156}, // 2^21
1018
1019 // Literals are always inlined.
1020 {new (std::nothrow) Json_null, false, 0},
1021 {new (std::nothrow) Json_boolean(false), false, 0},
1022 {new (std::nothrow) Json_boolean(true), false, 0},
1023
1024 // 16-bit integers are always inlined.
1025 {new (std::nothrow) Json_int(0), false, 0},
1026 {new (std::nothrow) Json_int(-1), false, 0},
1027 {new (std::nothrow) Json_int(1), false, 0},
1028 {new (std::nothrow) Json_int(INT_MIN16), false, 0},
1029 {new (std::nothrow) Json_int(INT_MAX16), false, 0},
1030 {new (std::nothrow) Json_uint(0), false, 0},
1031 {new (std::nothrow) Json_uint(1), false, 0},
1032 {new (std::nothrow) Json_uint(UINT_MAX16), false, 0},
1033
1034 // 32-bit integers are inlined only in the large storage format.
1035 {new (std::nothrow) Json_int(INT_MIN32), false, 4, 0},
1036 {new (std::nothrow) Json_int(INT_MIN16 - 1), false, 4, 0},
1037 {new (std::nothrow) Json_int(INT_MAX16 + 1), false, 4, 0},
1038 {new (std::nothrow) Json_int(INT_MAX32), false, 4, 0},
1039 {new (std::nothrow) Json_uint(UINT_MAX16 + 1), false, 4, 0},
1040 {new (std::nothrow) Json_uint(UINT_MAX32), false, 4, 0},
1041
1042 // Larger integers and doubles require 8 bytes.
1043 {new (std::nothrow) Json_int(INT_MIN64), false, 8},
1044 {new (std::nothrow) Json_int(static_cast<longlong>(INT_MIN32) - 1), false,
1045 8},
1046 {new (std::nothrow) Json_int(static_cast<longlong>(INT_MAX32) + 1), false,
1047 8},
1048 {new (std::nothrow) Json_int(INT_MAX64), false, 8},
1049 {new (std::nothrow) Json_uint(static_cast<ulonglong>(UINT_MAX32) + 1),
1050 false, 8},
1051 {new (std::nothrow) Json_uint(0xFFFFFFFFFFFFFFFFULL), false, 8},
1052 {new (std::nothrow) Json_double(0), false, 8},
1053 {new (std::nothrow) Json_double(3.14), false, 8},
1054
1055 /*
1056 Opaque values need space for type info (one byte), a variable
1057 length field, and the actual data.
1058 */
1059 {new (std::nothrow) Json_opaque(MYSQL_TYPE_BLOB, ""), false, 2},
1060 {new (std::nothrow) Json_opaque(MYSQL_TYPE_BLOB, "a"), false, 3},
1061 {new (std::nothrow) Json_opaque(MYSQL_TYPE_BLOB, 127, 'a'), false, 129},
1062 {new (std::nothrow) Json_opaque(MYSQL_TYPE_BLOB, 128, 'a'), false, 131},
1063 {new (std::nothrow) Json_datetime(create_time(), MYSQL_TYPE_TIME), false,
1064 Json_datetime::PACKED_SIZE + 2},
1065 {new (std::nothrow) Json_datetime(create_date(), MYSQL_TYPE_DATE), false,
1066 Json_datetime::PACKED_SIZE + 2},
1067 {new (std::nothrow) Json_datetime(create_datetime(), MYSQL_TYPE_DATETIME),
1068 false, Json_datetime::PACKED_SIZE + 2},
1069 {new (std::nothrow) Json_datetime(create_datetime(), MYSQL_TYPE_TIMESTAMP),
1070 false, Json_datetime::PACKED_SIZE + 2},
1071 {new (std::nothrow) Json_decimal(create_decimal(12.3)), false, 6},
1072
1073 // Arrays.
1074 {new (std::nothrow) Json_array, false, 4},
1075 {parse_json("[1.5]").release(), false, 15},
1076
1077 // Objects
1078 {new (std::nothrow) Json_object, false, 4},
1079 {parse_json("{\"a\":1.5}").release(), false, 20},
1080
1081 // Handle type == ERROR.
1082 {nullptr, true, 0},
1083 };
1084
1085 INSTANTIATE_TEST_SUITE_P(JsonBinary, SpaceNeededTest,
1086 ::testing::ValuesIn(space_needed_tuples));
1087
1088 /**
1089 Helper function for testing Value::has_space(). Serializes a JSON
1090 array or JSON object and checks if has_space() reports the correct
1091 size and offset for an element in the array or object.
1092 */
test_has_space(THD * thd,const Json_dom * container,Value::enum_type type,size_t size,size_t element,size_t expected_offset)1093 static void test_has_space(THD *thd, const Json_dom *container,
1094 Value::enum_type type, size_t size, size_t element,
1095 size_t expected_offset) {
1096 StringBuffer<100> buf;
1097 EXPECT_FALSE(json_binary::serialize(thd, container, &buf));
1098 Value v1 = parse_binary(buf.ptr(), buf.length());
1099 Value v2 = v1.element(element);
1100 EXPECT_EQ(type, v2.type());
1101 size_t offset = 0;
1102 if (size > 0) {
1103 EXPECT_TRUE(v1.has_space(element, size - 1, &offset));
1104 EXPECT_EQ(expected_offset, offset);
1105 }
1106 offset = 0;
1107 EXPECT_TRUE(v1.has_space(element, size, &offset));
1108 EXPECT_EQ(expected_offset, offset);
1109 offset = 0;
1110 EXPECT_FALSE(v1.has_space(element, size + 1, &offset));
1111 EXPECT_EQ(0U, offset);
1112 offset = 0;
1113 EXPECT_TRUE(v1.has_space(element, 0, &offset));
1114 EXPECT_EQ(expected_offset, offset);
1115 }
1116
1117 /**
1118 Test Value::has_size() by inserting a value into an array or an
1119 object and checking that has_size() returns the correct size and
1120 offset.
1121 */
test_has_space(THD * thd,const Json_dom * dom,Value::enum_type type,size_t size)1122 static void test_has_space(THD *thd, const Json_dom *dom, Value::enum_type type,
1123 size_t size) {
1124 {
1125 SCOPED_TRACE("array");
1126 Json_array a;
1127 a.append_clone(dom);
1128
1129 /*
1130 The array contains the element count (2 bytes), byte size (2
1131 bytes) and a value entry (3 bytes) before the value.
1132 */
1133 size_t expected_offset = 2 + 2 + 3;
1134 {
1135 SCOPED_TRACE("first element");
1136 test_has_space(thd, &a, type, size, 0, expected_offset);
1137 }
1138
1139 /*
1140 Insert a literal at the beginning of the array. The offset
1141 should increase by 3 (size of the value entry).
1142 */
1143 expected_offset += 3;
1144 {
1145 SCOPED_TRACE("second element");
1146 a.insert_alias(0, create_dom_ptr<Json_null>());
1147 test_has_space(thd, &a, type, size, 1, expected_offset);
1148 }
1149
1150 /*
1151 Insert a double at the beginning of the array. Expect the offset
1152 to increase by 3 (size of the value entry) + 8 (size of the
1153 double).
1154 */
1155 expected_offset += 3 + 8;
1156 {
1157 SCOPED_TRACE("third element");
1158 a.insert_alias(0, create_dom_ptr<Json_double>(123.0));
1159 test_has_space(thd, &a, type, size, 2, expected_offset);
1160 }
1161
1162 /*
1163 Insert some values at the end of the array. The offset should
1164 increase by 3 (one value entry) per added value.
1165 */
1166 expected_offset += 3;
1167 {
1168 SCOPED_TRACE("append literal");
1169 a.append_alias(new (std::nothrow) Json_boolean(true));
1170 test_has_space(thd, &a, type, size, 2, expected_offset);
1171 }
1172 expected_offset += 3;
1173 {
1174 SCOPED_TRACE("append double");
1175 a.append_alias(new (std::nothrow) Json_double(1.23));
1176 test_has_space(thd, &a, type, size, 2, expected_offset);
1177 }
1178 }
1179
1180 /*
1181 Now test the same with an object.
1182 */
1183 {
1184 SCOPED_TRACE("object");
1185 Json_object o;
1186 o.add_clone("k", dom);
1187
1188 /*
1189 The object contains the element count (2 bytes), byte size (2
1190 bytes), a key entry (4 bytes), a value entry (3 bytes) and a key
1191 (1 byte) before the value.
1192 */
1193 size_t expected_offset = 2 + 2 + 4 + 3 + 1;
1194 {
1195 SCOPED_TRACE("first element");
1196 test_has_space(thd, &o, type, size, 0, expected_offset);
1197 }
1198
1199 /*
1200 Add a literal at the beginning of the object. The offset should
1201 increase by 4 (size of the key entry) + 3 (size of the value
1202 entry) + 1 (size of the key).
1203 */
1204 expected_offset += 4 + 3 + 1;
1205 {
1206 SCOPED_TRACE("second element");
1207 o.add_alias("b", new (std::nothrow) Json_null);
1208 test_has_space(thd, &o, type, size, 1, expected_offset);
1209 }
1210
1211 /*
1212 Add a double at the beginning of the object. Expect the offset
1213 to increase by 4 (size of the key entry) + 3 (size of the value
1214 entry) + 1 (size of the key) + 8 (size of the double).
1215 */
1216 expected_offset += 4 + 3 + 1 + 8;
1217 {
1218 SCOPED_TRACE("third element");
1219 o.add_alias("a", new (std::nothrow) Json_double(123.0));
1220 test_has_space(thd, &o, type, size, 2, expected_offset);
1221 }
1222
1223 /*
1224 Add some values at the end of the array. The offset should
1225 increase by 4 (one key entry) + 3 (one value entry) + 1 (one
1226 key) per added member.
1227 */
1228 expected_offset += 4 + 3 + 1;
1229 {
1230 SCOPED_TRACE("add literal");
1231 o.add_alias("x", new (std::nothrow) Json_boolean(true));
1232 test_has_space(thd, &o, type, size, 2, expected_offset);
1233 }
1234 expected_offset += 4 + 3 + 1;
1235 {
1236 SCOPED_TRACE("add double");
1237 o.add_alias("y", new (std::nothrow) Json_double(1.23));
1238 test_has_space(thd, &o, type, size, 2, expected_offset);
1239 }
1240 }
1241 }
1242
1243 /**
1244 Various tests for Value::has_space().
1245 */
TEST_F(JsonBinaryTest,HasSpace)1246 TEST_F(JsonBinaryTest, HasSpace) {
1247 {
1248 SCOPED_TRACE("empty string");
1249 Json_string jstr;
1250 test_has_space(thd(), &jstr, Value::STRING, 1);
1251 }
1252 {
1253 // Test longest possible string with 1-byte length field.
1254 SCOPED_TRACE("string(127)");
1255 Json_string jstr(127, 'a');
1256 test_has_space(thd(), &jstr, Value::STRING, 128);
1257 }
1258 {
1259 // Test shortest possible string with 2-byte length field.
1260 SCOPED_TRACE("string(128)");
1261 Json_string jstr(128, 'a');
1262 test_has_space(thd(), &jstr, Value::STRING, 130);
1263 }
1264 {
1265 SCOPED_TRACE("null literal");
1266 Json_null jnull;
1267 test_has_space(thd(), &jnull, Value::LITERAL_NULL, 0);
1268 }
1269 {
1270 SCOPED_TRACE("true literal");
1271 Json_boolean jtrue(true);
1272 test_has_space(thd(), &jtrue, Value::LITERAL_TRUE, 0);
1273 }
1274 {
1275 SCOPED_TRACE("false literal");
1276 Json_boolean jfalse(false);
1277 test_has_space(thd(), &jfalse, Value::LITERAL_FALSE, 0);
1278 }
1279 {
1280 SCOPED_TRACE("inlined uint");
1281 Json_uint u(123);
1282 EXPECT_TRUE(u.is_16bit());
1283 test_has_space(thd(), &u, Value::UINT, 0);
1284 }
1285 {
1286 SCOPED_TRACE("32-bit uint");
1287 Json_uint u(100000);
1288 EXPECT_FALSE(u.is_16bit());
1289 EXPECT_TRUE(u.is_32bit());
1290 test_has_space(thd(), &u, Value::UINT, 4);
1291 }
1292 {
1293 SCOPED_TRACE("64-bit uint");
1294 Json_uint u(5000000000ULL);
1295 EXPECT_FALSE(u.is_32bit());
1296 test_has_space(thd(), &u, Value::UINT, 8);
1297 }
1298 {
1299 SCOPED_TRACE("inlined int");
1300 Json_int i(123);
1301 EXPECT_TRUE(i.is_16bit());
1302 test_has_space(thd(), &i, Value::INT, 0);
1303 }
1304 {
1305 SCOPED_TRACE("32-bit int");
1306 Json_int i(100000);
1307 EXPECT_FALSE(i.is_16bit());
1308 EXPECT_TRUE(i.is_32bit());
1309 test_has_space(thd(), &i, Value::INT, 4);
1310 }
1311 {
1312 SCOPED_TRACE("64-bit uint");
1313 Json_int i(5000000000LL);
1314 EXPECT_FALSE(i.is_32bit());
1315 test_has_space(thd(), &i, Value::INT, 8);
1316 }
1317 {
1318 SCOPED_TRACE("double");
1319 Json_double d(3.14);
1320 test_has_space(thd(), &d, Value::DOUBLE, 8);
1321 }
1322 {
1323 SCOPED_TRACE("opaque");
1324 Json_opaque o(MYSQL_TYPE_BLOB, "abc", 3);
1325 // 1 byte for type, 1 byte for length, 3 bytes of blob data
1326 test_has_space(thd(), &o, Value::OPAQUE, 5);
1327 }
1328 {
1329 SCOPED_TRACE("empty array");
1330 Json_array a;
1331 /*
1332 An empty array has two bytes for element count and two bytes for
1333 total size in bytes.
1334 */
1335 test_has_space(thd(), &a, Value::ARRAY, 4);
1336 }
1337 {
1338 SCOPED_TRACE("non-empty array");
1339 auto a = parse_json("[null]");
1340 // Here we have an additional 3 bytes for the value entry.
1341 test_has_space(thd(), a.get(), Value::ARRAY, 4 + 3);
1342 }
1343 {
1344 SCOPED_TRACE("empty object");
1345 Json_object o;
1346 /*
1347 An empty object has two bytes for element count and two bytes for
1348 total size in bytes.
1349 */
1350 test_has_space(thd(), &o, Value::OBJECT, 4);
1351 }
1352 {
1353 SCOPED_TRACE("non-empty object");
1354 Json_object o;
1355 o.add_alias("a", new (std::nothrow) Json_null);
1356 /*
1357 Here we have an additional 4 bytes for the key entry, 3 bytes
1358 for the value entry, and 1 byte for the key.
1359 */
1360 test_has_space(thd(), &o, Value::OBJECT, 4 + 4 + 3 + 1);
1361 }
1362 }
1363
1364 /**
1365 Helper function for microbenchmarks that test the performance of
1366 json_binary::serialize().
1367
1368 @param dom the Json_dom to serialize
1369 @param num_iterations the number of iterations in the test
1370 */
serialize_benchmark(const Json_dom * dom,size_t num_iterations)1371 static void serialize_benchmark(const Json_dom *dom, size_t num_iterations) {
1372 my_testing::Server_initializer initializer;
1373 initializer.SetUp();
1374 const THD *thd = initializer.thd();
1375
1376 StartBenchmarkTiming();
1377
1378 for (size_t i = 0; i < num_iterations; ++i) {
1379 String buf;
1380 EXPECT_FALSE(json_binary::serialize(thd, dom, &buf));
1381 }
1382
1383 StopBenchmarkTiming();
1384
1385 initializer.TearDown();
1386 }
1387
1388 /**
1389 Microbenchmark which tests the performance of serializing a JSON
1390 array with 10000 integers.
1391 */
BM_JsonBinarySerializeIntArray(size_t num_iterations)1392 static void BM_JsonBinarySerializeIntArray(size_t num_iterations) {
1393 StopBenchmarkTiming();
1394
1395 Json_array array;
1396 for (int i = 0; i < 10000; ++i)
1397 array.append_alias(create_dom_ptr<Json_int>(i * 1000));
1398
1399 serialize_benchmark(&array, num_iterations);
1400 }
BENCHMARK(BM_JsonBinarySerializeIntArray)1401 BENCHMARK(BM_JsonBinarySerializeIntArray)
1402
1403 /**
1404 Microbenchmark which tests the performance of serializing a JSON
1405 array with 10000 double values.
1406 */
1407 static void BM_JsonBinarySerializeDoubleArray(size_t num_iterations) {
1408 StopBenchmarkTiming();
1409
1410 Json_array array;
1411 for (int i = 0; i < 10000; ++i)
1412 array.append_alias(create_dom_ptr<Json_double>(i * 1000));
1413
1414 serialize_benchmark(&array, num_iterations);
1415 }
BENCHMARK(BM_JsonBinarySerializeDoubleArray)1416 BENCHMARK(BM_JsonBinarySerializeDoubleArray)
1417
1418 /**
1419 Microbenchmark which tests the performance of serializing a JSON
1420 array with 10000 strings.
1421 */
1422 static void BM_JsonBinarySerializeStringArray(size_t num_iterations) {
1423 StopBenchmarkTiming();
1424
1425 Json_array array;
1426 for (int i = 0; i < 10000; ++i)
1427 array.append_alias(create_dom_ptr<Json_string>(std::to_string(i)));
1428
1429 serialize_benchmark(&array, num_iterations);
1430 }
1431 BENCHMARK(BM_JsonBinarySerializeStringArray)
1432
1433 } // namespace json_binary_unittest
1434