diff options
Diffstat (limited to 'src/mongo/client')
-rw-r--r-- | src/mongo/client/sdam/sdam_test_base.h | 170 | ||||
-rw-r--r-- | src/mongo/client/sdam/server_description_test.cpp | 7 | ||||
-rw-r--r-- | src/mongo/client/sdam/server_selector_test.cpp | 3 | ||||
-rw-r--r-- | src/mongo/client/sdam/topology_description_test.cpp | 22 | ||||
-rw-r--r-- | src/mongo/client/sdam/topology_manager_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/client/sdam/topology_state_machine_test.cpp | 19 |
6 files changed, 139 insertions, 84 deletions
diff --git a/src/mongo/client/sdam/sdam_test_base.h b/src/mongo/client/sdam/sdam_test_base.h index 3532e0588b7..eb2ecebfcdc 100644 --- a/src/mongo/client/sdam/sdam_test_base.h +++ b/src/mongo/client/sdam/sdam_test_base.h @@ -28,6 +28,8 @@ */ #pragma once +#include <array> +#include <iterator> #include <map> #include <ostream> #include <set> @@ -37,82 +39,142 @@ #include "mongo/client/sdam/sdam_datatypes.h" #include "mongo/client/sdam/server_description.h" - +#include "mongo/unittest/unittest.h" /** * The following facilitates writing tests in the Server Discovery And Monitoring (sdam) namespace. */ -namespace mongo { +namespace mongo::sdam { + +namespace test_stream_extension { + +template <typename T> +struct IsStdVector : std::false_type {}; +template <typename... Ts> +struct IsStdVector<std::vector<Ts...>> : std::true_type {}; + +template <typename T> +struct IsStdSet : std::false_type {}; +template <typename... Ts> +struct IsStdSet<std::set<Ts...>> : std::true_type {}; + +template <typename T> +struct IsStdMap : std::false_type {}; +template <typename... Ts> +struct IsStdMap<std::map<Ts...>> : std::true_type {}; + template <typename T> -std::ostream& operator<<(std::ostream& os, const std::vector<T>& s) { - os << "["; - size_t i = 0; - for (const auto& item : s) { - os << item; - if (i != s.size() - 1) +struct IsStdPair : std::false_type {}; +template <typename... Ts> +struct IsStdPair<std::pair<Ts...>> : std::true_type {}; + +template <typename T> +struct IsBoostOptional : std::false_type {}; +template <typename... Ts> +struct IsBoostOptional<boost::optional<Ts...>> : std::true_type {}; + +template <typename T> +std::ostream& stream(std::ostream& os, const T& v); + +template <typename Seq> +std::ostream& streamSequence(std::ostream& os, std::array<StringData, 2> braces, const Seq& seq) { + bool sep = false; + os << braces[0]; + for (const auto& item : seq) { + if (sep) os << ", "; + sep = true; + stream(os, item); } - os << "]"; + os << braces[1]; return os; } template <typename T> -std::ostream& operator<<(std::ostream& os, const std::set<T>& s) { - os << "{"; - size_t i = 0; - for (const auto& item : s) { - os << item; - if (i != s.size() - 1) - os << ", "; +struct Extension { + const T& operator*() const { + return v; } - os << "}"; - return os; -} -template <typename K, typename V> -std::ostream& operator<<(std::ostream& os, const std::map<K, V>& m) { - os << "{"; - size_t i = 0; - for (const auto& item : m) { - os << item.first << ": " << item.second; - if (i != m.size() - 1) - os << ", "; + template <typename U> + friend bool operator==(const Extension& a, const Extension<U>& b) { + return *a == *b; + } + template <typename U> + friend bool operator!=(const Extension& a, const Extension<U>& b) { + return *a != *b; + } + template <typename U> + friend bool operator<(const Extension& a, const Extension<U>& b) { + return *a < *b; + } + template <typename U> + friend bool operator>(const Extension& a, const Extension<U>& b) { + return *a > *b; + } + template <typename U> + friend bool operator<=(const Extension& a, const Extension<U>& b) { + return *a <= *b; + } + template <typename U> + friend bool operator>=(const Extension& a, const Extension<U>& b) { + return *a >= *b; + } + + friend std::ostream& operator<<(std::ostream& os, const Extension& ext) { + return stream(os, *ext); + } + + const T& v; +}; + +template <typename T> +std::ostream& stream(std::ostream& os, const T& v) { + if constexpr (IsStdVector<T>{}) { + return streamSequence(os, {"[", "]"}, v); + } else if constexpr (IsStdSet<T>{}) { + return streamSequence(os, {"{", "}"}, v); + } else if constexpr (IsStdMap<T>{}) { + return streamSequence(os, {"{", "}"}, v); + } else if constexpr (IsStdPair<T>{}) { + stream(os, v.first); + os << ": "; + stream(os, v.second); + return os; + } else if constexpr (IsBoostOptional<T>{}) { + if (!v) + return os << boost::optional<Extension<T>>{}; + return os << boost::optional<Extension<T>>{Extension<T>{*v}}; + } else { + return os << v; } - os << "}"; - return os; } -template std::ostream& operator<<(std::ostream& os, - const std::vector<mongo::sdam::ServerDescriptionPtr>& v); -template std::ostream& operator<<(std::ostream& os, const std::set<std::string>& s); -template std::ostream& operator<<(std::ostream& os, const std::map<std::string, std::string>& m); -}; // namespace mongo +} // namespace test_stream_extension -// We include this here because the ASSERT_EQUALS needs to have the operator<< defined -// beforehand for the types used in the tests. -#include "mongo/unittest/unittest.h" -namespace mongo { -namespace sdam { -using mongo::operator<<; +/** + * Facade for use in ASSERTions. Presents pass-through relational ops and custom streaming + * behavior around arbitrary object `v`. + */ +template <typename T> +auto adaptForAssert(const T& v) { + return test_stream_extension::Extension<T>{v}; +} -class SdamTestFixture : public mongo::unittest::Test { +class SdamTestFixture : public unittest::Test { protected: - template <typename T, typename U> - std::vector<U> map(std::vector<T> source, std::function<U(const T&)> f) { + template <typename T, typename F, typename U = std::invoke_result_t<F, T>> + std::vector<U> map(const std::vector<T>& source, const F& f) { std::vector<U> result; - std::transform(source.begin(), - source.end(), - std::back_inserter(result), - [f](const auto& item) { return f(item); }); + std::transform(source.begin(), source.end(), std::back_inserter(result), f); return result; } - template <typename T, typename U> - std::set<U> mapSet(std::vector<T> source, std::function<U(const T&)> f) { - auto v = map<T, U>(source, f); - std::set<U> result(v.begin(), v.end()); - return result; + template <typename T, typename F, typename U = std::invoke_result_t<F, T>> + std::set<U> mapSet(const std::vector<T>& source, const F& f) { + auto v = map(source, f); + return std::set<U>(v.begin(), v.end()); } }; -} // namespace sdam -} // namespace mongo + +} // namespace mongo::sdam diff --git a/src/mongo/client/sdam/server_description_test.cpp b/src/mongo/client/sdam/server_description_test.cpp index c6dc8053e11..eac743ed6f5 100644 --- a/src/mongo/client/sdam/server_description_test.cpp +++ b/src/mongo/client/sdam/server_description_test.cpp @@ -39,6 +39,7 @@ #include "mongo/db/repl/optime.h" #include "mongo/platform/random.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/str.h" #include "mongo/util/system_clock_source.h" namespace mongo::sdam { @@ -212,8 +213,7 @@ class ServerDescriptionTestFixture : public SdamTestFixture { protected: // returns a set containing the elements in the given bson array with lowercase values. std::set<std::string> toHostSet(std::vector<BSONElement> bsonArray) { - return mapSet<BSONElement, std::string>( - bsonArray, [](const BSONElement& e) { return boost::to_lower_copy(e.String()); }); + return mapSet(bsonArray, [](const BSONElement& e) { return str::toLower(e.String()); }); } std::map<std::string, std::string> toStringMap(BSONObj bsonObj) { @@ -466,7 +466,8 @@ TEST_F(ServerDescriptionTestFixture, ShouldStoreTags) { auto response = HelloOutcome( HostAndPort("foo:1234"), kBsonTags, duration_cast<HelloRTT>(mongo::Milliseconds(40))); auto description = ServerDescription(clockSource, response); - ASSERT_EQUALS(toStringMap(kBsonTags["tags"].Obj()), description.getTags()); + ASSERT_EQUALS(adaptForAssert(toStringMap(kBsonTags["tags"].Obj())), + adaptForAssert(description.getTags())); } TEST_F(ServerDescriptionTestFixture, ShouldStoreSetVersionAndName) { diff --git a/src/mongo/client/sdam/server_selector_test.cpp b/src/mongo/client/sdam/server_selector_test.cpp index 5e8ed5f2837..0c0688f03fe 100644 --- a/src/mongo/client/sdam/server_selector_test.cpp +++ b/src/mongo/client/sdam/server_selector_test.cpp @@ -180,7 +180,8 @@ TEST_F(ServerSelectorTestFixture, ShouldThrowOnWireError) { TEST_F(ServerSelectorTestFixture, ShouldReturnNoneIfTopologyUnknown) { auto topologyDescription = std::make_shared<TopologyDescription>(sdamConfiguration); ASSERT_EQ(TopologyType::kUnknown, topologyDescription->getType()); - ASSERT_EQ(boost::none, selector.selectServers(topologyDescription, ReadPreferenceSetting())); + ASSERT_EQ(adaptForAssert(boost::none), + adaptForAssert(selector.selectServers(topologyDescription, ReadPreferenceSetting()))); } TEST_F(ServerSelectorTestFixture, ShouldBeAbleToSelectWithMaxStalenessFromClonedTopology) { diff --git a/src/mongo/client/sdam/topology_description_test.cpp b/src/mongo/client/sdam/topology_description_test.cpp index 6e93291b255..537f70e9e20 100644 --- a/src/mongo/client/sdam/topology_description_test.cpp +++ b/src/mongo/client/sdam/topology_description_test.cpp @@ -41,15 +41,12 @@ #include "mongo/unittest/death_test.h" namespace mongo { -template std::ostream& operator<<(std::ostream& os, const std::vector<HostAndPort>& s); bool operator==(const TopologyVersion& a, const TopologyVersion& b) { return a.getProcessId() == b.getProcessId() && a.getCounter() == b.getCounter(); } namespace sdam { -using mongo::operator<<; - class TopologyDescriptionTestFixture : public SdamTestFixture { protected: @@ -106,7 +103,7 @@ TEST_F(TopologyDescriptionTestFixture, ShouldHaveCorrectDefaultValues) { // // auto expectedAddresses = kTwoServersNormalCase; // -// auto serverAddresses = map<ServerDescriptionPtr, HostAndPort>( +// auto serverAddresses = map( // topologyDescription.getServers(), // [](const ServerDescriptionPtr& description) { return description->getAddress(); }); // @@ -118,10 +115,9 @@ TEST_F(TopologyDescriptionTestFixture, ShouldAllowTypeSingleWithASingleSeed) { ASSERT(TopologyType::kSingle == topologyDescription.getType()); - auto servers = map<ServerDescriptionPtr, HostAndPort>( - topologyDescription.getServers(), - [](const ServerDescriptionPtr& desc) { return desc->getAddress(); }); - ASSERT_EQUALS(kOneServer, servers); + auto servers = + map(topologyDescription.getServers(), [](const auto& desc) { return desc->getAddress(); }); + ASSERT_EQUALS(adaptForAssert(kOneServer), adaptForAssert(servers)); } TEST_F(TopologyDescriptionTestFixture, DoesNotAllowMultipleSeedsWithSingle) { @@ -244,7 +240,7 @@ TEST_F(TopologyDescriptionTestFixture, ShouldSetLogicalSessionTimeoutToMinOfAllS const auto logicalSessionTimeouts = std::vector{300, 100, 200}; auto timeoutIt = logicalSessionTimeouts.begin(); - const auto serverDescriptionsWithTimeouts = map<ServerDescriptionPtr, ServerDescriptionPtr>( + const auto serverDescriptionsWithTimeouts = map( topologyDescription->getServers(), [&timeoutIt](const ServerDescriptionPtr& description) { auto newInstanceBuilder = ServerDescriptionBuilder() .withType(ServerType::kRSSecondary) @@ -274,8 +270,8 @@ TEST_F(TopologyDescriptionTestFixture, const auto logicalSessionTimeouts = std::vector{300, 100, 200}; auto timeoutIt = logicalSessionTimeouts.begin(); - const auto serverDescriptionsWithTimeouts = map<ServerDescriptionPtr, ServerDescriptionPtr>( - topologyDescription->getServers(), [&](const ServerDescriptionPtr& description) { + const auto serverDescriptionsWithTimeouts = + map(topologyDescription->getServers(), [&](const ServerDescriptionPtr& description) { auto timeoutValue = (timeoutIt == logicalSessionTimeouts.begin()) ? boost::none : boost::make_optional(*timeoutIt); @@ -341,5 +337,5 @@ TEST_F(TopologyDescriptionTestFixture, ShouldNotUpdateTopologyVersionOnError) { auto topologyVersion = topologyDescription->getServers()[1]->getTopologyVersion(); ASSERT(topologyVersion == boost::none); } -}; // namespace sdam -}; // namespace mongo +} // namespace sdam +} // namespace mongo diff --git a/src/mongo/client/sdam/topology_manager_test.cpp b/src/mongo/client/sdam/topology_manager_test.cpp index ba1eadaa89f..7b27038d256 100644 --- a/src/mongo/client/sdam/topology_manager_test.cpp +++ b/src/mongo/client/sdam/topology_manager_test.cpp @@ -35,10 +35,8 @@ #include "mongo/util/system_clock_source.h" namespace mongo { -template std::ostream& operator<<(std::ostream& os, const std::vector<HostAndPort>& s); namespace sdam { -using mongo::operator<<; class TopologyManagerTestFixture : public SdamTestFixture { protected: diff --git a/src/mongo/client/sdam/topology_state_machine_test.cpp b/src/mongo/client/sdam/topology_state_machine_test.cpp index 821d476aade..52a8d52754b 100644 --- a/src/mongo/client/sdam/topology_state_machine_test.cpp +++ b/src/mongo/client/sdam/topology_state_machine_test.cpp @@ -184,14 +184,12 @@ TEST_F(TopologyStateMachineTestFixture, .instance(); ASSERT_EQUALS(static_cast<size_t>(2), topologyDescription->getServers().size()); - auto serversBefore = map<ServerDescriptionPtr, HostAndPort>(topologyDescription->getServers(), - getServerDescriptionAddress); + auto serversBefore = map(topologyDescription->getServers(), getServerDescriptionAddress); stateMachine.onServerDescription(*topologyDescription, serverDescription); - auto serversAfter = map<ServerDescriptionPtr, HostAndPort>(topologyDescription->getServers(), - getServerDescriptionAddress); - ASSERT_EQUALS(serversBefore, serversAfter); + auto serversAfter = map(topologyDescription->getServers(), getServerDescriptionAddress); + ASSERT_EQUALS(adaptForAssert(serversBefore), adaptForAssert(serversAfter)); } TEST_F(TopologyStateMachineTestFixture, @@ -259,15 +257,14 @@ TEST_F(TopologyStateMachineTestFixture, ASSERT_EQUALS(topologyDescription->getType(), TopologyType::kReplicaSetWithPrimary); ASSERT_EQUALS(static_cast<size_t>(2), topologyDescription->getServers().size()); - auto serversBefore = map<ServerDescriptionPtr, HostAndPort>(topologyDescription->getServers(), - getServerDescriptionAddress); + auto serversBefore = map(topologyDescription->getServers(), getServerDescriptionAddress); stateMachine.onServerDescription(*topologyDescription, serverDescription); - ASSERT_EQUALS(topologyDescription->getType(), TopologyType::kReplicaSetWithPrimary); + ASSERT_EQUALS(adaptForAssert(topologyDescription->getType()), + adaptForAssert(TopologyType::kReplicaSetWithPrimary)); - auto serversAfter = map<ServerDescriptionPtr, HostAndPort>(topologyDescription->getServers(), - getServerDescriptionAddress); - ASSERT_EQUALS(serversBefore, serversAfter); + auto serversAfter = map(topologyDescription->getServers(), getServerDescriptionAddress); + ASSERT_EQUALS(adaptForAssert(serversBefore), adaptForAssert(serversAfter)); } TEST_F(TopologyStateMachineTestFixture, |