• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     __ _____ _____ _____
3  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
4 |  |  |__   |  |  | | | |  version 3.9.1
5 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10 
11 Permission is hereby  granted, free of charge, to any  person obtaining a copy
12 of this software and associated  documentation files (the "Software"), to deal
13 in the Software  without restriction, including without  limitation the rights
14 to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
15 copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
16 furnished to do so, subject to the following conditions:
17 
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20 
21 THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
22 IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
23 FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
24 AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
25 LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29 
30 #include "doctest_compatibility.h"
31 
32 #include <nlohmann/json.hpp>
33 using nlohmann::json;
34 
35 #include <fstream>
36 #include <sstream>
37 #include <test_data.hpp>
38 #include "test_utils.hpp"
39 
40 TEST_CASE("BSON")
41 {
42     SECTION("individual values not supported")
43     {
44         SECTION("null")
45         {
46             json j = nullptr;
47             CHECK_THROWS_AS(json::to_bson(j), json::type_error&);
48             CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] to serialize to BSON, top-level type must be object, but is null");
49         }
50 
51         SECTION("boolean")
52         {
53             SECTION("true")
54             {
55                 json j = true;
56                 CHECK_THROWS_AS(json::to_bson(j), json::type_error&);
57                 CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] to serialize to BSON, top-level type must be object, but is boolean");
58             }
59 
60             SECTION("false")
61             {
62                 json j = false;
63                 CHECK_THROWS_AS(json::to_bson(j), json::type_error&);
64                 CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] to serialize to BSON, top-level type must be object, but is boolean");
65             }
66         }
67 
68         SECTION("number")
69         {
70             json j = 42;
71             CHECK_THROWS_AS(json::to_bson(j), json::type_error&);
72             CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] to serialize to BSON, top-level type must be object, but is number");
73         }
74 
75         SECTION("float")
76         {
77             json j = 4.2;
78             CHECK_THROWS_AS(json::to_bson(j), json::type_error&);
79             CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] to serialize to BSON, top-level type must be object, but is number");
80         }
81 
82         SECTION("string")
83         {
84             json j = "not supported";
85             CHECK_THROWS_AS(json::to_bson(j), json::type_error&);
86             CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] to serialize to BSON, top-level type must be object, but is string");
87         }
88 
89         SECTION("array")
90         {
91             json j = std::vector<int> {1, 2, 3, 4, 5, 6, 7};
92             CHECK_THROWS_AS(json::to_bson(j), json::type_error&);
93             CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.type_error.317] to serialize to BSON, top-level type must be object, but is array");
94         }
95     }
96 
97     SECTION("keys containing code-point U+0000 cannot be serialized to BSON")
98     {
99         json j =
100         {
101             { std::string("en\0try", 6), true }
102         };
103         CHECK_THROWS_AS(json::to_bson(j), json::out_of_range&);
104         CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.out_of_range.409] BSON key cannot contain code point U+0000 (at byte 2)");
105     }
106 
107     SECTION("string length must be at least 1")
108     {
109         // from https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11175
110         std::vector<std::uint8_t> v =
111         {
112             0x20, 0x20, 0x20, 0x20,
113             0x02,
114             0x00,
115             0x00, 0x00, 0x00, 0x80
116         };
117         json _;
118         CHECK_THROWS_AS(_ = json::from_bson(v), json::parse_error&);
119         CHECK_THROWS_WITH(_ = json::from_bson(v), "[json.exception.parse_error.112] parse error at byte 10: syntax error while parsing BSON string: string length must be at least 1, is -2147483648");
120     }
121 
122     SECTION("objects")
123     {
124         SECTION("empty object")
125         {
126             json j = json::object();
127             std::vector<std::uint8_t> expected =
128             {
129                 0x05, 0x00, 0x00, 0x00, // size (little endian)
130                 // no entries
131                 0x00 // end marker
132             };
133 
134             const auto result = json::to_bson(j);
135             CHECK(result == expected);
136 
137             // roundtrip
138             CHECK(json::from_bson(result) == j);
139             CHECK(json::from_bson(result, true, false) == j);
140         }
141 
142         SECTION("non-empty object with bool")
143         {
144             json j =
145             {
146                 { "entry", true }
147             };
148 
149             std::vector<std::uint8_t> expected =
150             {
151                 0x0D, 0x00, 0x00, 0x00, // size (little endian)
152                 0x08,               // entry: boolean
153                 'e', 'n', 't', 'r', 'y', '\x00',
154                 0x01,           // value = true
155                 0x00                    // end marker
156             };
157 
158             const auto result = json::to_bson(j);
159             CHECK(result == expected);
160 
161             // roundtrip
162             CHECK(json::from_bson(result) == j);
163             CHECK(json::from_bson(result, true, false) == j);
164         }
165 
166         SECTION("non-empty object with bool")
167         {
168             json j =
169             {
170                 { "entry", false }
171             };
172 
173             std::vector<std::uint8_t> expected =
174             {
175                 0x0D, 0x00, 0x00, 0x00, // size (little endian)
176                 0x08,               // entry: boolean
177                 'e', 'n', 't', 'r', 'y', '\x00',
178                 0x00,           // value = false
179                 0x00                    // end marker
180             };
181 
182             const auto result = json::to_bson(j);
183             CHECK(result == expected);
184 
185             // roundtrip
186             CHECK(json::from_bson(result) == j);
187             CHECK(json::from_bson(result, true, false) == j);
188         }
189 
190         SECTION("non-empty object with double")
191         {
192             json j =
193             {
194                 { "entry", 4.2 }
195             };
196 
197             std::vector<std::uint8_t> expected =
198             {
199                 0x14, 0x00, 0x00, 0x00, // size (little endian)
200                 0x01, /// entry: double
201                 'e', 'n', 't', 'r', 'y', '\x00',
202                 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x10, 0x40,
203                 0x00 // end marker
204             };
205 
206             const auto result = json::to_bson(j);
207             CHECK(result == expected);
208 
209             // roundtrip
210             CHECK(json::from_bson(result) == j);
211             CHECK(json::from_bson(result, true, false) == j);
212         }
213 
214         SECTION("non-empty object with string")
215         {
216             json j =
217             {
218                 { "entry", "bsonstr" }
219             };
220 
221             std::vector<std::uint8_t> expected =
222             {
223                 0x18, 0x00, 0x00, 0x00, // size (little endian)
224                 0x02, /// entry: string (UTF-8)
225                 'e', 'n', 't', 'r', 'y', '\x00',
226                 0x08, 0x00, 0x00, 0x00, 'b', 's', 'o', 'n', 's', 't', 'r', '\x00',
227                 0x00 // end marker
228             };
229 
230             const auto result = json::to_bson(j);
231             CHECK(result == expected);
232 
233             // roundtrip
234             CHECK(json::from_bson(result) == j);
235             CHECK(json::from_bson(result, true, false) == j);
236         }
237 
238         SECTION("non-empty object with null member")
239         {
240             json j =
241             {
242                 { "entry", nullptr }
243             };
244 
245             std::vector<std::uint8_t> expected =
246             {
247                 0x0C, 0x00, 0x00, 0x00, // size (little endian)
248                 0x0A, /// entry: null
249                 'e', 'n', 't', 'r', 'y', '\x00',
250                 0x00 // end marker
251             };
252 
253             const auto result = json::to_bson(j);
254             CHECK(result == expected);
255 
256             // roundtrip
257             CHECK(json::from_bson(result) == j);
258             CHECK(json::from_bson(result, true, false) == j);
259         }
260 
261         SECTION("non-empty object with integer (32-bit) member")
262         {
263             json j =
264             {
265                 { "entry", std::int32_t{0x12345678} }
266             };
267 
268             std::vector<std::uint8_t> expected =
269             {
270                 0x10, 0x00, 0x00, 0x00, // size (little endian)
271                 0x10, /// entry: int32
272                 'e', 'n', 't', 'r', 'y', '\x00',
273                 0x78, 0x56, 0x34, 0x12,
274                 0x00 // end marker
275             };
276 
277             const auto result = json::to_bson(j);
278             CHECK(result == expected);
279 
280             // roundtrip
281             CHECK(json::from_bson(result) == j);
282             CHECK(json::from_bson(result, true, false) == j);
283         }
284 
285         SECTION("non-empty object with integer (64-bit) member")
286         {
287             json j =
288             {
289                 { "entry", std::int64_t{0x1234567804030201} }
290             };
291 
292             std::vector<std::uint8_t> expected =
293             {
294                 0x14, 0x00, 0x00, 0x00, // size (little endian)
295                 0x12, /// entry: int64
296                 'e', 'n', 't', 'r', 'y', '\x00',
297                 0x01, 0x02, 0x03, 0x04, 0x78, 0x56, 0x34, 0x12,
298                 0x00 // end marker
299             };
300 
301             const auto result = json::to_bson(j);
302             CHECK(result == expected);
303 
304             // roundtrip
305             CHECK(json::from_bson(result) == j);
306             CHECK(json::from_bson(result, true, false) == j);
307         }
308 
309         SECTION("non-empty object with negative integer (32-bit) member")
310         {
311             json j =
312             {
313                 { "entry", std::int32_t{-1} }
314             };
315 
316             std::vector<std::uint8_t> expected =
317             {
318                 0x10, 0x00, 0x00, 0x00, // size (little endian)
319                 0x10, /// entry: int32
320                 'e', 'n', 't', 'r', 'y', '\x00',
321                 0xFF, 0xFF, 0xFF, 0xFF,
322                 0x00 // end marker
323             };
324 
325             const auto result = json::to_bson(j);
326             CHECK(result == expected);
327 
328             // roundtrip
329             CHECK(json::from_bson(result) == j);
330             CHECK(json::from_bson(result, true, false) == j);
331         }
332 
333         SECTION("non-empty object with negative integer (64-bit) member")
334         {
335             json j =
336             {
337                 { "entry", std::int64_t{-1} }
338             };
339 
340             std::vector<std::uint8_t> expected =
341             {
342                 0x10, 0x00, 0x00, 0x00, // size (little endian)
343                 0x10, /// entry: int32
344                 'e', 'n', 't', 'r', 'y', '\x00',
345                 0xFF, 0xFF, 0xFF, 0xFF,
346                 0x00 // end marker
347             };
348 
349             const auto result = json::to_bson(j);
350             CHECK(result == expected);
351 
352             // roundtrip
353             CHECK(json::from_bson(result) == j);
354             CHECK(json::from_bson(result, true, false) == j);
355         }
356 
357         SECTION("non-empty object with unsigned integer (64-bit) member")
358         {
359             // directly encoding uint64 is not supported in bson (only for timestamp values)
360             json j =
361             {
362                 { "entry", std::uint64_t{0x1234567804030201} }
363             };
364 
365             std::vector<std::uint8_t> expected =
366             {
367                 0x14, 0x00, 0x00, 0x00, // size (little endian)
368                 0x12, /// entry: int64
369                 'e', 'n', 't', 'r', 'y', '\x00',
370                 0x01, 0x02, 0x03, 0x04, 0x78, 0x56, 0x34, 0x12,
371                 0x00 // end marker
372             };
373 
374             const auto result = json::to_bson(j);
375             CHECK(result == expected);
376 
377             // roundtrip
378             CHECK(json::from_bson(result) == j);
379             CHECK(json::from_bson(result, true, false) == j);
380         }
381 
382         SECTION("non-empty object with small unsigned integer member")
383         {
384             json j =
385             {
386                 { "entry", std::uint64_t{0x42} }
387             };
388 
389             std::vector<std::uint8_t> expected =
390             {
391                 0x10, 0x00, 0x00, 0x00, // size (little endian)
392                 0x10, /// entry: int32
393                 'e', 'n', 't', 'r', 'y', '\x00',
394                 0x42, 0x00, 0x00, 0x00,
395                 0x00 // end marker
396             };
397 
398             const auto result = json::to_bson(j);
399             CHECK(result == expected);
400 
401             // roundtrip
402             CHECK(json::from_bson(result) == j);
403             CHECK(json::from_bson(result, true, false) == j);
404         }
405 
406         SECTION("non-empty object with object member")
407         {
408             json j =
409             {
410                 { "entry", json::object() }
411             };
412 
413             std::vector<std::uint8_t> expected =
414             {
415                 0x11, 0x00, 0x00, 0x00, // size (little endian)
416                 0x03, /// entry: embedded document
417                 'e', 'n', 't', 'r', 'y', '\x00',
418 
419                 0x05, 0x00, 0x00, 0x00, // size (little endian)
420                 // no entries
421                 0x00, // end marker (embedded document)
422 
423                 0x00 // end marker
424             };
425 
426             const auto result = json::to_bson(j);
427             CHECK(result == expected);
428 
429             // roundtrip
430             CHECK(json::from_bson(result) == j);
431             CHECK(json::from_bson(result, true, false) == j);
432         }
433 
434         SECTION("non-empty object with array member")
435         {
436             json j =
437             {
438                 { "entry", json::array() }
439             };
440 
441             std::vector<std::uint8_t> expected =
442             {
443                 0x11, 0x00, 0x00, 0x00, // size (little endian)
444                 0x04, /// entry: embedded document
445                 'e', 'n', 't', 'r', 'y', '\x00',
446 
447                 0x05, 0x00, 0x00, 0x00, // size (little endian)
448                 // no entries
449                 0x00, // end marker (embedded document)
450 
451                 0x00 // end marker
452             };
453 
454             const auto result = json::to_bson(j);
455             CHECK(result == expected);
456 
457             // roundtrip
458             CHECK(json::from_bson(result) == j);
459             CHECK(json::from_bson(result, true, false) == j);
460         }
461 
462         SECTION("non-empty object with non-empty array member")
463         {
464             json j =
465             {
466                 { "entry", json::array({1, 2, 3, 4, 5, 6, 7, 8}) }
467             };
468 
469             std::vector<std::uint8_t> expected =
470             {
471                 0x49, 0x00, 0x00, 0x00, // size (little endian)
472                 0x04, /// entry: embedded document
473                 'e', 'n', 't', 'r', 'y', '\x00',
474 
475                 0x3D, 0x00, 0x00, 0x00, // size (little endian)
476                 0x10, '0', 0x00, 0x01, 0x00, 0x00, 0x00,
477                 0x10, '1', 0x00, 0x02, 0x00, 0x00, 0x00,
478                 0x10, '2', 0x00, 0x03, 0x00, 0x00, 0x00,
479                 0x10, '3', 0x00, 0x04, 0x00, 0x00, 0x00,
480                 0x10, '4', 0x00, 0x05, 0x00, 0x00, 0x00,
481                 0x10, '5', 0x00, 0x06, 0x00, 0x00, 0x00,
482                 0x10, '6', 0x00, 0x07, 0x00, 0x00, 0x00,
483                 0x10, '7', 0x00, 0x08, 0x00, 0x00, 0x00,
484                 0x00, // end marker (embedded document)
485 
486                 0x00 // end marker
487             };
488 
489             const auto result = json::to_bson(j);
490             CHECK(result == expected);
491 
492             // roundtrip
493             CHECK(json::from_bson(result) == j);
494             CHECK(json::from_bson(result, true, false) == j);
495         }
496 
497         SECTION("non-empty object with binary member")
498         {
499             const size_t N = 10;
500             const auto s = std::vector<std::uint8_t>(N, 'x');
501             json j =
502             {
503                 { "entry", json::binary(s, 0) }
504             };
505 
506             std::vector<std::uint8_t> expected =
507             {
508                 0x1B, 0x00, 0x00, 0x00, // size (little endian)
509                 0x05, // entry: binary
510                 'e', 'n', 't', 'r', 'y', '\x00',
511 
512                 0x0A, 0x00, 0x00, 0x00, // size of binary (little endian)
513                 0x00, // Generic binary subtype
514                 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
515 
516                 0x00 // end marker
517             };
518 
519             const auto result = json::to_bson(j);
520             CHECK(result == expected);
521 
522             // roundtrip
523             CHECK(json::from_bson(result) == j);
524             CHECK(json::from_bson(result, true, false) == j);
525         }
526 
527         SECTION("non-empty object with binary member with subtype")
528         {
529             // an MD5 hash
530             const std::vector<std::uint8_t> md5hash = {0xd7, 0x7e, 0x27, 0x54, 0xbe, 0x12, 0x37, 0xfe, 0xd6, 0x0c, 0x33, 0x98, 0x30, 0x3b, 0x8d, 0xc4};
531             json j =
532             {
533                 { "entry", json::binary(md5hash, 5) }
534             };
535 
536             std::vector<std::uint8_t> expected =
537             {
538                 0x21, 0x00, 0x00, 0x00, // size (little endian)
539                 0x05, // entry: binary
540                 'e', 'n', 't', 'r', 'y', '\x00',
541 
542                 0x10, 0x00, 0x00, 0x00, // size of binary (little endian)
543                 0x05, // MD5 binary subtype
544                 0xd7, 0x7e, 0x27, 0x54, 0xbe, 0x12, 0x37, 0xfe, 0xd6, 0x0c, 0x33, 0x98, 0x30, 0x3b, 0x8d, 0xc4,
545 
546                 0x00 // end marker
547             };
548 
549             const auto result = json::to_bson(j);
550             CHECK(result == expected);
551 
552             // roundtrip
553             CHECK(json::from_bson(result) == j);
554             CHECK(json::from_bson(result, true, false) == j);
555         }
556 
557         SECTION("Some more complex document")
558         {
559             // directly encoding uint64 is not supported in bson (only for timestamp values)
560             json j =
561             {
562                 {"double", 42.5},
563                 {"entry", 4.2},
564                 {"number", 12345},
565                 {"object", {{ "string", "value" }}}
566             };
567 
568             std::vector<std::uint8_t> expected =
569             {
570                 /*size */ 0x4f, 0x00, 0x00, 0x00,
571                 /*entry*/ 0x01, 'd',  'o',  'u',  'b',  'l',  'e',  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x45, 0x40,
572                 /*entry*/ 0x01, 'e',  'n',  't',  'r',  'y',  0x00, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x10, 0x40,
573                 /*entry*/ 0x10, 'n',  'u',  'm',  'b',  'e',  'r',  0x00, 0x39, 0x30, 0x00, 0x00,
574                 /*entry*/ 0x03, 'o',  'b',  'j',  'e',  'c',  't',  0x00,
575                 /*entry: obj-size */ 0x17, 0x00, 0x00, 0x00,
576                 /*entry: obj-entry*/0x02, 's',  't',  'r',  'i',  'n',  'g', 0x00, 0x06, 0x00, 0x00, 0x00, 'v', 'a', 'l', 'u', 'e', 0,
577                 /*entry: obj-term.*/0x00,
578                 /*obj-term*/ 0x00
579             };
580 
581             const auto result = json::to_bson(j);
582             CHECK(result == expected);
583 
584             // roundtrip
585             CHECK(json::from_bson(result) == j);
586             CHECK(json::from_bson(result, true, false) == j);
587         }
588     }
589 
590     SECTION("Examples from http://bsonspec.org/faq.html")
591     {
592         SECTION("Example 1")
593         {
594             std::vector<std::uint8_t> input = {0x16, 0x00, 0x00, 0x00, 0x02, 'h', 'e', 'l', 'l', 'o', 0x00, 0x06, 0x00, 0x00, 0x00, 'w', 'o', 'r', 'l', 'd', 0x00, 0x00};
595             json parsed = json::from_bson(input);
596             json expected = {{"hello", "world"}};
597             CHECK(parsed == expected);
598             auto dumped = json::to_bson(parsed);
599             CHECK(dumped == input);
600             CHECK(json::from_bson(dumped) == expected);
601         }
602 
603         SECTION("Example 2")
604         {
605             std::vector<std::uint8_t> input = {0x31, 0x00, 0x00, 0x00, 0x04, 'B', 'S', 'O', 'N', 0x00, 0x26, 0x00, 0x00, 0x00, 0x02, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 'a', 'w', 'e', 's', 'o', 'm', 'e', 0x00, 0x01, 0x31, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x14, 0x40, 0x10, 0x32, 0x00, 0xc2, 0x07, 0x00, 0x00, 0x00, 0x00};
606             json parsed = json::from_bson(input);
607             json expected = {{"BSON", {"awesome", 5.05, 1986}}};
608             CHECK(parsed == expected);
609             auto dumped = json::to_bson(parsed);
610             CHECK(dumped == input);
611             CHECK(json::from_bson(dumped) == expected);
612         }
613     }
614 }
615 
616 TEST_CASE("BSON input/output_adapters")
617 {
618     json json_representation =
619     {
620         {"double", 42.5},
621         {"entry", 4.2},
622         {"number", 12345},
623         {"object", {{ "string", "value" }}}
624     };
625 
626     std::vector<std::uint8_t> bson_representation =
627     {
628         /*size */ 0x4f, 0x00, 0x00, 0x00,
629         /*entry*/ 0x01, 'd',  'o',  'u',  'b',  'l',  'e',  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x45, 0x40,
630         /*entry*/ 0x01, 'e',  'n',  't',  'r',  'y',  0x00, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x10, 0x40,
631         /*entry*/ 0x10, 'n',  'u',  'm',  'b',  'e',  'r',  0x00, 0x39, 0x30, 0x00, 0x00,
632         /*entry*/ 0x03, 'o',  'b',  'j',  'e',  'c',  't',  0x00,
633         /*entry: obj-size */ 0x17, 0x00, 0x00, 0x00,
634         /*entry: obj-entry*/0x02, 's',  't',  'r',  'i',  'n',  'g', 0x00, 0x06, 0x00, 0x00, 0x00, 'v', 'a', 'l', 'u', 'e', 0,
635         /*entry: obj-term.*/0x00,
636         /*obj-term*/ 0x00
637     };
638 
639     json j2;
640     CHECK_NOTHROW(j2 = json::from_bson(bson_representation));
641 
642     // compare parsed JSON values
643     CHECK(json_representation == j2);
644 
645     SECTION("roundtrips")
646     {
647         SECTION("std::ostringstream")
648         {
649             std::basic_ostringstream<std::uint8_t> ss;
650             json::to_bson(json_representation, ss);
651             json j3 = json::from_bson(ss.str());
652             CHECK(json_representation == j3);
653         }
654 
655         SECTION("std::string")
656         {
657             std::string s;
658             json::to_bson(json_representation, s);
659             json j3 = json::from_bson(s);
660             CHECK(json_representation == j3);
661         }
662 
663         SECTION("std::vector")
664         {
665             std::vector<std::uint8_t> v;
666             json::to_bson(json_representation, v);
667             json j3 = json::from_bson(v);
668             CHECK(json_representation == j3);
669         }
670     }
671 }
672 
673 namespace
674 {
675 class SaxCountdown
676 {
677   public:
SaxCountdown(const int count)678     explicit SaxCountdown(const int count) : events_left(count)
679     {}
680 
null()681     bool null()
682     {
683         return events_left-- > 0;
684     }
685 
boolean(bool)686     bool boolean(bool)
687     {
688         return events_left-- > 0;
689     }
690 
number_integer(json::number_integer_t)691     bool number_integer(json::number_integer_t)
692     {
693         return events_left-- > 0;
694     }
695 
number_unsigned(json::number_unsigned_t)696     bool number_unsigned(json::number_unsigned_t)
697     {
698         return events_left-- > 0;
699     }
700 
number_float(json::number_float_t,const std::string &)701     bool number_float(json::number_float_t, const std::string&)
702     {
703         return events_left-- > 0;
704     }
705 
string(std::string &)706     bool string(std::string&)
707     {
708         return events_left-- > 0;
709     }
710 
binary(std::vector<std::uint8_t> &)711     bool binary(std::vector<std::uint8_t>&)
712     {
713         return events_left-- > 0;
714     }
715 
start_object(std::size_t)716     bool start_object(std::size_t)
717     {
718         return events_left-- > 0;
719     }
720 
key(std::string &)721     bool key(std::string&)
722     {
723         return events_left-- > 0;
724     }
725 
end_object()726     bool end_object()
727     {
728         return events_left-- > 0;
729     }
730 
start_array(std::size_t)731     bool start_array(std::size_t)
732     {
733         return events_left-- > 0;
734     }
735 
end_array()736     bool end_array()
737     {
738         return events_left-- > 0;
739     }
740 
parse_error(std::size_t,const std::string &,const json::exception &)741     bool parse_error(std::size_t, const std::string&, const json::exception&)
742     {
743         return false;
744     }
745 
746   private:
747     int events_left = 0;
748 };
749 }
750 
751 TEST_CASE("Incomplete BSON Input")
752 {
753     SECTION("Incomplete BSON Input 1")
754     {
755         std::vector<std::uint8_t> incomplete_bson =
756         {
757             0x0D, 0x00, 0x00, 0x00, // size (little endian)
758             0x08,                   // entry: boolean
759             'e', 'n', 't'           // unexpected EOF
760         };
761 
762         json _;
763         CHECK_THROWS_AS(_ = json::from_bson(incomplete_bson), json::parse_error&);
764         CHECK_THROWS_WITH(_ = json::from_bson(incomplete_bson),
765                           "[json.exception.parse_error.110] parse error at byte 9: syntax error while parsing BSON cstring: unexpected end of input");
766 
767         CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
768 
769         SaxCountdown scp(0);
770         CHECK(!json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
771     }
772 
773     SECTION("Incomplete BSON Input 2")
774     {
775         std::vector<std::uint8_t> incomplete_bson =
776         {
777             0x0D, 0x00, 0x00, 0x00, // size (little endian)
778             0x08,                   // entry: boolean, unexpected EOF
779         };
780 
781         json _;
782         CHECK_THROWS_AS(_ = json::from_bson(incomplete_bson), json::parse_error&);
783         CHECK_THROWS_WITH(_ = json::from_bson(incomplete_bson),
784                           "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing BSON cstring: unexpected end of input");
785         CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
786 
787         SaxCountdown scp(0);
788         CHECK(!json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
789     }
790 
791     SECTION("Incomplete BSON Input 3")
792     {
793         std::vector<std::uint8_t> incomplete_bson =
794         {
795             0x41, 0x00, 0x00, 0x00, // size (little endian)
796             0x04, /// entry: embedded document
797             'e', 'n', 't', 'r', 'y', '\x00',
798 
799             0x35, 0x00, 0x00, 0x00, // size (little endian)
800             0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
801             0x10, 0x00, 0x02, 0x00, 0x00, 0x00
802             // missing input data...
803         };
804 
805         json _;
806         CHECK_THROWS_AS(_ = json::from_bson(incomplete_bson), json::parse_error&);
807         CHECK_THROWS_WITH(_ = json::from_bson(incomplete_bson),
808                           "[json.exception.parse_error.110] parse error at byte 28: syntax error while parsing BSON element list: unexpected end of input");
809         CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
810 
811         SaxCountdown scp(1);
812         CHECK(!json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
813     }
814 
815     SECTION("Incomplete BSON Input 4")
816     {
817         std::vector<std::uint8_t> incomplete_bson =
818         {
819             0x0D, 0x00, // size (incomplete), unexpected EOF
820         };
821 
822         json _;
823         CHECK_THROWS_AS(_ = json::from_bson(incomplete_bson), json::parse_error&);
824         CHECK_THROWS_WITH(_ = json::from_bson(incomplete_bson),
825                           "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BSON number: unexpected end of input");
826         CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
827 
828         SaxCountdown scp(0);
829         CHECK(!json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
830     }
831 
832     SECTION("Improve coverage")
833     {
834         SECTION("key")
835         {
836             json j = {{"key", "value"}};
837             auto bson_vec = json::to_bson(j);
838             SaxCountdown scp(2);
839             CHECK(!json::sax_parse(bson_vec, &scp, json::input_format_t::bson));
840         }
841 
842         SECTION("array")
843         {
844             json j =
845             {
846                 { "entry", json::array() }
847             };
848             auto bson_vec = json::to_bson(j);
849             SaxCountdown scp(2);
850             CHECK(!json::sax_parse(bson_vec, &scp, json::input_format_t::bson));
851         }
852     }
853 }
854 
855 TEST_CASE("Negative size of binary value")
856 {
857     // invalid BSON: the size of the binary value is -1
858     std::vector<std::uint8_t> input =
859     {
860         0x21, 0x00, 0x00, 0x00, // size (little endian)
861         0x05, // entry: binary
862         'e', 'n', 't', 'r', 'y', '\x00',
863 
864         0xFF, 0xFF, 0xFF, 0xFF, // size of binary (little endian)
865         0x05, // MD5 binary subtype
866         0xd7, 0x7e, 0x27, 0x54, 0xbe, 0x12, 0x37, 0xfe, 0xd6, 0x0c, 0x33, 0x98, 0x30, 0x3b, 0x8d, 0xc4,
867 
868         0x00 // end marker
869     };
870     CHECK_THROWS_AS(json::from_bson(input), json::parse_error);
871     CHECK_THROWS_WITH(json::from_bson(input), "[json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1");
872 }
873 
874 TEST_CASE("Unsupported BSON input")
875 {
876     std::vector<std::uint8_t> bson =
877     {
878         0x0C, 0x00, 0x00, 0x00, // size (little endian)
879         0xFF,                   // entry type: Min key (not supported yet)
880         'e', 'n', 't', 'r', 'y', '\x00',
881         0x00 // end marker
882     };
883 
884     json _;
885     CHECK_THROWS_AS(_ = json::from_bson(bson), json::parse_error&);
886     CHECK_THROWS_WITH(_ = json::from_bson(bson),
887                       "[json.exception.parse_error.114] parse error at byte 5: Unsupported BSON record type 0xFF");
888     CHECK(json::from_bson(bson, true, false).is_discarded());
889 
890     SaxCountdown scp(0);
891     CHECK(!json::sax_parse(bson, &scp, json::input_format_t::bson));
892 }
893 
894 TEST_CASE("BSON numerical data")
895 {
896     SECTION("number")
897     {
898         SECTION("signed")
899         {
900             SECTION("std::int64_t: INT64_MIN .. INT32_MIN-1")
901             {
902                 std::vector<int64_t> numbers
903                 {
904                     INT64_MIN,
905                     -1000000000000000000LL,
906                     -100000000000000000LL,
907                     -10000000000000000LL,
908                     -1000000000000000LL,
909                     -100000000000000LL,
910                     -10000000000000LL,
911                     -1000000000000LL,
912                     -100000000000LL,
913                     -10000000000LL,
914                     static_cast<std::int64_t>(INT32_MIN) - 1,
915                 };
916 
917                 for (auto i : numbers)
918                 {
919 
920                     CAPTURE(i)
921 
922                     json j =
923                     {
924                         { "entry", i }
925                     };
926                     CHECK(j.at("entry").is_number_integer());
927 
928                     std::uint64_t iu = *reinterpret_cast<std::uint64_t*>(&i);
929                     std::vector<std::uint8_t> expected_bson =
930                     {
931                         0x14u, 0x00u, 0x00u, 0x00u, // size (little endian)
932                         0x12u, /// entry: int64
933                         'e', 'n', 't', 'r', 'y', '\x00',
934                         static_cast<std::uint8_t>((iu >> (8u * 0u)) & 0xffu),
935                         static_cast<std::uint8_t>((iu >> (8u * 1u)) & 0xffu),
936                         static_cast<std::uint8_t>((iu >> (8u * 2u)) & 0xffu),
937                         static_cast<std::uint8_t>((iu >> (8u * 3u)) & 0xffu),
938                         static_cast<std::uint8_t>((iu >> (8u * 4u)) & 0xffu),
939                         static_cast<std::uint8_t>((iu >> (8u * 5u)) & 0xffu),
940                         static_cast<std::uint8_t>((iu >> (8u * 6u)) & 0xffu),
941                         static_cast<std::uint8_t>((iu >> (8u * 7u)) & 0xffu),
942                         0x00u // end marker
943                     };
944 
945                     const auto bson = json::to_bson(j);
946                     CHECK(bson == expected_bson);
947 
948                     auto j_roundtrip = json::from_bson(bson);
949 
950                     CHECK(j_roundtrip.at("entry").is_number_integer());
951                     CHECK(j_roundtrip == j);
952                     CHECK(json::from_bson(bson, true, false) == j);
953 
954                 }
955             }
956 
957 
958             SECTION("signed std::int32_t: INT32_MIN .. INT32_MAX")
959             {
960                 std::vector<int32_t> numbers
961                 {
962                     INT32_MIN,
963                     -2147483647L,
964                     -1000000000L,
965                     -100000000L,
966                     -10000000L,
967                     -1000000L,
968                     -100000L,
969                     -10000L,
970                     -1000L,
971                     -100L,
972                     -10L,
973                     -1L,
974                     0L,
975                     1L,
976                     10L,
977                     100L,
978                     1000L,
979                     10000L,
980                     100000L,
981                     1000000L,
982                     10000000L,
983                     100000000L,
984                     1000000000L,
985                     2147483646L,
986                     INT32_MAX
987                 };
988 
989                 for (auto i : numbers)
990                 {
991 
992                     CAPTURE(i)
993 
994                     json j =
995                     {
996                         { "entry", i }
997                     };
998                     CHECK(j.at("entry").is_number_integer());
999 
1000                     std::uint32_t iu = *reinterpret_cast<std::uint32_t*>(&i);
1001                     std::vector<std::uint8_t> expected_bson =
1002                     {
1003                         0x10u, 0x00u, 0x00u, 0x00u, // size (little endian)
1004                         0x10u, /// entry: int32
1005                         'e', 'n', 't', 'r', 'y', '\x00',
1006                         static_cast<std::uint8_t>((iu >> (8u * 0u)) & 0xffu),
1007                         static_cast<std::uint8_t>((iu >> (8u * 1u)) & 0xffu),
1008                         static_cast<std::uint8_t>((iu >> (8u * 2u)) & 0xffu),
1009                         static_cast<std::uint8_t>((iu >> (8u * 3u)) & 0xffu),
1010                         0x00u // end marker
1011                     };
1012 
1013                     const auto bson = json::to_bson(j);
1014                     CHECK(bson == expected_bson);
1015 
1016                     auto j_roundtrip = json::from_bson(bson);
1017 
1018                     CHECK(j_roundtrip.at("entry").is_number_integer());
1019                     CHECK(j_roundtrip == j);
1020                     CHECK(json::from_bson(bson, true, false) == j);
1021 
1022                 }
1023             }
1024 
1025             SECTION("signed std::int64_t: INT32_MAX+1 .. INT64_MAX")
1026             {
1027                 std::vector<int64_t> numbers
1028                 {
1029                     INT64_MAX,
1030                     1000000000000000000LL,
1031                     100000000000000000LL,
1032                     10000000000000000LL,
1033                     1000000000000000LL,
1034                     100000000000000LL,
1035                     10000000000000LL,
1036                     1000000000000LL,
1037                     100000000000LL,
1038                     10000000000LL,
1039                     static_cast<std::int64_t>(INT32_MAX) + 1,
1040                 };
1041 
1042                 for (auto i : numbers)
1043                 {
1044 
1045                     CAPTURE(i)
1046 
1047                     json j =
1048                     {
1049                         { "entry", i }
1050                     };
1051                     CHECK(j.at("entry").is_number_integer());
1052 
1053                     std::uint64_t iu = *reinterpret_cast<std::uint64_t*>(&i);
1054                     std::vector<std::uint8_t> expected_bson =
1055                     {
1056                         0x14u, 0x00u, 0x00u, 0x00u, // size (little endian)
1057                         0x12u, /// entry: int64
1058                         'e', 'n', 't', 'r', 'y', '\x00',
1059                         static_cast<std::uint8_t>((iu >> (8u * 0u)) & 0xffu),
1060                         static_cast<std::uint8_t>((iu >> (8u * 1u)) & 0xffu),
1061                         static_cast<std::uint8_t>((iu >> (8u * 2u)) & 0xffu),
1062                         static_cast<std::uint8_t>((iu >> (8u * 3u)) & 0xffu),
1063                         static_cast<std::uint8_t>((iu >> (8u * 4u)) & 0xffu),
1064                         static_cast<std::uint8_t>((iu >> (8u * 5u)) & 0xffu),
1065                         static_cast<std::uint8_t>((iu >> (8u * 6u)) & 0xffu),
1066                         static_cast<std::uint8_t>((iu >> (8u * 7u)) & 0xffu),
1067                         0x00u // end marker
1068                     };
1069 
1070                     const auto bson = json::to_bson(j);
1071                     CHECK(bson == expected_bson);
1072 
1073                     auto j_roundtrip = json::from_bson(bson);
1074 
1075                     CHECK(j_roundtrip.at("entry").is_number_integer());
1076                     CHECK(j_roundtrip == j);
1077                     CHECK(json::from_bson(bson, true, false) == j);
1078 
1079                 }
1080             }
1081         }
1082 
1083         SECTION("unsigned")
1084         {
1085             SECTION("unsigned std::uint64_t: 0 .. INT32_MAX")
1086             {
1087                 std::vector<std::uint64_t> numbers
1088                 {
1089                     0ULL,
1090                     1ULL,
1091                     10ULL,
1092                     100ULL,
1093                     1000ULL,
1094                     10000ULL,
1095                     100000ULL,
1096                     1000000ULL,
1097                     10000000ULL,
1098                     100000000ULL,
1099                     1000000000ULL,
1100                     2147483646ULL,
1101                     static_cast<std::uint64_t>(INT32_MAX)
1102                 };
1103 
1104                 for (auto i : numbers)
1105                 {
1106 
1107                     CAPTURE(i)
1108 
1109                     json j =
1110                     {
1111                         { "entry", i }
1112                     };
1113 
1114                     auto iu = i;
1115                     std::vector<std::uint8_t> expected_bson =
1116                     {
1117                         0x10u, 0x00u, 0x00u, 0x00u, // size (little endian)
1118                         0x10u, /// entry: int32
1119                         'e', 'n', 't', 'r', 'y', '\x00',
1120                         static_cast<std::uint8_t>((iu >> (8u * 0u)) & 0xffu),
1121                         static_cast<std::uint8_t>((iu >> (8u * 1u)) & 0xffu),
1122                         static_cast<std::uint8_t>((iu >> (8u * 2u)) & 0xffu),
1123                         static_cast<std::uint8_t>((iu >> (8u * 3u)) & 0xffu),
1124                         0x00u // end marker
1125                     };
1126 
1127                     const auto bson = json::to_bson(j);
1128                     CHECK(bson == expected_bson);
1129 
1130                     auto j_roundtrip = json::from_bson(bson);
1131 
1132                     CHECK(j.at("entry").is_number_unsigned());
1133                     CHECK(j_roundtrip.at("entry").is_number_integer());
1134                     CHECK(j_roundtrip == j);
1135                     CHECK(json::from_bson(bson, true, false) == j);
1136 
1137                 }
1138             }
1139 
1140             SECTION("unsigned std::uint64_t: INT32_MAX+1 .. INT64_MAX")
1141             {
1142                 std::vector<std::uint64_t> numbers
1143                 {
1144                     static_cast<std::uint64_t>(INT32_MAX) + 1,
1145                     4000000000ULL,
1146                     static_cast<std::uint64_t>(UINT32_MAX),
1147                     10000000000ULL,
1148                     100000000000ULL,
1149                     1000000000000ULL,
1150                     10000000000000ULL,
1151                     100000000000000ULL,
1152                     1000000000000000ULL,
1153                     10000000000000000ULL,
1154                     100000000000000000ULL,
1155                     1000000000000000000ULL,
1156                     static_cast<std::uint64_t>(INT64_MAX),
1157                 };
1158 
1159                 for (auto i : numbers)
1160                 {
1161 
1162                     CAPTURE(i)
1163 
1164                     json j =
1165                     {
1166                         { "entry", i }
1167                     };
1168 
1169                     auto iu = i;
1170                     std::vector<std::uint8_t> expected_bson =
1171                     {
1172                         0x14u, 0x00u, 0x00u, 0x00u, // size (little endian)
1173                         0x12u, /// entry: int64
1174                         'e', 'n', 't', 'r', 'y', '\x00',
1175                         static_cast<std::uint8_t>((iu >> (8u * 0u)) & 0xffu),
1176                         static_cast<std::uint8_t>((iu >> (8u * 1u)) & 0xffu),
1177                         static_cast<std::uint8_t>((iu >> (8u * 2u)) & 0xffu),
1178                         static_cast<std::uint8_t>((iu >> (8u * 3u)) & 0xffu),
1179                         static_cast<std::uint8_t>((iu >> (8u * 4u)) & 0xffu),
1180                         static_cast<std::uint8_t>((iu >> (8u * 5u)) & 0xffu),
1181                         static_cast<std::uint8_t>((iu >> (8u * 6u)) & 0xffu),
1182                         static_cast<std::uint8_t>((iu >> (8u * 7u)) & 0xffu),
1183                         0x00u // end marker
1184                     };
1185 
1186                     const auto bson = json::to_bson(j);
1187                     CHECK(bson == expected_bson);
1188 
1189                     auto j_roundtrip = json::from_bson(bson);
1190 
1191                     CHECK(j.at("entry").is_number_unsigned());
1192                     CHECK(j_roundtrip.at("entry").is_number_integer());
1193                     CHECK(j_roundtrip == j);
1194                     CHECK(json::from_bson(bson, true, false) == j);
1195                 }
1196             }
1197 
1198             SECTION("unsigned std::uint64_t: INT64_MAX+1 .. UINT64_MAX")
1199             {
1200                 std::vector<std::uint64_t> numbers
1201                 {
1202                     static_cast<std::uint64_t>(INT64_MAX) + 1ULL,
1203                     10000000000000000000ULL,
1204                     18000000000000000000ULL,
1205                     UINT64_MAX - 1ULL,
1206                     UINT64_MAX,
1207                 };
1208 
1209                 for (auto i : numbers)
1210                 {
1211 
1212                     CAPTURE(i)
1213 
1214                     json j =
1215                     {
1216                         { "entry", i }
1217                     };
1218 
1219                     auto iu = i;
1220                     std::vector<std::uint8_t> expected_bson =
1221                     {
1222                         0x14u, 0x00u, 0x00u, 0x00u, // size (little endian)
1223                         0x12u, /// entry: int64
1224                         'e', 'n', 't', 'r', 'y', '\x00',
1225                         static_cast<std::uint8_t>((iu >> (8u * 0u)) & 0xffu),
1226                         static_cast<std::uint8_t>((iu >> (8u * 1u)) & 0xffu),
1227                         static_cast<std::uint8_t>((iu >> (8u * 2u)) & 0xffu),
1228                         static_cast<std::uint8_t>((iu >> (8u * 3u)) & 0xffu),
1229                         static_cast<std::uint8_t>((iu >> (8u * 4u)) & 0xffu),
1230                         static_cast<std::uint8_t>((iu >> (8u * 5u)) & 0xffu),
1231                         static_cast<std::uint8_t>((iu >> (8u * 6u)) & 0xffu),
1232                         static_cast<std::uint8_t>((iu >> (8u * 7u)) & 0xffu),
1233                         0x00u // end marker
1234                     };
1235 
1236                     CHECK_THROWS_AS(json::to_bson(j), json::out_of_range&);
1237                     CHECK_THROWS_WITH_STD_STR(json::to_bson(j), "[json.exception.out_of_range.407] integer number " + std::to_string(i) + " cannot be represented by BSON as it does not fit int64");
1238                 }
1239             }
1240 
1241         }
1242     }
1243 }
1244 
skip()1245 TEST_CASE("BSON roundtrips" * doctest::skip())
1246 {
1247     SECTION("reference files")
1248     {
1249         for (std::string filename :
1250                 {
1251                     TEST_DATA_DIRECTORY "/json.org/1.json",
1252                     TEST_DATA_DIRECTORY "/json.org/2.json",
1253                     TEST_DATA_DIRECTORY "/json.org/3.json",
1254                     TEST_DATA_DIRECTORY "/json.org/4.json",
1255                     TEST_DATA_DIRECTORY "/json.org/5.json"
1256                 })
1257         {
1258             CAPTURE(filename)
1259 
1260             {
1261                 INFO_WITH_TEMP(filename + ": std::vector<std::uint8_t>");
1262                 // parse JSON file
1263                 std::ifstream f_json(filename);
1264                 json j1 = json::parse(f_json);
1265 
1266                 // parse BSON file
1267                 auto packed = utils::read_binary_file(filename + ".bson");
1268                 json j2;
1269                 CHECK_NOTHROW(j2 = json::from_bson(packed));
1270 
1271                 // compare parsed JSON values
1272                 CHECK(j1 == j2);
1273             }
1274 
1275             {
1276                 INFO_WITH_TEMP(filename + ": std::ifstream");
1277                 // parse JSON file
1278                 std::ifstream f_json(filename);
1279                 json j1 = json::parse(f_json);
1280 
1281                 // parse BSON file
1282                 std::ifstream f_bson(filename + ".bson", std::ios::binary);
1283                 json j2;
1284                 CHECK_NOTHROW(j2 = json::from_bson(f_bson));
1285 
1286                 // compare parsed JSON values
1287                 CHECK(j1 == j2);
1288             }
1289 
1290             {
1291                 INFO_WITH_TEMP(filename + ": uint8_t* and size");
1292                 // parse JSON file
1293                 std::ifstream f_json(filename);
1294                 json j1 = json::parse(f_json);
1295 
1296                 // parse BSON file
1297                 auto packed = utils::read_binary_file(filename + ".bson");
1298                 json j2;
1299                 CHECK_NOTHROW(j2 = json::from_bson({packed.data(), packed.size()}));
1300 
1301                 // compare parsed JSON values
1302                 CHECK(j1 == j2);
1303             }
1304 
1305             {
1306                 INFO_WITH_TEMP(filename + ": output to output adapters");
1307                 // parse JSON file
1308                 std::ifstream f_json(filename);
1309                 json j1 = json::parse(f_json);
1310 
1311                 // parse BSON file
1312                 auto packed = utils::read_binary_file(filename + ".bson");
1313 
1314                 {
1315                     INFO_WITH_TEMP(filename + ": output adapters: std::vector<std::uint8_t>");
1316                     std::vector<std::uint8_t> vec;
1317                     json::to_bson(j1, vec);
1318 
1319                     if (vec != packed)
1320                     {
1321                         // the exact serializations may differ due to the order of
1322                         // object keys; in these cases, just compare whether both
1323                         // serializations create the same JSON value
1324                         CHECK(json::from_bson(vec) == json::from_bson(packed));
1325                     }
1326                 }
1327             }
1328         }
1329     }
1330 }
1331