summaryrefslogtreecommitdiffstats
path: root/src/test/librbd/watcher
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/librbd/watcher')
-rw-r--r--src/test/librbd/watcher/test_mock_RewatchRequest.cc227
1 files changed, 227 insertions, 0 deletions
diff --git a/src/test/librbd/watcher/test_mock_RewatchRequest.cc b/src/test/librbd/watcher/test_mock_RewatchRequest.cc
new file mode 100644
index 000000000..9e7c5e023
--- /dev/null
+++ b/src/test/librbd/watcher/test_mock_RewatchRequest.cc
@@ -0,0 +1,227 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/librbd/test_mock_fixture.h"
+#include "include/rados/librados.hpp"
+#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
+#include "test/librados_test_stub/MockTestMemRadosClient.h"
+#include "test/librbd/test_support.h"
+#include "test/librbd/mock/MockImageCtx.h"
+#include "librados/AioCompletionImpl.h"
+#include "librbd/watcher/RewatchRequest.h"
+
+namespace librbd {
+namespace watcher {
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::WithArg;
+using ::testing::WithArgs;
+
+struct TestMockWatcherRewatchRequest : public TestMockFixture {
+ typedef RewatchRequest MockRewatchRequest;
+
+ TestMockWatcherRewatchRequest() = default;
+
+ void expect_aio_watch(MockImageCtx &mock_image_ctx, int r) {
+ librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(
+ mock_image_ctx.md_ctx));
+
+ EXPECT_CALL(mock_io_ctx, aio_watch(mock_image_ctx.header_oid, _, _, _))
+ .WillOnce(DoAll(WithArgs<1, 2>(Invoke([&mock_image_ctx, &mock_io_ctx, r](librados::AioCompletionImpl *c, uint64_t *cookie) {
+ *cookie = 234;
+ c->get();
+ mock_image_ctx.image_ctx->op_work_queue->queue(new LambdaContext([&mock_io_ctx, c](int r) {
+ mock_io_ctx.get_mock_rados_client()->finish_aio_completion(c, r);
+ }), r);
+ })),
+ Return(0)));
+ }
+
+ void expect_aio_unwatch(MockImageCtx &mock_image_ctx, int r) {
+ librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(
+ mock_image_ctx.md_ctx));
+
+ EXPECT_CALL(mock_io_ctx, aio_unwatch(m_watch_handle, _))
+ .WillOnce(DoAll(Invoke([&mock_image_ctx, &mock_io_ctx, r](uint64_t handle,
+ librados::AioCompletionImpl *c) {
+ c->get();
+ mock_image_ctx.image_ctx->op_work_queue->queue(new LambdaContext([&mock_io_ctx, c](int r) {
+ mock_io_ctx.get_mock_rados_client()->finish_aio_completion(c, r);
+ }), r);
+ }),
+ Return(0)));
+ }
+
+ struct WatchCtx : public librados::WatchCtx2 {
+ void handle_notify(uint64_t, uint64_t, uint64_t,
+ ceph::bufferlist&) override {
+ ceph_abort();
+ }
+ void handle_error(uint64_t, int) override {
+ ceph_abort();
+ }
+ };
+
+ ceph::shared_mutex m_watch_lock = ceph::make_shared_mutex("watch_lock");
+ WatchCtx m_watch_ctx;
+ uint64_t m_watch_handle = 123;
+};
+
+TEST_F(TestMockWatcherRewatchRequest, Success) {
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+
+ InSequence seq;
+ expect_aio_unwatch(mock_image_ctx, 0);
+ expect_aio_watch(mock_image_ctx, 0);
+
+ C_SaferCond ctx;
+ MockRewatchRequest *req = MockRewatchRequest::create(mock_image_ctx.md_ctx,
+ mock_image_ctx.header_oid,
+ m_watch_lock,
+ &m_watch_ctx,
+ &m_watch_handle,
+ &ctx);
+ {
+ std::unique_lock watch_locker{m_watch_lock};
+ req->send();
+ }
+ ASSERT_EQ(0, ctx.wait());
+ ASSERT_EQ(234U, m_watch_handle);
+}
+
+TEST_F(TestMockWatcherRewatchRequest, UnwatchError) {
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+
+ InSequence seq;
+ expect_aio_unwatch(mock_image_ctx, -EINVAL);
+ expect_aio_watch(mock_image_ctx, 0);
+
+ C_SaferCond ctx;
+ MockRewatchRequest *req = MockRewatchRequest::create(mock_image_ctx.md_ctx,
+ mock_image_ctx.header_oid,
+ m_watch_lock,
+ &m_watch_ctx,
+ &m_watch_handle,
+ &ctx);
+ {
+ std::unique_lock watch_locker{m_watch_lock};
+ req->send();
+ }
+ ASSERT_EQ(0, ctx.wait());
+ ASSERT_EQ(234U, m_watch_handle);
+}
+
+TEST_F(TestMockWatcherRewatchRequest, WatchBlocklist) {
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+
+ InSequence seq;
+ expect_aio_unwatch(mock_image_ctx, 0);
+ expect_aio_watch(mock_image_ctx, -EBLOCKLISTED);
+
+ C_SaferCond ctx;
+ MockRewatchRequest *req = MockRewatchRequest::create(mock_image_ctx.md_ctx,
+ mock_image_ctx.header_oid,
+ m_watch_lock,
+ &m_watch_ctx,
+ &m_watch_handle,
+ &ctx);
+ {
+ std::unique_lock watch_locker{m_watch_lock};
+ req->send();
+ }
+ ASSERT_EQ(-EBLOCKLISTED, ctx.wait());
+ ASSERT_EQ(0U, m_watch_handle);
+}
+
+TEST_F(TestMockWatcherRewatchRequest, WatchDNE) {
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+
+ InSequence seq;
+ expect_aio_unwatch(mock_image_ctx, 0);
+ expect_aio_watch(mock_image_ctx, -ENOENT);
+
+ C_SaferCond ctx;
+ MockRewatchRequest *req = MockRewatchRequest::create(mock_image_ctx.md_ctx,
+ mock_image_ctx.header_oid,
+ m_watch_lock,
+ &m_watch_ctx,
+ &m_watch_handle,
+ &ctx);
+ {
+ std::unique_lock watch_locker{m_watch_lock};
+ req->send();
+ }
+ ASSERT_EQ(-ENOENT, ctx.wait());
+ ASSERT_EQ(0U, m_watch_handle);
+}
+
+TEST_F(TestMockWatcherRewatchRequest, WatchError) {
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+
+ InSequence seq;
+ expect_aio_unwatch(mock_image_ctx, 0);
+ expect_aio_watch(mock_image_ctx, -EINVAL);
+
+ C_SaferCond ctx;
+ MockRewatchRequest *req = MockRewatchRequest::create(mock_image_ctx.md_ctx,
+ mock_image_ctx.header_oid,
+ m_watch_lock,
+ &m_watch_ctx,
+ &m_watch_handle,
+ &ctx);
+ {
+ std::unique_lock watch_locker{m_watch_lock};
+ req->send();
+ }
+ ASSERT_EQ(-EINVAL, ctx.wait());
+ ASSERT_EQ(0U, m_watch_handle);
+}
+
+TEST_F(TestMockWatcherRewatchRequest, InvalidWatchHandler) {
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockImageCtx mock_image_ctx(*ictx);
+
+ InSequence seq;
+ expect_aio_watch(mock_image_ctx, 0);
+
+ m_watch_handle = 0;
+
+ C_SaferCond ctx;
+ MockRewatchRequest *req = MockRewatchRequest::create(mock_image_ctx.md_ctx,
+ mock_image_ctx.header_oid,
+ m_watch_lock,
+ &m_watch_ctx,
+ &m_watch_handle,
+ &ctx);
+ {
+ std::unique_lock watch_locker{m_watch_lock};
+ req->send();
+ }
+
+ ASSERT_EQ(0, ctx.wait());
+ ASSERT_EQ(234U, m_watch_handle);
+}
+
+} // namespace watcher
+} // namespace librbd