aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/tests/storageserver/rpc/caching_rpc_target_resolver_test.cpp
diff options
context:
space:
mode:
authorGeir Storli <geirst@verizonmedia.com>2020-09-11 11:34:44 +0000
committerTor Brede Vekterli <vekterli@verizonmedia.com>2020-09-14 13:22:15 +0000
commitfb531dcd1963725b657d0412f1ca8ab97352db08 (patch)
tree9176104547d84c923d1a64812686d3dddeb7af6f /storage/src/tests/storageserver/rpc/caching_rpc_target_resolver_test.cpp
parent06a0f822bc6f90e64e6d8510e1b3f5ef3cc037ab (diff)
Decouple CachingRpcTargetResolver from slobrok and fnet implementations and write unit tests.
Diffstat (limited to 'storage/src/tests/storageserver/rpc/caching_rpc_target_resolver_test.cpp')
-rw-r--r--storage/src/tests/storageserver/rpc/caching_rpc_target_resolver_test.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/storage/src/tests/storageserver/rpc/caching_rpc_target_resolver_test.cpp b/storage/src/tests/storageserver/rpc/caching_rpc_target_resolver_test.cpp
new file mode 100644
index 00000000000..bdf0aaee610
--- /dev/null
+++ b/storage/src/tests/storageserver/rpc/caching_rpc_target_resolver_test.cpp
@@ -0,0 +1,134 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/slobrok/imirrorapi.h>
+#include <vespa/storage/storageserver/rpc/caching_rpc_target_resolver.h>
+#include <vespa/storageapi/messageapi/storagemessage.h>
+#include <vespa/vdslib/state/nodetype.h>
+#include <vespa/vespalib/gtest/gtest.h>
+
+using namespace storage::rpc;
+using slobrok::api::IMirrorAPI;
+using storage::api::StorageMessageAddress;
+using storage::lib::NodeType;
+
+class MockMirror : public IMirrorAPI {
+public:
+ using Mappings = std::map<vespalib::string, IMirrorAPI::SpecList>;
+ Mappings mappings;
+ uint32_t gen;
+ MockMirror() : mappings(), gen(1) {}
+ SpecList lookup(const std::string& pattern) const override {
+ auto itr = mappings.find(pattern);
+ if (itr != mappings.end()) {
+ return itr->second;
+ }
+ return {};
+ }
+ uint32_t updates() const override { return gen; }
+ bool ready() const override { return true; }
+ void inc_gen() { ++gen; }
+};
+
+class MockWrappedFrtTarget : public WrappedFrtTarget {
+private:
+ bool& _valid;
+public:
+ MockWrappedFrtTarget(bool& valid) : _valid(valid) {}
+ FRT_Target* get() override { return nullptr; }
+ bool is_valid() const override { return _valid; }
+};
+
+class MockTargetFactory : public RpcTargetFactory {
+public:
+ mutable bool valid_target;
+
+ MockTargetFactory() : valid_target(true) {}
+ std::unique_ptr<RpcTarget> make_target(const vespalib::string& connection_spec, uint32_t slobrok_gen) const override {
+ return std::make_unique<RpcTarget>(std::make_unique<MockWrappedFrtTarget>(valid_target),
+ connection_spec, slobrok_gen);
+ }
+};
+
+class CachingRpcTargetResolverTest : public ::testing::Test {
+public:
+ MockMirror mirror;
+ MockTargetFactory factory;
+ CachingRpcTargetResolver resolver;
+ StorageMessageAddress address_0;
+ StorageMessageAddress address_1;
+ vespalib::string spec_0;
+ vespalib::string spec_1;
+
+ CachingRpcTargetResolverTest()
+ : mirror(),
+ factory(),
+ resolver(mirror, factory),
+ address_0("my_cluster", NodeType::STORAGE, 5),
+ address_1("my_cluster", NodeType::DISTRIBUTOR, 7),
+ spec_0("tcp/my:41"),
+ spec_1("tcp/my:42")
+ {
+ add_mapping(address_0, spec_0);
+ }
+ void add_mapping(const StorageMessageAddress& address, const vespalib::string& connection_spec) {
+ mirror.mappings[to_slobrok_id(address)] = {{to_slobrok_id(address), connection_spec}};
+ }
+ vespalib::string to_slobrok_id(const storage::api::StorageMessageAddress& address) const {
+ return CachingRpcTargetResolver::address_to_slobrok_id(address);
+ }
+};
+
+TEST_F(CachingRpcTargetResolverTest, converts_storage_message_address_to_slobrok_id)
+{
+ EXPECT_EQ("storage/cluster.my_cluster/storage/5", to_slobrok_id(address_0));
+ EXPECT_EQ("storage/cluster.my_cluster/distributor/7", to_slobrok_id(address_1));
+}
+
+TEST_F(CachingRpcTargetResolverTest, resolves_rpc_target_and_caches_result)
+{
+ auto target_a = resolver.resolve_rpc_target(address_0);
+ ASSERT_TRUE(target_a);
+ EXPECT_EQ(spec_0, target_a->_spec);
+ EXPECT_EQ(1, target_a->_slobrok_gen);
+ auto target_b = resolver.resolve_rpc_target(address_0);
+ ASSERT_TRUE(target_b);
+ EXPECT_EQ(target_a.get(), target_b.get());
+ EXPECT_EQ(spec_0, target_b->_spec);
+ EXPECT_EQ(1, target_b->_slobrok_gen);
+}
+
+TEST_F(CachingRpcTargetResolverTest, cached_rpc_target_is_updated_when_slobrok_generation_changes)
+{
+ auto target_a = resolver.resolve_rpc_target(address_0);
+ mirror.inc_gen();
+ auto target_b = resolver.resolve_rpc_target(address_0);
+ EXPECT_EQ(target_a.get(), target_b.get());
+ EXPECT_EQ(2, target_b->_slobrok_gen);
+}
+
+TEST_F(CachingRpcTargetResolverTest, new_rpc_target_is_created_if_connection_spec_changes)
+{
+ auto target_a = resolver.resolve_rpc_target(address_0);
+ add_mapping(address_0, spec_1);
+ mirror.inc_gen();
+ auto target_b = resolver.resolve_rpc_target(address_0);
+ EXPECT_NE(target_a.get(), target_b.get());
+ EXPECT_EQ(spec_1, target_b->_spec);
+ EXPECT_EQ(2, target_b->_slobrok_gen);
+}
+
+TEST_F(CachingRpcTargetResolverTest, new_rpc_target_is_created_if_raw_target_is_invalid)
+{
+ auto target_a = resolver.resolve_rpc_target(address_0);
+ factory.valid_target = false;
+ auto target_b = resolver.resolve_rpc_target(address_0);
+ EXPECT_NE(target_a.get(), target_b.get());
+ EXPECT_EQ(spec_0, target_b->_spec);
+ EXPECT_EQ(1, target_b->_slobrok_gen);
+}
+
+TEST_F(CachingRpcTargetResolverTest, null_rpc_target_is_returned_if_slobrok_id_is_not_found)
+{
+ auto target = resolver.resolve_rpc_target(address_1);
+ EXPECT_FALSE(target);
+}