From: Jason Dillaman Date: Sat, 5 Dec 2015 02:45:24 +0000 (-0500) Subject: tests: mock test cases for new async object map lock/unlock/refresh ops X-Git-Tag: v10.0.2~35^2~19 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=19127742ac5f004e6393702aafb763bcc5ed183d;p=ceph.git tests: mock test cases for new async object map lock/unlock/refresh ops Signed-off-by: Jason Dillaman --- diff --git a/src/test/Makefile-client.am b/src/test/Makefile-client.am index 533e81beebbe..07efa48a5d85 100644 --- a/src/test/Makefile-client.am +++ b/src/test/Makefile-client.am @@ -354,10 +354,13 @@ unittest_librbd_SOURCES = \ test/librbd/test_main.cc \ test/librbd/test_mock_fixture.cc \ test/librbd/object_map/test_mock_InvalidateRequest.cc \ + test/librbd/object_map/test_mock_LockRequest.cc \ + test/librbd/object_map/test_mock_RefreshRequest.cc \ test/librbd/object_map/test_mock_ResizeRequest.cc \ test/librbd/object_map/test_mock_SnapshotCreateRequest.cc \ test/librbd/object_map/test_mock_SnapshotRemoveRequest.cc \ test/librbd/object_map/test_mock_SnapshotRollbackRequest.cc \ + test/librbd/object_map/test_mock_UnlockRequest.cc \ test/librbd/object_map/test_mock_UpdateRequest.cc \ test/librbd/operation/test_mock_SnapshotCreateRequest.cc \ test/librbd/operation/test_mock_SnapshotProtectRequest.cc \ diff --git a/src/test/librbd/mock/MockImageCtx.h b/src/test/librbd/mock/MockImageCtx.h index 1e70b1f27cfc..3633a5256f0c 100644 --- a/src/test/librbd/mock/MockImageCtx.h +++ b/src/test/librbd/mock/MockImageCtx.h @@ -35,6 +35,7 @@ struct MockImageCtx { header_oid(image_ctx.header_oid), id(image_ctx.id), parent_md(image_ctx.parent_md), + layout(image_ctx.layout), aio_work_queue(new MockAioImageRequestWQ()), op_work_queue(new MockContextWQ()), image_watcher(NULL), journal(NULL), @@ -62,6 +63,7 @@ struct MockImageCtx { } } + MOCK_CONST_METHOD1(get_image_size, uint64_t(librados::snap_t)); MOCK_CONST_METHOD1(get_snap_id, librados::snap_t(std::string in_snap_name)); MOCK_CONST_METHOD1(get_snap_info, const SnapInfo*(librados::snap_t)); MOCK_CONST_METHOD2(get_parent_spec, int(librados::snap_t in_snap_id, @@ -105,6 +107,8 @@ struct MockImageCtx { std::string id; parent_info parent_md; + ceph_file_layout layout; + xlist*> async_requests; Cond async_requests_cond; diff --git a/src/test/librbd/object_map/test_mock_LockRequest.cc b/src/test/librbd/object_map/test_mock_LockRequest.cc new file mode 100644 index 000000000000..e7a62fd3c663 --- /dev/null +++ b/src/test/librbd/object_map/test_mock_LockRequest.cc @@ -0,0 +1,215 @@ +// -*- 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 "test/librbd/test_support.h" +#include "test/librbd/mock/MockImageCtx.h" +#include "test/librados_test_stub/MockTestMemIoCtxImpl.h" +#include "cls/lock/cls_lock_ops.h" +#include "librbd/ObjectMap.h" +#include "librbd/object_map/LockRequest.h" + +// template definitions +#include "librbd/object_map/LockRequest.cc" + +namespace librbd { +namespace object_map { + +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Return; +using ::testing::WithArg; + +class TestMockObjectMapLockRequest : public TestMockFixture { +public: + typedef LockRequest MockLockRequest; + + void expect_lock(MockImageCtx &mock_image_ctx, int r) { + std::string oid(ObjectMap::object_map_name(mock_image_ctx.id, CEPH_NOSNAP)); + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(oid, _, "lock", "lock", _, _, _)) + .WillOnce(Return(r)); + } + + void expect_get_lock_info(MockImageCtx &mock_image_ctx, int r) { + std::string oid(ObjectMap::object_map_name(mock_image_ctx.id, CEPH_NOSNAP)); + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(oid, _, "lock", "get_info", _, _, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + entity_name_t entity1(entity_name_t::CLIENT(1)); + entity_name_t entity2(entity_name_t::CLIENT(2)); + + cls_lock_get_info_reply reply; + reply.lockers = decltype(reply.lockers){ + {rados::cls::lock::locker_id_t(entity1, "cookie1"), + rados::cls::lock::locker_info_t()}, + {rados::cls::lock::locker_id_t(entity2, "cookie2"), + rados::cls::lock::locker_info_t()}}; + + bufferlist bl; + ::encode(reply, bl); + + std::string str(bl.c_str(), bl.length()); + expect.WillOnce(DoAll(WithArg<5>(CopyInBufferlist(str)), Return(r))); + } + } + + void expect_break_lock(MockImageCtx &mock_image_ctx, int r) { + std::string oid(ObjectMap::object_map_name(mock_image_ctx.id, CEPH_NOSNAP)); + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(oid, _, "lock", "break_lock", _, _, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.Times(2).WillRepeatedly(Return(0)); + } + } +}; + +TEST_F(TestMockObjectMapLockRequest, Success) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_lock(mock_image_ctx, 0); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockObjectMapLockRequest, LockBusy) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_lock(mock_image_ctx, -EBUSY); + expect_get_lock_info(mock_image_ctx, 0); + expect_break_lock(mock_image_ctx, 0); + expect_lock(mock_image_ctx, 0); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockObjectMapLockRequest, LockError) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_lock(mock_image_ctx, -ENOENT); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockObjectMapLockRequest, GetLockInfoMissing) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_lock(mock_image_ctx, -EBUSY); + expect_get_lock_info(mock_image_ctx, -ENOENT); + expect_lock(mock_image_ctx, 0); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockObjectMapLockRequest, GetLockInfoError) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_lock(mock_image_ctx, -EBUSY); + expect_get_lock_info(mock_image_ctx, -EINVAL); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockObjectMapLockRequest, BreakLockMissing) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_lock(mock_image_ctx, -EBUSY); + expect_get_lock_info(mock_image_ctx, 0); + expect_break_lock(mock_image_ctx, -ENOENT); + expect_lock(mock_image_ctx, 0); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockObjectMapLockRequest, BreakLockError) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_lock(mock_image_ctx, -EBUSY); + expect_get_lock_info(mock_image_ctx, 0); + expect_break_lock(mock_image_ctx, -EINVAL); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockObjectMapLockRequest, LockErrorAfterBrokeLock) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockLockRequest *req = new MockLockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_lock(mock_image_ctx, -EBUSY); + expect_get_lock_info(mock_image_ctx, 0); + expect_break_lock(mock_image_ctx, 0); + expect_lock(mock_image_ctx, -EBUSY); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +} // namespace object_map +} // namespace librbd diff --git a/src/test/librbd/object_map/test_mock_RefreshRequest.cc b/src/test/librbd/object_map/test_mock_RefreshRequest.cc new file mode 100644 index 000000000000..043ad351f0e5 --- /dev/null +++ b/src/test/librbd/object_map/test_mock_RefreshRequest.cc @@ -0,0 +1,291 @@ +// -*- 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 "test/librbd/test_support.h" +#include "test/librbd/mock/MockImageCtx.h" +#include "test/librbd/object_map/mock/MockInvalidateRequest.h" +#include "test/librados_test_stub/MockTestMemIoCtxImpl.h" +#include "common/bit_vector.hpp" +#include "librbd/ObjectMap.h" +#include "librbd/object_map/RefreshRequest.h" + +// template definitions +#include "librbd/object_map/RefreshRequest.cc" + +namespace librbd { +namespace object_map { + +using ::testing::_; +using ::testing::DoAll; +using ::testing::DoDefault; +using ::testing::InSequence; +using ::testing::Return; +using ::testing::WithArg; + +class TestMockObjectMapRefreshRequest : public TestMockFixture { +public: + static const uint64_t TEST_SNAP_ID = 123; + + typedef RefreshRequest MockRefreshRequest; + + void expect_object_map_load(MockImageCtx &mock_image_ctx, + ceph::BitVector<2> *object_map, int r) { + std::string oid(ObjectMap::object_map_name(mock_image_ctx.id, TEST_SNAP_ID)); + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(oid, _, "rbd", "object_map_load", _, _, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + assert(object_map); + object_map->set_crc_enabled(false); + + bufferlist bl; + ::encode(*object_map, bl); + + std::string str(bl.c_str(), bl.length()); + expect.WillOnce(DoAll(WithArg<5>(CopyInBufferlist(str)), Return(0))); + } + } + + void expect_get_image_size(MockImageCtx &mock_image_ctx, uint64_t size) { + EXPECT_CALL(mock_image_ctx, get_image_size(TEST_SNAP_ID)) + .WillOnce(Return(size)); + } + + void expect_invalidate_request(MockImageCtx &mock_image_ctx, + MockInvalidateRequest &invalidate_request) { + EXPECT_CALL(invalidate_request, send()) + .WillOnce(FinishRequest(&invalidate_request, 0, + &mock_image_ctx)); + } + + void expect_truncate_request(MockImageCtx &mock_image_ctx) { + std::string oid(ObjectMap::object_map_name(mock_image_ctx.id, TEST_SNAP_ID)); + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), truncate(oid, 0, _)) + .WillOnce(Return(0)); + } + + void expect_object_map_resize(MockImageCtx &mock_image_ctx, + uint64_t num_objects, int r) { + std::string oid(ObjectMap::object_map_name(mock_image_ctx.id, TEST_SNAP_ID)); + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(oid, _, "rbd", "object_map_resize", _, _, _)); + expect.WillOnce(Return(r)); + } + + void init_object_map(MockImageCtx &mock_image_ctx, + ceph::BitVector<2> *object_map) { + uint64_t num_objs = Striper::get_num_objects( + mock_image_ctx.layout, mock_image_ctx.image_ctx->size); + object_map->resize(num_objs); + for (uint64_t i = 0; i < num_objs; ++i) { + (*object_map)[i] = rand() % 3; + } + } + + void when_apply_refresh_request(MockImageCtx &mock_image_ctx, + MockRefreshRequest *req) { + RWLock::WLocker snap_locker(mock_image_ctx.snap_lock); + RWLock::WLocker object_map_locker(mock_image_ctx.object_map_lock); + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); + req->apply(); + } +}; + +TEST_F(TestMockObjectMapRefreshRequest, Success) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + ceph::BitVector<2> on_disk_object_map; + init_object_map(mock_image_ctx, &on_disk_object_map); + + C_SaferCond ctx; + ceph::BitVector<2> object_map; + MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, + TEST_SNAP_ID, &ctx); + + InSequence seq; + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); + expect_object_map_load(mock_image_ctx, &on_disk_object_map, 0); + req->send(); + ASSERT_EQ(0, ctx.wait()); + + when_apply_refresh_request(mock_image_ctx, req); + ASSERT_EQ(on_disk_object_map, object_map); +} + +TEST_F(TestMockObjectMapRefreshRequest, LoadError) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + ceph::BitVector<2> on_disk_object_map; + init_object_map(mock_image_ctx, &on_disk_object_map); + + C_SaferCond ctx; + ceph::BitVector<2> object_map; + MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, + TEST_SNAP_ID, &ctx); + + InSequence seq; + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); + expect_object_map_load(mock_image_ctx, nullptr, -ENOENT); + + MockInvalidateRequest invalidate_request; + expect_invalidate_request(mock_image_ctx, invalidate_request); + + req->send(); + ASSERT_EQ(0, ctx.wait()); + + when_apply_refresh_request(mock_image_ctx, req); +} + +TEST_F(TestMockObjectMapRefreshRequest, LoadCorrupt) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + ceph::BitVector<2> on_disk_object_map; + init_object_map(mock_image_ctx, &on_disk_object_map); + + C_SaferCond ctx; + ceph::BitVector<2> object_map; + MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, + TEST_SNAP_ID, &ctx); + + InSequence seq; + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); + expect_object_map_load(mock_image_ctx, nullptr, -EINVAL); + + MockInvalidateRequest invalidate_request; + expect_invalidate_request(mock_image_ctx, invalidate_request); + expect_truncate_request(mock_image_ctx); + expect_object_map_resize(mock_image_ctx, on_disk_object_map.size(), 0); + + req->send(); + ASSERT_EQ(0, ctx.wait()); + + when_apply_refresh_request(mock_image_ctx, req); +} + +TEST_F(TestMockObjectMapRefreshRequest, TooSmall) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + ceph::BitVector<2> on_disk_object_map; + init_object_map(mock_image_ctx, &on_disk_object_map); + + ceph::BitVector<2> small_object_map; + + C_SaferCond ctx; + ceph::BitVector<2> object_map; + MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, + TEST_SNAP_ID, &ctx); + + InSequence seq; + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); + expect_object_map_load(mock_image_ctx, &small_object_map, 0); + + MockInvalidateRequest invalidate_request; + expect_invalidate_request(mock_image_ctx, invalidate_request); + expect_object_map_resize(mock_image_ctx, on_disk_object_map.size(), 0); + + req->send(); + ASSERT_EQ(0, ctx.wait()); + + when_apply_refresh_request(mock_image_ctx, req); +} + +TEST_F(TestMockObjectMapRefreshRequest, TooLarge) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + ceph::BitVector<2> on_disk_object_map; + init_object_map(mock_image_ctx, &on_disk_object_map); + + ceph::BitVector<2> large_object_map; + large_object_map.resize(on_disk_object_map.size() * 2); + + C_SaferCond ctx; + ceph::BitVector<2> object_map; + MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, + TEST_SNAP_ID, &ctx); + + InSequence seq; + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); + expect_object_map_load(mock_image_ctx, &large_object_map, 0); + req->send(); + ASSERT_EQ(0, ctx.wait()); + + when_apply_refresh_request(mock_image_ctx, req); +} + +TEST_F(TestMockObjectMapRefreshRequest, ResizeError) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + ceph::BitVector<2> on_disk_object_map; + init_object_map(mock_image_ctx, &on_disk_object_map); + + ceph::BitVector<2> small_object_map; + + C_SaferCond ctx; + ceph::BitVector<2> object_map; + MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, + TEST_SNAP_ID, &ctx); + + InSequence seq; + expect_get_image_size(mock_image_ctx, mock_image_ctx.image_ctx->size); + expect_object_map_load(mock_image_ctx, &small_object_map, 0); + + MockInvalidateRequest invalidate_request; + expect_invalidate_request(mock_image_ctx, invalidate_request); + expect_object_map_resize(mock_image_ctx, on_disk_object_map.size(), -ESTALE); + + req->send(); + ASSERT_EQ(0, ctx.wait()); + + when_apply_refresh_request(mock_image_ctx, req); +} + +TEST_F(TestMockObjectMapRefreshRequest, StaleRefresh) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + ceph::BitVector<2> object_map; + MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, + TEST_SNAP_ID, &ctx); + ASSERT_THROW(when_apply_refresh_request(mock_image_ctx, req), + ceph::FailedAssertion); +} + +TEST_F(TestMockObjectMapRefreshRequest, Discard) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + ceph::BitVector<2> object_map; + MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, &object_map, + TEST_SNAP_ID, &ctx); + req->discard(); +} + +} // namespace object_map +} // namespace librbd + diff --git a/src/test/librbd/object_map/test_mock_UnlockRequest.cc b/src/test/librbd/object_map/test_mock_UnlockRequest.cc new file mode 100644 index 000000000000..4cd2db46cc92 --- /dev/null +++ b/src/test/librbd/object_map/test_mock_UnlockRequest.cc @@ -0,0 +1,67 @@ +// -*- 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 "test/librbd/test_support.h" +#include "test/librbd/mock/MockImageCtx.h" +#include "test/librados_test_stub/MockTestMemIoCtxImpl.h" +#include "cls/lock/cls_lock_ops.h" +#include "librbd/ObjectMap.h" +#include "librbd/object_map/UnlockRequest.h" + +// template definitions +#include "librbd/object_map/UnlockRequest.cc" + +namespace librbd { +namespace object_map { + +using ::testing::_; +using ::testing::InSequence; +using ::testing::Return; + +class TestMockObjectMapUnlockRequest : public TestMockFixture { +public: + typedef UnlockRequest MockUnlockRequest; + + void expect_unlock(MockImageCtx &mock_image_ctx, int r) { + std::string oid(ObjectMap::object_map_name(mock_image_ctx.id, CEPH_NOSNAP)); + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), + exec(oid, _, "lock", "unlock", _, _, _)) + .WillOnce(Return(r)); + } +}; + +TEST_F(TestMockObjectMapUnlockRequest, Success) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockUnlockRequest *req = new MockUnlockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_unlock(mock_image_ctx, 0); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockObjectMapUnlockRequest, UnlockError) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + C_SaferCond ctx; + MockUnlockRequest *req = new MockUnlockRequest(mock_image_ctx, &ctx); + + InSequence seq; + expect_unlock(mock_image_ctx, -ENOENT); + req->send(); + + ASSERT_EQ(0, ctx.wait()); +} + +} // namespace object_map +} // namespace librbd diff --git a/src/test/librbd/test_mock_fixture.h b/src/test/librbd/test_mock_fixture.h index 150e312f259b..320fd1a76aa8 100644 --- a/src/test/librbd/test_mock_fixture.h +++ b/src/test/librbd/test_mock_fixture.h @@ -5,6 +5,7 @@ #define CEPH_TEST_LIBRBD_TEST_MOCK_FIXTURE_H #include "test/librbd/test_fixture.h" +#include "test/librbd/mock/MockImageCtx.h" #include "common/WorkQueue.h" #include #include @@ -18,6 +19,10 @@ namespace librbd { class MockImageCtx; } +ACTION_P(CopyInBufferlist, str) { + arg0->append(str); +} + ACTION_P2(CompleteContext, r, wq) { ContextWQ *context_wq = reinterpret_cast(wq); if (context_wq != NULL) { @@ -31,6 +36,12 @@ ACTION_P(DispatchContext, wq) { wq->queue(arg0, arg1); } +ACTION_P3(FinishRequest, request, r, mock) { + librbd::MockImageCtx *mock_image_ctx = + reinterpret_cast(mock); + mock_image_ctx->image_ctx->op_work_queue->queue(request->on_finish, r); +} + ACTION_P(GetReference, ref_object) { ref_object->get(); }