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(), &param.m_value, large, &needed));
953       EXPECT_TRUE(handler.is_called());
954     }
955     return;
956   }
957 
958   needed = 0;
959   EXPECT_FALSE(space_needed(thd(), &param.m_value, false, &needed));
960   EXPECT_EQ(param.m_needed_small, needed);
961 
962   needed = 0;
963   EXPECT_FALSE(space_needed(thd(), &param.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