summaryrefslogtreecommitdiffstats
path: root/src/test/rbd_mirror/test_Instances.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/test/rbd_mirror/test_Instances.cc164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/test/rbd_mirror/test_Instances.cc b/src/test/rbd_mirror/test_Instances.cc
new file mode 100644
index 000000000..4b189d903
--- /dev/null
+++ b/src/test/rbd_mirror/test_Instances.cc
@@ -0,0 +1,164 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "include/rados/librados.hpp"
+#include "cls/rbd/cls_rbd_client.h"
+#include "test/rbd_mirror/test_fixture.h"
+#include "tools/rbd_mirror/InstanceWatcher.h"
+#include "tools/rbd_mirror/Instances.h"
+#include "tools/rbd_mirror/Threads.h"
+#include "common/Cond.h"
+
+#include "test/librados/test.h"
+#include "gtest/gtest.h"
+#include <vector>
+
+using rbd::mirror::InstanceWatcher;
+using rbd::mirror::Instances;
+
+void register_test_instances() {
+}
+
+class TestInstances : public ::rbd::mirror::TestFixture {
+public:
+ struct Listener : public rbd::mirror::instances::Listener {
+ std::mutex lock;
+
+ struct Instance {
+ uint32_t count = 0;
+ std::set<std::string> ids;
+ C_SaferCond ctx;
+ };
+
+ Instance add;
+ Instance remove;
+
+ void handle(const InstanceIds& instance_ids, Instance* instance) {
+ std::unique_lock<std::mutex> locker(lock);
+ for (auto& instance_id : instance_ids) {
+ ceph_assert(instance->count > 0);
+ --instance->count;
+
+ instance->ids.insert(instance_id);
+ if (instance->count == 0) {
+ instance->ctx.complete(0);
+ }
+ }
+ }
+
+ void handle_added(const InstanceIds& instance_ids) override {
+ handle(instance_ids, &add);
+ }
+
+ void handle_removed(const InstanceIds& instance_ids) override {
+ handle(instance_ids, &remove);
+ }
+ };
+
+ virtual void SetUp() {
+ TestFixture::SetUp();
+ m_local_io_ctx.remove(RBD_MIRROR_LEADER);
+ EXPECT_EQ(0, m_local_io_ctx.create(RBD_MIRROR_LEADER, true));
+
+ m_instance_id = stringify(m_local_io_ctx.get_instance_id());
+ }
+
+ Listener m_listener;
+ std::string m_instance_id;
+};
+
+TEST_F(TestInstances, InitShutdown)
+{
+ m_listener.add.count = 1;
+ Instances<> instances(m_threads, m_local_io_ctx, m_instance_id, m_listener);
+
+ std::string instance_id = "instance_id";
+ ASSERT_EQ(0, librbd::cls_client::mirror_instances_add(&m_local_io_ctx,
+ instance_id));
+
+ C_SaferCond on_init;
+ instances.init(&on_init);
+ ASSERT_EQ(0, on_init.wait());
+
+ ASSERT_LT(0U, m_listener.add.count);
+ instances.unblock_listener();
+
+ ASSERT_EQ(0, m_listener.add.ctx.wait());
+ ASSERT_EQ(std::set<std::string>({instance_id}), m_listener.add.ids);
+
+ C_SaferCond on_shut_down;
+ instances.shut_down(&on_shut_down);
+ ASSERT_EQ(0, on_shut_down.wait());
+}
+
+TEST_F(TestInstances, InitEnoent)
+{
+ Instances<> instances(m_threads, m_local_io_ctx, m_instance_id, m_listener);
+
+ m_local_io_ctx.remove(RBD_MIRROR_LEADER);
+
+ C_SaferCond on_init;
+ instances.init(&on_init);
+ ASSERT_EQ(0, on_init.wait());
+
+ C_SaferCond on_shut_down;
+ instances.shut_down(&on_shut_down);
+ ASSERT_EQ(0, on_shut_down.wait());
+}
+
+TEST_F(TestInstances, NotifyRemove)
+{
+ // speed testing up a little
+ EXPECT_EQ(0, _rados->conf_set("rbd_mirror_leader_heartbeat_interval", "1"));
+ EXPECT_EQ(0, _rados->conf_set("rbd_mirror_leader_max_missed_heartbeats",
+ "2"));
+ EXPECT_EQ(0, _rados->conf_set("rbd_mirror_leader_max_acquire_attempts_before_break",
+ "0"));
+
+ m_listener.add.count = 2;
+ m_listener.remove.count = 1;
+ Instances<> instances(m_threads, m_local_io_ctx, m_instance_id, m_listener);
+
+ std::string instance_id1 = "instance_id1";
+ std::string instance_id2 = "instance_id2";
+
+ ASSERT_EQ(0, librbd::cls_client::mirror_instances_add(&m_local_io_ctx,
+ instance_id1));
+
+ C_SaferCond on_init;
+ instances.init(&on_init);
+ ASSERT_EQ(0, on_init.wait());
+
+ instances.acked({instance_id2});
+
+ ASSERT_LT(0U, m_listener.add.count);
+ instances.unblock_listener();
+
+ ASSERT_EQ(0, m_listener.add.ctx.wait());
+ ASSERT_EQ(std::set<std::string>({instance_id1, instance_id2}),
+ m_listener.add.ids);
+
+ std::vector<std::string> instance_ids;
+ for (int i = 0; i < 100; i++) {
+ instances.acked({instance_id1});
+ if (m_listener.remove.count > 0) {
+ usleep(250000);
+ }
+ }
+
+ instances.acked({instance_id1});
+ ASSERT_EQ(0, m_listener.remove.ctx.wait());
+ ASSERT_EQ(std::set<std::string>({instance_id2}),
+ m_listener.remove.ids);
+
+ C_SaferCond on_get;
+ instances.acked({instance_id1});
+ InstanceWatcher<>::get_instances(m_local_io_ctx, &instance_ids, &on_get);
+ EXPECT_EQ(0, on_get.wait());
+ EXPECT_EQ(1U, instance_ids.size());
+ ASSERT_EQ(instance_ids[0], instance_id1);
+
+ C_SaferCond on_shut_down;
+ instances.shut_down(&on_shut_down);
+ ASSERT_EQ(0, on_shut_down.wait());
+}