From f1f3f50e5cd551bddb4951dbd2343c69bd2821a1 Mon Sep 17 00:00:00 2001 From: Ezra Chung <88335979+eramongodb@users.noreply.github.com> Date: Fri, 26 Aug 2022 13:16:31 -0500 Subject: [PATCH] Add StringMaker specialization for bsoncxx::types::bson_value types (#891) * Add StringMaker specialization for bsoncxx::types::bson_value types * Add StringMaker specialization for bsoncxx::document::view_or_value * Fix missing return in StringMaker specialization for optionals --- src/bsoncxx/CMakeLists.txt | 1 + src/bsoncxx/test_util/catch.hh | 35 ++++++- src/bsoncxx/test_util/to_string.hh | 96 +++++++++++++++++++ src/mongocxx/test/spec/monitoring.cpp | 3 +- .../test/spec/unified_tests/assert.cpp | 63 +----------- .../test/spec/unified_tests/assert.hh | 1 - 6 files changed, 132 insertions(+), 67 deletions(-) create mode 100644 src/bsoncxx/test_util/to_string.hh diff --git a/src/bsoncxx/CMakeLists.txt b/src/bsoncxx/CMakeLists.txt index 270701d348..d87d588e0a 100644 --- a/src/bsoncxx/CMakeLists.txt +++ b/src/bsoncxx/CMakeLists.txt @@ -289,6 +289,7 @@ set_local_dist (src_bsoncxx_DIST_local string/view_or_value.hpp test_util/catch.hh test_util/export_for_testing.hh + test_util/to_string.hh types.cpp types.hpp types/value.hpp diff --git a/src/bsoncxx/test_util/catch.hh b/src/bsoncxx/test_util/catch.hh index d16a8984c2..6b60483168 100644 --- a/src/bsoncxx/test_util/catch.hh +++ b/src/bsoncxx/test_util/catch.hh @@ -14,11 +14,12 @@ #pragma once -#include "catch.hpp" -#include +#include #include #include #include +#include +#include #include @@ -41,6 +42,13 @@ struct StringMaker { } }; +template <> +struct StringMaker { + static std::string convert(const bsoncxx::document::view_or_value& value) { + return StringMaker::convert(value.view()); + } +}; + template <> struct StringMaker { static std::string convert(const bsoncxx::document::value& value) { @@ -48,11 +56,32 @@ struct StringMaker { } }; +template <> +struct StringMaker { + static std::string convert(const bsoncxx::types::bson_value::view& value) { + return '{' + to_string(value.type()) + ": " + to_string(value) + '}'; + } +}; + +template <> +struct StringMaker { + static std::string convert(const bsoncxx::types::bson_value::value& value) { + return StringMaker::convert(value.view()); + } +}; + +template <> +struct StringMaker { + static std::string convert(const bsoncxx::types::bson_value::view_or_value& value) { + return StringMaker::convert(value.view()); + } +}; + template struct StringMaker> { static std::string convert(const bsoncxx::stdx::optional& value) { if (value) { - StringMaker::convert(value.value()); + return StringMaker::convert(value.value()); } return "{nullopt}"; diff --git a/src/bsoncxx/test_util/to_string.hh b/src/bsoncxx/test_util/to_string.hh new file mode 100644 index 0000000000..53620a420a --- /dev/null +++ b/src/bsoncxx/test_util/to_string.hh @@ -0,0 +1,96 @@ +// Copyright 2022 MongoDB Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace bsoncxx { +BSONCXX_INLINE_NAMESPACE_BEGIN + +inline std::string to_string(types::bson_value::view_or_value val) { + switch (val.view().type()) { + case bsoncxx::type::k_string: + return string::to_string(val.view().get_string().value); + case bsoncxx::type::k_int32: + return std::to_string(val.view().get_int32().value); + case bsoncxx::type::k_int64: + return std::to_string(val.view().get_int64().value); + case bsoncxx::type::k_document: + return to_json(val.view().get_document().value); + case bsoncxx::type::k_array: + return to_json(val.view().get_array().value); + case bsoncxx::type::k_oid: + return val.view().get_oid().value.to_string(); + case bsoncxx::type::k_binary: { + const auto& binary = val.view().get_binary(); + std::stringstream ss; + ss << std::hex; + for (auto&& byte : + std::vector(binary.bytes, binary.bytes + binary.size)) { + ss << std::setw(2) << std::setfill('0') << byte; + } + return ss.str(); + } + case bsoncxx::type::k_bool: + return val.view().get_bool().value ? "true" : "false"; + case bsoncxx::type::k_code: + return string::to_string(val.view().get_code().code); + case bsoncxx::type::k_codewscope: + return "code={" + string::to_string(val.view().get_codewscope().code) + "}, scope={" + + to_json(val.view().get_codewscope().scope) + "}"; + case bsoncxx::type::k_date: + return std::to_string(val.view().get_date().value.count()); + case bsoncxx::type::k_double: + return std::to_string(val.view().get_double()); + case bsoncxx::type::k_null: + return "null"; + case bsoncxx::type::k_undefined: + return "undefined"; + case bsoncxx::type::k_timestamp: + return "timestamp={" + std::to_string(val.view().get_timestamp().timestamp) + + "}, increment={" + std::to_string(val.view().get_timestamp().increment) + "}"; + case bsoncxx::type::k_regex: + return "regex={" + string::to_string(val.view().get_regex().regex) + "}, options={" + + string::to_string(val.view().get_regex().options) + "}"; + case bsoncxx::type::k_minkey: + return "minkey"; + case bsoncxx::type::k_maxkey: + return "maxkey"; + case bsoncxx::type::k_decimal128: + return val.view().get_decimal128().value.to_string(); + case bsoncxx::type::k_symbol: + return string::to_string(val.view().get_symbol().symbol); + case bsoncxx::type::k_dbpointer: + return val.view().get_dbpointer().value.to_string(); + default: + return "?"; // Match bsoncxx::to_string(bsoncxx::type) behavior. + } +} + +BSONCXX_INLINE_NAMESPACE_END +} // namespace bsoncxx + +#include diff --git a/src/mongocxx/test/spec/monitoring.cpp b/src/mongocxx/test/spec/monitoring.cpp index cf3a0c263b..6fa6c9bd2e 100644 --- a/src/mongocxx/test/spec/monitoring.cpp +++ b/src/mongocxx/test/spec/monitoring.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -53,7 +54,7 @@ void apm_checker::compare_unified(bsoncxx::array::view expectations, // This will throw an exception on unmatched fields and return true in all other cases. auto compare = [&](const bsoncxx::array::element& exp, const bsoncxx::document::view actual) { - CAPTURE(print_all(), to_json(actual), assert::to_string(exp.get_value())); + CAPTURE(print_all(), to_json(actual), bsoncxx::to_string(exp.get_value())); // Extra fields are only allowed in root-level documents. Here, each k in keys is treated // as its own root-level document, allowing extra fields. diff --git a/src/mongocxx/test/spec/unified_tests/assert.cpp b/src/mongocxx/test/spec/unified_tests/assert.cpp index d28c7bd00d..9dc5f08ce2 100644 --- a/src/mongocxx/test/spec/unified_tests/assert.cpp +++ b/src/mongocxx/test/spec/unified_tests/assert.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -29,7 +30,6 @@ using namespace bsoncxx; using namespace mongocxx; -using assert::to_string; using bsoncxx::types::bson_value::value; namespace { @@ -74,67 +74,6 @@ std::string match_doc_current_path() noexcept { } // namespace -std::string binary_to_string(types::b_binary binary) { - std::stringstream ss; - ss << std::hex; - for (auto&& byte : std::vector(binary.bytes, binary.bytes + binary.size)) { - ss << std::setw(2) << std::setfill('0') << byte; - } - return ss.str(); -} - -std::string assert::to_string(types::bson_value::view_or_value val) { - switch (val.view().type()) { - case bsoncxx::type::k_string: - return string::to_string(val.view().get_string().value); - case bsoncxx::type::k_int32: - return std::to_string(val.view().get_int32().value); - case bsoncxx::type::k_int64: - return std::to_string(val.view().get_int64().value); - case bsoncxx::type::k_document: - return to_json(val.view().get_document().value); - case bsoncxx::type::k_array: - return to_json(val.view().get_array().value); - case bsoncxx::type::k_oid: - return val.view().get_oid().value.to_string(); - case bsoncxx::type::k_binary: - return binary_to_string(val.view().get_binary()); - case bsoncxx::type::k_bool: - return val.view().get_bool().value ? "true" : "false"; - case bsoncxx::type::k_code: - return string::to_string(val.view().get_code().code); - case bsoncxx::type::k_codewscope: - return "code={" + string::to_string(val.view().get_codewscope().code) + "}, scope={" + - to_json(val.view().get_codewscope().scope) + "}"; - case bsoncxx::type::k_date: - return std::to_string(val.view().get_date().value.count()); - case bsoncxx::type::k_double: - return std::to_string(val.view().get_double()); - case bsoncxx::type::k_null: - return "null"; - case bsoncxx::type::k_undefined: - return "undefined"; - case bsoncxx::type::k_timestamp: - return "timestamp={" + std::to_string(val.view().get_timestamp().timestamp) + - "}, increment={" + std::to_string(val.view().get_timestamp().increment) + "}"; - case bsoncxx::type::k_regex: - return "regex={" + string::to_string(val.view().get_regex().regex) + "}, options={" + - string::to_string(val.view().get_regex().options) + "}"; - case bsoncxx::type::k_minkey: - return "minkey"; - case bsoncxx::type::k_maxkey: - return "maxkey"; - case bsoncxx::type::k_decimal128: - return val.view().get_decimal128().value.to_string(); - case bsoncxx::type::k_symbol: - return string::to_string(val.view().get_symbol().symbol); - case bsoncxx::type::k_dbpointer: - return val.view().get_dbpointer().value.to_string(); - default: - MONGOCXX_UNREACHABLE; - } -} - template type to_type(const Element& type) { auto type_str = string::to_string(type.get_string().value); diff --git a/src/mongocxx/test/spec/unified_tests/assert.hh b/src/mongocxx/test/spec/unified_tests/assert.hh index f0651a6a1c..edceb51d12 100644 --- a/src/mongocxx/test/spec/unified_tests/assert.hh +++ b/src/mongocxx/test/spec/unified_tests/assert.hh @@ -29,7 +29,6 @@ void matches(bsoncxx::types::bson_value::view actual, bool is_root = true, bool is_array_of_root_docs = false); -std::string to_string(bsoncxx::types::bson_value::view_or_value val); } // namespace assert MONGOCXX_INLINE_NAMESPACE_END } // namespace mongocxx