#include "librados/AioCompletionImpl.h"
#include "librbd/ManagedLock.h"
-#include "test/librados/test.h"
+#include "test/librados/test_cxx.h"
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "test/librados_test_stub/MockTestMemRadosClient.h"
#include "test/librbd/mock/MockImageCtx.h"
managed_lock::Mode mode,
bool blacklist_on_break_lock,
uint32_t blacklist_expire_seconds) {
- assert(s_instance != nullptr);
+ ceph_assert(s_instance != nullptr);
return s_instance;
}
ManagedLock() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
~ManagedLock() {
- assert(s_instance == this);
+ ceph_assert(s_instance == this);
s_instance = nullptr;
}
struct ImageSyncThrottler<librbd::MockTestImageCtx> {
static ImageSyncThrottler* s_instance;
- static ImageSyncThrottler *create() {
- assert(s_instance != nullptr);
+ static ImageSyncThrottler *create(CephContext *cct) {
+ ceph_assert(s_instance != nullptr);
return s_instance;
}
ImageSyncThrottler() {
- assert(s_instance == nullptr);
+ ceph_assert(s_instance == nullptr);
s_instance = this;
}
virtual ~ImageSyncThrottler() {
- assert(s_instance == this);
+ ceph_assert(s_instance == this);
s_instance = nullptr;
}
auto ctx = new FunctionContext(
[instance_watcher, &mock_io_ctx, c, pbl](int r) {
instance_watcher->cancel_notify_requests("other");
- ::encode(librbd::watcher::NotifyResponse(), *pbl);
+ encode(librbd::watcher::NotifyResponse(), *pbl);
mock_io_ctx.get_mock_rados_client()->
finish_aio_completion(c, -ETIMEDOUT);
});
auto ctx = new FunctionContext(
[instance_watcher, &mock_io_ctx, c, pbl](int r) {
instance_watcher->cancel_notify_requests("other");
- ::encode(librbd::watcher::NotifyResponse(), *pbl);
+ encode(librbd::watcher::NotifyResponse(), *pbl);
mock_io_ctx.get_mock_rados_client()->
finish_aio_completion(c, -ETIMEDOUT);
});
delete instance_watcher;
}
+TEST_F(TestMockInstanceWatcher, PeerImageAcquireWatchDNE) {
+ MockManagedLock mock_managed_lock;
+ librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_local_io_ctx));
+
+ MockInstanceReplayer mock_instance_replayer;
+ auto instance_watcher = new MockInstanceWatcher(
+ m_local_io_ctx, m_mock_threads->work_queue, &mock_instance_replayer,
+ m_instance_id);
+ InSequence seq;
+
+ // Init
+ expect_register_instance(mock_io_ctx, 0);
+ expect_register_watch(mock_io_ctx);
+ expect_acquire_lock(mock_managed_lock, 0);
+ ASSERT_EQ(0, instance_watcher->init());
+
+ // Acquire image on dead (blacklisted) instance
+ C_SaferCond on_acquire;
+ instance_watcher->notify_image_acquire("dead instance", "global image id",
+ &on_acquire);
+ ASSERT_EQ(-ENOENT, on_acquire.wait());
+
+ // Shutdown
+ expect_release_lock(mock_managed_lock, 0);
+ expect_unregister_watch(mock_io_ctx);
+ expect_unregister_instance(mock_io_ctx, 0);
+ instance_watcher->shut_down();
+
+ expect_destroy_lock(mock_managed_lock);
+ delete instance_watcher;
+}
+
+TEST_F(TestMockInstanceWatcher, PeerImageReleaseWatchDNE) {
+ MockManagedLock mock_managed_lock;
+ librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_local_io_ctx));
+
+ MockInstanceReplayer mock_instance_replayer;
+ auto instance_watcher = new MockInstanceWatcher(
+ m_local_io_ctx, m_mock_threads->work_queue, &mock_instance_replayer,
+ m_instance_id);
+ InSequence seq;
+
+ // Init
+ expect_register_instance(mock_io_ctx, 0);
+ expect_register_watch(mock_io_ctx);
+ expect_acquire_lock(mock_managed_lock, 0);
+ ASSERT_EQ(0, instance_watcher->init());
+
+ // Release image on dead (blacklisted) instance
+ C_SaferCond on_acquire;
+ instance_watcher->notify_image_release("dead instance", "global image id",
+ &on_acquire);
+ ASSERT_EQ(-ENOENT, on_acquire.wait());
+
+ // Shutdown
+ expect_release_lock(mock_managed_lock, 0);
+ expect_unregister_watch(mock_io_ctx);
+ expect_unregister_instance(mock_io_ctx, 0);
+ instance_watcher->shut_down();
+
+ expect_destroy_lock(mock_managed_lock);
+ delete instance_watcher;
+}
+
TEST_F(TestMockInstanceWatcher, PeerImageRemovedCancel) {
MockManagedLock mock_managed_lock;
librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_local_io_ctx));
auto ctx = new FunctionContext(
[instance_watcher, &mock_io_ctx, c, pbl](int r) {
instance_watcher->cancel_notify_requests("other");
- ::encode(librbd::watcher::NotifyResponse(), *pbl);
+ encode(librbd::watcher::NotifyResponse(), *pbl);
mock_io_ctx.get_mock_rados_client()->
finish_aio_completion(c, -ETIMEDOUT);
});
delete instance_watcher;
}
-
class TestMockInstanceWatcher_NotifySync : public TestMockInstanceWatcher {
public:
typedef ImageSyncThrottler<librbd::MockTestImageCtx> MockImageSyncThrottler;
EXPECT_CALL(mock_image_sync_throttler, start_op(sync_id, _))
.WillOnce(Invoke([on_call, on_start_ctx] (const std::string &,
Context *ctx) {
- if (on_call != nullptr) {
- on_call->complete(0);
- }
if (on_start_ctx != nullptr) {
*on_start_ctx = ctx;
} else {
ctx->complete(0);
}
+ if (on_call != nullptr) {
+ on_call->complete(0);
+ }
}));
}
C_SaferCond on_start_op_called;
Context *on_start_ctx;
- expect_throttler_start_op("sync_id", &on_start_op_called,
- &on_start_ctx);
+ expect_throttler_start_op("sync_id", &on_start_op_called, &on_start_ctx);
C_SaferCond on_start;
instance_watcher1->notify_sync_request("sync_id", &on_start);
ASSERT_EQ(0, on_start_op_called.wait());
std::vector<Context *> throttler_queue = {on_start_ctx};
expect_throttler_destroy(&throttler_queue);
instance_watcher1->handle_release_leader();
+ expect_throttler_start_op("sync_id");
instance_watcher2->handle_acquire_leader();
instance_watcher1->handle_update_leader(instance_id2);
- expect_throttler_start_op("sync_id");
ASSERT_EQ(0, on_start.wait());
C_SaferCond on_finish;
expect_throttler_finish_op("sync_id", &on_finish);
expect_throttler_destroy();
instance_watcher2->handle_release_leader();
instance_watcher1->handle_acquire_leader();
- instance_watcher2->handle_update_leader(instance_id2);
+ instance_watcher2->handle_update_leader(instance_id1);
instance_watcher1->notify_sync_complete("sync_id");
}