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 \
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),
}
}
+ 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,
std::string id;
parent_info parent_md;
+ ceph_file_layout layout;
+
xlist<AsyncRequest<MockImageCtx>*> async_requests;
Cond async_requests_cond;
--- /dev/null
+// -*- 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<MockImageCtx> 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
--- /dev/null
+// -*- 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<MockImageCtx> 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
+
--- /dev/null
+// -*- 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<MockImageCtx> 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
#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 <boost/shared_ptr.hpp>
#include <gmock/gmock.h>
class MockImageCtx;
}
+ACTION_P(CopyInBufferlist, str) {
+ arg0->append(str);
+}
+
ACTION_P2(CompleteContext, r, wq) {
ContextWQ *context_wq = reinterpret_cast<ContextWQ *>(wq);
if (context_wq != NULL) {
wq->queue(arg0, arg1);
}
+ACTION_P3(FinishRequest, request, r, mock) {
+ librbd::MockImageCtx *mock_image_ctx =
+ reinterpret_cast<librbd::MockImageCtx *>(mock);
+ mock_image_ctx->image_ctx->op_work_queue->queue(request->on_finish, r);
+}
+
ACTION_P(GetReference, ref_object) {
ref_object->get();
}