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