From: Jason Dillaman Date: Sun, 6 Mar 2016 18:09:38 +0000 (-0500) Subject: test: unit test cases for rbd::mirror::image_sync::ObjectCopyRequest X-Git-Tag: v10.1.0~104^2~19 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=dd4f6a92aeea7f150333f1dea35a294f11cd7aa2;p=ceph.git test: unit test cases for rbd::mirror::image_sync::ObjectCopyRequest Signed-off-by: Jason Dillaman --- diff --git a/src/test/Makefile-client.am b/src/test/Makefile-client.am index 3edca402abda..e18c4ec923fe 100644 --- a/src/test/Makefile-client.am +++ b/src/test/Makefile-client.am @@ -441,12 +441,20 @@ noinst_HEADERS += \ librbd_mirror_test_la_SOURCES = \ test/rbd_mirror/test_ClusterWatcher.cc \ test/rbd_mirror/test_PoolWatcher.cc \ - test/rbd_mirror/test_ImageReplayer.cc + test/rbd_mirror/test_ImageReplayer.cc \ + test/rbd_mirror/test_fixture.cc \ + test/rbd_mirror/test_mock_fixture.cc + +noinst_HEADERS += \ + test/rbd_mirror/test_fixture.h \ + test/rbd_mirror/test_mock_fixture.h + librbd_mirror_test_la_CXXFLAGS = $(UNITTEST_CXXFLAGS) noinst_LTLIBRARIES += librbd_mirror_test.la unittest_rbd_mirror_SOURCES = \ - test/rbd_mirror/test_main.cc + test/rbd_mirror/test_main.cc \ + test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc unittest_rbd_mirror_CXXFLAGS = $(UNITTEST_CXXFLAGS) unittest_rbd_mirror_LDADD = \ librbd_mirror_test.la \ diff --git a/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc new file mode 100644 index 000000000000..14997b48a592 --- /dev/null +++ b/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc @@ -0,0 +1,459 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "test/rbd_mirror/test_mock_fixture.h" +#include "include/interval_set.h" +#include "include/rbd/librbd.hpp" +#include "librbd/ImageCtx.h" +#include "librbd/ImageState.h" +#include "librbd/Operations.h" +#include "test/librados_test_stub/MockTestMemIoCtxImpl.h" +#include "test/librbd/mock/MockImageCtx.h" +#include "tools/rbd_mirror/image_sync/ObjectCopyRequest.h" + +// template definitions +#include "tools/rbd_mirror/image_sync/ObjectCopyRequest.cc" +template class rbd::mirror::image_sync::ObjectCopyRequest; + +namespace rbd { +namespace mirror { +namespace image_sync { + +using ::testing::_; +using ::testing::DoDefault; +using ::testing::InSequence; +using ::testing::Return; + +namespace { + +void scribble(librados::IoCtx &io_ctx, const std::string &oid, int num_ops, + size_t max_size, interval_set *what) +{ + uint64_t object_size = 1 << 22; + librados::ObjectWriteOperation op; + for (int i=0; i w; + w.insert(off, len); + what->union_of(w); + } + + ASSERT_EQ(0, io_ctx.operate(oid, &op)); + std::cout << " wrote " << *what << std::endl; +} + +} // anonymous namespace + +class TestMockImageSyncObjectCopyRequest : public TestMockFixture { +public: + typedef ObjectCopyRequest MockObjectCopyRequest; + + virtual void SetUp() { + TestMockFixture::SetUp(); + + librbd::RBD rbd; + ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size)); + ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx)); + + ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size)); + ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx)); + } + + void expect_list_snaps(librbd::MockImageCtx &mock_image_ctx, + librados::MockTestMemIoCtxImpl &mock_io_ctx, int r) { + auto &expect = EXPECT_CALL(mock_io_ctx, + list_snaps(mock_image_ctx.image_ctx->get_object_name(0), + _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_get_object_name(librbd::MockImageCtx &mock_image_ctx) { + EXPECT_CALL(mock_image_ctx, get_object_name(0)) + .WillOnce(Return(mock_image_ctx.image_ctx->get_object_name(0))); + } + + MockObjectCopyRequest *create_request(librbd::MockImageCtx &mock_remote_image_ctx, + librbd::MockImageCtx &mock_local_image_ctx, + Context *on_finish) { + expect_get_object_name(mock_local_image_ctx); + expect_get_object_name(mock_remote_image_ctx); + return new MockObjectCopyRequest(&mock_local_image_ctx, + &mock_remote_image_ctx, &m_snap_map, + 0, on_finish); + } + + void expect_read(librados::MockTestMemIoCtxImpl &mock_io_ctx, uint64_t offset, + uint64_t length, int r) { + auto &expect = EXPECT_CALL(mock_io_ctx, read(_, length, offset, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_read(librados::MockTestMemIoCtxImpl &mock_io_ctx, + const interval_set &extents, int r) { + for (auto extent : extents) { + expect_read(mock_io_ctx, extent.first, extent.second, r); + if (r < 0) { + break; + } + } + } + + void expect_write(librados::MockTestMemIoCtxImpl &mock_io_ctx, + uint64_t offset, uint64_t length, int r) { + auto &expect = EXPECT_CALL(mock_io_ctx, write(_, _, length, offset, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_write(librados::MockTestMemIoCtxImpl &mock_io_ctx, + const interval_set &extents, int r) { + for (auto extent : extents) { + expect_write(mock_io_ctx, extent.first, extent.second, r); + if (r < 0) { + break; + } + } + } + + void expect_truncate(librados::MockTestMemIoCtxImpl &mock_io_ctx, + uint64_t offset, int r) { + auto &expect = EXPECT_CALL(mock_io_ctx, truncate(_, offset, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_remove(librados::MockTestMemIoCtxImpl &mock_io_ctx, int r) { + auto &expect = EXPECT_CALL(mock_io_ctx, remove(_, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + int create_snap(librbd::ImageCtx *image_ctx, const char* snap_name, + librados::snap_t *snap_id) { + int r = image_ctx->operations->snap_create(snap_name); + if (r < 0) { + return r; + } + + r = image_ctx->state->refresh(); + if (r < 0) { + return r; + } + + if (image_ctx->snap_ids.count(snap_name) == 0) { + return -ENOENT; + } + *snap_id = image_ctx->snap_ids[snap_name]; + return 0; + } + + int create_snap(const char* snap_name) { + librados::snap_t remote_snap_id; + int r = create_snap(m_remote_image_ctx, snap_name, &remote_snap_id); + if (r < 0) { + return r; + } + + librados::snap_t local_snap_id; + r = create_snap(m_local_image_ctx, snap_name, &local_snap_id); + if (r < 0) { + return r; + } + + // collection of all existing snaps in local image + MockObjectCopyRequest::SnapIds local_snap_ids({local_snap_id}); + if (!m_snap_map.empty()) { + local_snap_ids.insert(local_snap_ids.end(), + m_snap_map.rbegin()->second.begin(), + m_snap_map.rbegin()->second.end()); + } + m_snap_map[remote_snap_id] = local_snap_ids; + return 0; + } + + int compare_objects() { + MockObjectCopyRequest::SnapMap snap_map(m_snap_map); + if (snap_map.empty()) { + return -ENOENT; + } + + std::string remote_oid(m_remote_image_ctx->get_object_name(0)); + std::string local_oid(m_local_image_ctx->get_object_name(0)); + + librados::IoCtx remote_io_ctx; + remote_io_ctx.dup(m_remote_image_ctx->data_ctx); + + librados::IoCtx local_io_ctx; + local_io_ctx.dup(m_local_image_ctx->data_ctx); + + while (!snap_map.empty()) { + librados::snap_t remote_snap_id = snap_map.begin()->first; + librados::snap_t local_snap_id = *snap_map.begin()->second.begin(); + snap_map.erase(snap_map.begin()); + std::cout << "comparing " << remote_snap_id << " to " << local_snap_id + << std::endl; + + remote_io_ctx.snap_set_read(remote_snap_id); + bufferlist remote_bl; + int remote_r = remote_io_ctx.read(remote_oid, remote_bl, 1<<22, 0); + + local_io_ctx.snap_set_read(local_snap_id); + bufferlist local_bl; + int local_r = local_io_ctx.read(local_oid, local_bl, 1<<22, 0); + + if (remote_r != local_r) { + return remote_r < 0 ? remote_r : local_r; + } + + if (!remote_bl.contents_equal(local_bl)) { + return -EBADMSG; + } + } + return 0; + } + + librbd::ImageCtx *m_remote_image_ctx; + librbd::ImageCtx *m_local_image_ctx; + + MockObjectCopyRequest::SnapMap m_snap_map; + +}; + +TEST_F(TestMockImageSyncObjectCopyRequest, DNE) { + ASSERT_EQ(0, create_snap("sync")); + librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + C_SaferCond ctx; + MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, + mock_local_image_ctx, &ctx); + + librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx( + request->get_remote_io_ctx())); + + InSequence seq; + expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, -ENOENT); + + request->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockImageSyncObjectCopyRequest, Write) { + // scribble some data + std::string remote_oid(m_remote_image_ctx->get_object_name(0)); + interval_set one; + scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 102400, &one); + + ASSERT_EQ(0, create_snap("sync")); + librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + C_SaferCond ctx; + MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, + mock_local_image_ctx, &ctx); + + librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx( + request->get_remote_io_ctx())); + librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx( + request->get_local_io_ctx())); + + InSequence seq; + expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0); + expect_read(mock_remote_io_ctx, 0, one.range_end(), 0); + expect_write(mock_local_io_ctx, 0, one.range_end(), 0); + + request->send(); + ASSERT_EQ(0, ctx.wait()); + ASSERT_EQ(0, compare_objects()); +} + +TEST_F(TestMockImageSyncObjectCopyRequest, ReadError) { + // scribble some data + std::string remote_oid(m_remote_image_ctx->get_object_name(0)); + interval_set one; + scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 102400, &one); + + ASSERT_EQ(0, create_snap("sync")); + librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + C_SaferCond ctx; + MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, + mock_local_image_ctx, &ctx); + + librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx( + request->get_remote_io_ctx())); + + InSequence seq; + expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0); + expect_read(mock_remote_io_ctx, 0, one.range_end(), -EINVAL); + + request->send(); + ASSERT_EQ(-EINVAL, ctx.wait()); +} + +TEST_F(TestMockImageSyncObjectCopyRequest, WriteError) { + // scribble some data + std::string remote_oid(m_remote_image_ctx->get_object_name(0)); + interval_set one; + scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 102400, &one); + + ASSERT_EQ(0, create_snap("sync")); + librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + C_SaferCond ctx; + MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, + mock_local_image_ctx, &ctx); + + librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx( + request->get_remote_io_ctx())); + librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx( + request->get_local_io_ctx())); + + InSequence seq; + expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0); + expect_read(mock_remote_io_ctx, 0, one.range_end(), 0); + expect_write(mock_local_io_ctx, 0, one.range_end(), -EINVAL); + + request->send(); + ASSERT_EQ(-EINVAL, ctx.wait()); +} + +TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) { + // scribble some data + std::string remote_oid(m_remote_image_ctx->get_object_name(0)); + interval_set one; + scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &one); + ASSERT_EQ(0, create_snap("one")); + + interval_set two; + scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &two); + ASSERT_EQ(0, create_snap("two")); + + if (one.range_end() < two.range_end()) { + interval_set resize_diff; + resize_diff.insert(one.range_end(), two.range_end() - one.range_end()); + two.union_of(resize_diff); + } + + ASSERT_EQ(0, create_snap("sync")); + librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + C_SaferCond ctx; + MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, + mock_local_image_ctx, &ctx); + + librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx( + request->get_remote_io_ctx())); + librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx( + request->get_local_io_ctx())); + + InSequence seq; + expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0); + expect_read(mock_remote_io_ctx, 0, one.range_end(), 0); + expect_write(mock_local_io_ctx, 0, one.range_end(), 0); + expect_read(mock_remote_io_ctx, two, 0); + expect_write(mock_local_io_ctx, two, 0); + + request->send(); + ASSERT_EQ(0, ctx.wait()); + ASSERT_EQ(0, compare_objects()); +} + +TEST_F(TestMockImageSyncObjectCopyRequest, Trim) { + // scribble some data + std::string remote_oid(m_remote_image_ctx->get_object_name(0)); + interval_set one; + scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &one); + ASSERT_EQ(0, create_snap("one")); + + // trim the object + uint64_t trim_offset = rand() % one.range_end(); + ASSERT_EQ(0, m_remote_image_ctx->data_ctx.trunc(remote_oid, trim_offset)); + ASSERT_EQ(0, create_snap("sync")); + + librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + C_SaferCond ctx; + MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, + mock_local_image_ctx, &ctx); + + librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx( + request->get_remote_io_ctx())); + librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx( + request->get_local_io_ctx())); + + InSequence seq; + expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0); + expect_read(mock_remote_io_ctx, 0, one.range_end(), 0); + expect_write(mock_local_io_ctx, 0, one.range_end(), 0); + expect_truncate(mock_local_io_ctx, trim_offset, 0); + + request->send(); + ASSERT_EQ(0, ctx.wait()); + ASSERT_EQ(0, compare_objects()); +} + +TEST_F(TestMockImageSyncObjectCopyRequest, Remove) { + // scribble some data + std::string remote_oid(m_remote_image_ctx->get_object_name(0)); + interval_set one; + scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &one); + ASSERT_EQ(0, create_snap("one")); + + // remove the object + ASSERT_EQ(0, m_remote_image_ctx->data_ctx.remove(remote_oid)); + ASSERT_EQ(0, create_snap("sync")); + librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx); + + C_SaferCond ctx; + MockObjectCopyRequest *request = create_request(mock_remote_image_ctx, + mock_local_image_ctx, &ctx); + + librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx( + request->get_remote_io_ctx())); + librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx( + request->get_local_io_ctx())); + + InSequence seq; + expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0); + expect_read(mock_remote_io_ctx, 0, one.range_end(), 0); + expect_write(mock_local_io_ctx, 0, one.range_end(), 0); + expect_remove(mock_local_io_ctx, 0); + + request->send(); + ASSERT_EQ(0, ctx.wait()); + ASSERT_EQ(0, compare_objects()); +} + +} // namespace image_sync +} // namespace mirror +} // namespace rbd diff --git a/src/test/rbd_mirror/test_fixture.cc b/src/test/rbd_mirror/test_fixture.cc new file mode 100644 index 000000000000..51d25c27857e --- /dev/null +++ b/src/test/rbd_mirror/test_fixture.cc @@ -0,0 +1,72 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "test/rbd_mirror/test_fixture.h" +#include "include/stringify.h" +#include "include/rbd/librbd.hpp" +#include "librbd/ImageCtx.h" +#include "librbd/ImageState.h" +#include "test/librados/test.h" + +namespace rbd { +namespace mirror { + +std::string TestFixture::_local_pool_name; +std::string TestFixture::_remote_pool_name; +librados::Rados TestFixture::_rados; +uint64_t TestFixture::_image_number = 0; + +TestFixture::TestFixture() { +} + +void TestFixture::SetUpTestCase() { + _local_pool_name = get_temp_pool_name("test-rbd-mirror-"); + ASSERT_EQ("", create_one_pool_pp(_local_pool_name, _rados)); + + _remote_pool_name = get_temp_pool_name("test-rbd-mirror-"); + ASSERT_EQ("", create_one_pool_pp(_remote_pool_name, _rados)); +} + +void TestFixture::TearDownTestCase() { + ASSERT_EQ(0, _rados.pool_delete(_remote_pool_name.c_str())); + ASSERT_EQ(0, _rados.pool_delete(_local_pool_name.c_str())); + _rados.shutdown(); +} + +void TestFixture::SetUp() { + ASSERT_EQ(0, _rados.ioctx_create(_local_pool_name.c_str(), m_local_io_ctx)); + ASSERT_EQ(0, _rados.ioctx_create(_remote_pool_name.c_str(), m_remote_io_ctx)); + m_image_name = get_temp_image_name(); +} + +void TestFixture::TearDown() { + for (auto image_ctx : m_image_ctxs) { + image_ctx->state->close(); + } + + m_remote_io_ctx.close(); + m_local_io_ctx.close(); +} + +int TestFixture::create_image(librbd::RBD &rbd, librados::IoCtx &ioctx, + const std::string &name, uint64_t size) { + int order = 0; + return rbd.create2(ioctx, name.c_str(), size, RBD_FEATURES_ALL, &order); +} + +int TestFixture::open_image(librados::IoCtx &io_ctx, + const std::string &image_name, + librbd::ImageCtx **image_ctx) { + *image_ctx = new librbd::ImageCtx(image_name.c_str(), "", NULL, io_ctx, + false); + m_image_ctxs.insert(*image_ctx); + return (*image_ctx)->state->open(); +} + +std::string TestFixture::get_temp_image_name() { + ++_image_number; + return "image" + stringify(_image_number); +} + +} // namespace mirror +} // namespace rbd diff --git a/src/test/rbd_mirror/test_fixture.h b/src/test/rbd_mirror/test_fixture.h new file mode 100644 index 000000000000..4297615aedbf --- /dev/null +++ b/src/test/rbd_mirror/test_fixture.h @@ -0,0 +1,54 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_TEST_RBD_MIRROR_TEST_FIXTURE_H +#define CEPH_TEST_RBD_MIRROR_TEST_FIXTURE_H + +#include "include/int_types.h" +#include "include/rados/librados.hpp" +#include +#include + +namespace librbd { +class ImageCtx; +class RBD; +} + +namespace rbd { +namespace mirror { + +class TestFixture : public ::testing::Test { +public: + TestFixture(); + + static void SetUpTestCase(); + static void TearDownTestCase(); + + virtual void SetUp(); + virtual void TearDown(); + + librados::IoCtx m_local_io_ctx; + librados::IoCtx m_remote_io_ctx; + + std::string m_image_name; + uint64_t m_image_size = 2 << 20; + + std::set m_image_ctxs; + + int create_image(librbd::RBD &rbd, librados::IoCtx &ioctx, + const std::string &name, uint64_t size); + int open_image(librados::IoCtx &io_ctx, const std::string &image_name, + librbd::ImageCtx **image_ctx); + + static std::string get_temp_image_name(); + + static std::string _local_pool_name; + static std::string _remote_pool_name; + static librados::Rados _rados; + static uint64_t _image_number; +}; + +} // namespace mirror +} // namespace rbd + +#endif // CEPH_TEST_RBD_MIRROR_TEST_FIXTURE_H diff --git a/src/test/rbd_mirror/test_mock_fixture.cc b/src/test/rbd_mirror/test_mock_fixture.cc new file mode 100644 index 000000000000..e64297bb3bec --- /dev/null +++ b/src/test/rbd_mirror/test_mock_fixture.cc @@ -0,0 +1,53 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "test/rbd_mirror/test_mock_fixture.h" +#include "test/librados_test_stub/LibradosTestStub.h" +#include "test/librados_test_stub/MockTestMemRadosClient.h" + +namespace rbd { +namespace mirror { + +TestMockFixture::TestRadosClientPtr TestMockFixture::s_test_rados_client; +::testing::NiceMock * + TestMockFixture::s_mock_rados_client = NULL; + +void TestMockFixture::SetUpTestCase() { + s_test_rados_client = librados_test_stub::get_rados_client(); + + // use a mock version of the in-memory rados client + s_mock_rados_client = new ::testing::NiceMock( + s_test_rados_client->cct()); + librados_test_stub::set_rados_client(TestRadosClientPtr(s_mock_rados_client)); + TestFixture::SetUpTestCase(); +} + +void TestMockFixture::TearDownTestCase() { + TestFixture::TearDownTestCase(); + librados_test_stub::set_rados_client(s_test_rados_client); + s_test_rados_client->put(); + s_test_rados_client.reset(); +} + +void TestMockFixture::SetUp() { + TestFixture::SetUp(); +} + +void TestMockFixture::TearDown() { + TestFixture::TearDown(); + + // Mock rados client lives across tests -- reset it to initial state + ::testing::Mock::VerifyAndClear(s_mock_rados_client); + s_mock_rados_client->default_to_dispatch(); +} + +librados::MockTestMemIoCtxImpl &TestMockFixture::get_mock_io_ctx( + librados::IoCtx &ioctx) { + librados::MockTestMemIoCtxImpl **mock = + reinterpret_cast(&ioctx); + return **mock; +} + +} // namespace mirror +} // namespace rbd + diff --git a/src/test/rbd_mirror/test_mock_fixture.h b/src/test/rbd_mirror/test_mock_fixture.h new file mode 100644 index 000000000000..9038c797c158 --- /dev/null +++ b/src/test/rbd_mirror/test_mock_fixture.h @@ -0,0 +1,43 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_TEST_RBD_MIRROR_TEST_MOCK_FIXTURE_H +#define CEPH_TEST_RBD_MIRROR_TEST_MOCK_FIXTURE_H + +#include "test/rbd_mirror/test_fixture.h" +#include +#include + +namespace librados { +class TestRadosClient; +class MockTestMemIoCtxImpl; +class MockTestMemRadosClient; +} + +namespace rbd { +namespace mirror { + +class TestMockFixture : public TestFixture { +public: + typedef boost::shared_ptr TestRadosClientPtr; + + static void SetUpTestCase(); + static void TearDownTestCase(); + + virtual void SetUp(); + virtual void TearDown(); + + ::testing::NiceMock &get_mock_rados_client() { + return *s_mock_rados_client; + } + librados::MockTestMemIoCtxImpl &get_mock_io_ctx(librados::IoCtx &ioctx); + +private: + static TestRadosClientPtr s_test_rados_client; + static ::testing::NiceMock *s_mock_rados_client; +}; + +} // namespace mirror +} // namespace rbd + +#endif // CEPH_TEST_RBD_MIRROR_TEST_MOCK_FIXTURE_H