]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
test: verify proper update of object map during rbd-mirror image sync 7979/head
authorJason Dillaman <dillaman@redhat.com>
Sun, 13 Mar 2016 03:13:11 +0000 (22:13 -0500)
committerJason Dillaman <dillaman@redhat.com>
Sun, 13 Mar 2016 03:40:17 +0000 (22:40 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/librbd/mock/MockObjectMap.h
src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc
src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc
src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc
src/test/rbd_mirror/test_ImageSync.cc
src/test/rbd_mirror/test_fixture.cc
src/test/rbd_mirror/test_fixture.h
src/test/rbd_mirror/test_mock_ImageSync.cc
src/test/rbd_mirror/test_mock_fixture.cc
src/test/rbd_mirror/test_mock_fixture.h

index 2b81488b7a2205af24b562ccd448b9b6c4ed38df..25d14ed3c085c108b17ebd2754d83c0d22c80f09 100644 (file)
@@ -17,7 +17,10 @@ struct MockObjectMap {
 
   MOCK_METHOD3(aio_resize, void(uint64_t new_size, uint8_t default_object_state,
                                 Context *on_finish));
-
+  MOCK_METHOD6(aio_update, void(uint64_t snap_id, uint64_t start_object_no,
+                                uint64_t end_object_no, uint8_t new_state,
+                                const boost::optional<uint8_t> &current_state,
+                                Context *on_finish));
   MOCK_METHOD2(snapshot_add, void(uint64_t snap_id, Context *on_finish));
   MOCK_METHOD2(snapshot_remove, void(uint64_t snap_id, Context *on_finish));
   MOCK_METHOD2(rollback, void(uint64_t snap_id, Context *on_finish));
index 302a4d62500b828e119b3c8b40f97d57850dbfe7..ff3584e071fd49df72b330ad10b84ab86c9a78f6 100644 (file)
@@ -80,14 +80,6 @@ public:
 
     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));
-
-    m_threads = new rbd::mirror::Threads(reinterpret_cast<CephContext*>(
-      m_local_io_ctx.cct()));
-  }
-
-  virtual void TearDown() {
-    delete m_threads;
-    TestMockFixture::TearDown();
   }
 
   void expect_get_snap_id(librbd::MockImageCtx &mock_image_ctx) {
@@ -182,8 +174,6 @@ public:
   librbd::ImageCtx *m_local_image_ctx;
   librbd::journal::MirrorPeerClientMeta m_client_meta;
   MockImageCopyRequest::SnapMap m_snap_map;
-
-  rbd::mirror::Threads *m_threads = nullptr;
 };
 
 TEST_F(TestMockImageSyncImageCopyRequest, SimpleImage) {
index 7df68723e429e071f93e8440fe014d56b5e251f7..d99d7dfae1b05a02c39bf55d8f1115fd8921d701 100644 (file)
@@ -4,11 +4,14 @@
 #include "test/rbd_mirror/test_mock_fixture.h"
 #include "include/interval_set.h"
 #include "include/rbd/librbd.hpp"
+#include "librbd/AioImageRequestWQ.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/ImageState.h"
+#include "librbd/internal.h"
 #include "librbd/Operations.h"
 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
 #include "test/librbd/mock/MockImageCtx.h"
+#include "tools/rbd_mirror/Threads.h"
 #include "tools/rbd_mirror/image_sync/ObjectCopyRequest.h"
 
 // template definitions
@@ -22,15 +25,16 @@ namespace image_sync {
 using ::testing::_;
 using ::testing::DoDefault;
 using ::testing::InSequence;
+using ::testing::Invoke;
 using ::testing::Return;
+using ::testing::WithArg;
 
 namespace {
 
-void scribble(librados::IoCtx &io_ctx, const std::string &oid, int num_ops,
-              size_t max_size, interval_set<uint64_t> *what)
+void scribble(librbd::ImageCtx *image_ctx, int num_ops, size_t max_size,
+              interval_set<uint64_t> *what)
 {
-  uint64_t object_size = 1 << 22;
-  librados::ObjectWriteOperation op;
+  uint64_t object_size = 1 << image_ctx->order;
   for (int i=0; i<num_ops; i++) {
     uint64_t off = rand() % (object_size - max_size + 1);
     uint64_t len = 1 + rand() % max_size;
@@ -38,14 +42,13 @@ void scribble(librados::IoCtx &io_ctx, const std::string &oid, int num_ops,
     bufferlist bl;
     bl.append(std::string(len, '1'));
 
-    op.write(off, bl);
+    int r = image_ctx->aio_work_queue->write(off, len, bl.c_str(), 0);
+    ASSERT_EQ(static_cast<int>(len), r);
 
     interval_set<uint64_t> w;
     w.insert(off, len);
     what->union_of(w);
   }
-
-  ASSERT_EQ(0, io_ctx.operate(oid, &op));
   std::cout << " wrote " << *what << std::endl;
 }
 
@@ -152,6 +155,28 @@ public:
     }
   }
 
+  void expect_update_object_map(librbd::MockImageCtx &mock_image_ctx,
+                                librbd::MockObjectMap &mock_object_map,
+                                librados::snap_t snap_id, uint8_t state,
+                                int r) {
+    if (mock_image_ctx.image_ctx->object_map != nullptr) {
+      auto &expect = EXPECT_CALL(mock_object_map, aio_update(snap_id, 0, 1, state, _, _));
+      if (r < 0) {
+        expect.WillOnce(WithArg<5>(Invoke([this, r](Context *ctx) {
+            m_threads->work_queue->queue(ctx, r);
+          })));
+      } else {
+        expect.WillOnce(WithArg<5>(Invoke([&mock_image_ctx, snap_id, state, r](Context *ctx) {
+            RWLock::RLocker snap_locker(mock_image_ctx.image_ctx->snap_lock);
+            RWLock::WLocker object_map_locker(mock_image_ctx.image_ctx->object_map_lock);
+            mock_image_ctx.image_ctx->object_map->aio_update(snap_id, 0, 1,
+                                                             state,
+                                                             boost::none, ctx);
+          })));
+      }
+    }
+  }
+
   using TestFixture::create_snap;
   int create_snap(const char* snap_name) {
     librados::snap_t remote_snap_id;
@@ -174,47 +199,84 @@ public:
                             m_snap_map.rbegin()->second.end());
     }
     m_snap_map[remote_snap_id] = local_snap_ids;
+    m_local_snap_ids.push_back(local_snap_id);
     return 0;
   }
 
+  std::string get_snap_name(librbd::ImageCtx *image_ctx,
+                            librados::snap_t snap_id) {
+    auto it = std::find_if(image_ctx->snap_ids.begin(),
+                           image_ctx->snap_ids.end(),
+                           [snap_id](const std::pair<std::string, librados::snap_t> &pair) {
+        return (pair.second == snap_id);
+      });
+    if (it == image_ctx->snap_ids.end()) {
+      return "";
+    }
+    return it->first;
+  }
+
   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);
-
+    int r;
+    uint64_t object_size = 1 << m_remote_image_ctx->order;
     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);
+      std::string snap_name = get_snap_name(m_remote_image_ctx, remote_snap_id);
+      if (snap_name.empty()) {
+        return -ENOENT;
+      }
+
+      std::cout << "comparing '" << snap_name << " (" << remote_snap_id
+                << " to " << local_snap_id << ")" << std::endl;
+
+      r = librbd::snap_set(m_remote_image_ctx, snap_name.c_str());
+      if (r < 0) {
+        return r;
+      }
+
+      r = librbd::snap_set(m_local_image_ctx, snap_name.c_str());
+      if (r < 0) {
+        return r;
+      }
+
       bufferlist remote_bl;
-      int remote_r = remote_io_ctx.read(remote_oid, remote_bl, 1<<22, 0);
+      remote_bl.append(std::string(object_size, '1'));
+      r = m_remote_image_ctx->aio_work_queue->read(0, object_size,
+                                                   remote_bl.c_str(), 0);
+      if (r < 0) {
+        return r;
+      }
 
-      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;
+      local_bl.append(std::string(object_size, '1'));
+      r = m_local_image_ctx->aio_work_queue->read(0, object_size,
+                                                  local_bl.c_str(), 0);
+      if (r < 0) {
+        return r;
       }
 
       if (!remote_bl.contents_equal(local_bl)) {
         return -EBADMSG;
       }
     }
+
+    r = librbd::snap_set(m_remote_image_ctx, nullptr);
+    if (r < 0) {
+      return r;
+    }
+    r = librbd::snap_set(m_local_image_ctx, nullptr);
+    if (r < 0) {
+      return r;
+    }
+
     return 0;
   }
 
@@ -222,7 +284,7 @@ public:
   librbd::ImageCtx *m_local_image_ctx;
 
   MockObjectCopyRequest::SnapMap m_snap_map;
-
+  std::vector<librados::snap_t> m_local_snap_ids;
 };
 
 TEST_F(TestMockImageSyncObjectCopyRequest, DNE) {
@@ -230,6 +292,11 @@ TEST_F(TestMockImageSyncObjectCopyRequest, DNE) {
   librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
   librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx);
 
+  librbd::MockObjectMap mock_object_map;
+  mock_local_image_ctx.object_map = &mock_object_map;
+
+  expect_test_features(mock_local_image_ctx);
+
   C_SaferCond ctx;
   MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
                                                   mock_local_image_ctx, &ctx);
@@ -246,14 +313,18 @@ TEST_F(TestMockImageSyncObjectCopyRequest, DNE) {
 
 TEST_F(TestMockImageSyncObjectCopyRequest, Write) {
   // scribble some data
-  std::string remote_oid(m_remote_image_ctx->get_object_name(0));
   interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 102400, &one);
+  scribble(m_remote_image_ctx, 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);
 
+  librbd::MockObjectMap mock_object_map;
+  mock_local_image_ctx.object_map = &mock_object_map;
+
+  expect_test_features(mock_local_image_ctx);
+
   C_SaferCond ctx;
   MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
                                                   mock_local_image_ctx, &ctx);
@@ -267,6 +338,8 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Write) {
   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_update_object_map(mock_local_image_ctx, mock_object_map,
+                           m_local_snap_ids[0], OBJECT_EXISTS, 0);
 
   request->send();
   ASSERT_EQ(0, ctx.wait());
@@ -275,14 +348,18 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Write) {
 
 TEST_F(TestMockImageSyncObjectCopyRequest, ReadError) {
   // scribble some data
-  std::string remote_oid(m_remote_image_ctx->get_object_name(0));
   interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 102400, &one);
+  scribble(m_remote_image_ctx, 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);
 
+  librbd::MockObjectMap mock_object_map;
+  mock_local_image_ctx.object_map = &mock_object_map;
+
+  expect_test_features(mock_local_image_ctx);
+
   C_SaferCond ctx;
   MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
                                                   mock_local_image_ctx, &ctx);
@@ -300,14 +377,18 @@ TEST_F(TestMockImageSyncObjectCopyRequest, ReadError) {
 
 TEST_F(TestMockImageSyncObjectCopyRequest, WriteError) {
   // scribble some data
-  std::string remote_oid(m_remote_image_ctx->get_object_name(0));
   interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 102400, &one);
+  scribble(m_remote_image_ctx, 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);
 
+  librbd::MockObjectMap mock_object_map;
+  mock_local_image_ctx.object_map = &mock_object_map;
+
+  expect_test_features(mock_local_image_ctx);
+
   C_SaferCond ctx;
   MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
                                                   mock_local_image_ctx, &ctx);
@@ -328,13 +409,12 @@ TEST_F(TestMockImageSyncObjectCopyRequest, WriteError) {
 
 TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) {
   // scribble some data
-  std::string remote_oid(m_remote_image_ctx->get_object_name(0));
   interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &one);
+  scribble(m_remote_image_ctx, 10, 102400, &one);
   ASSERT_EQ(0, create_snap("one"));
 
   interval_set<uint64_t> two;
-  scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &two);
+  scribble(m_remote_image_ctx, 10, 102400, &two);
   ASSERT_EQ(0, create_snap("two"));
 
   if (one.range_end() < two.range_end()) {
@@ -347,6 +427,11 @@ TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) {
   librbd::MockImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
   librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx);
 
+  librbd::MockObjectMap mock_object_map;
+  mock_local_image_ctx.object_map = &mock_object_map;
+
+  expect_test_features(mock_local_image_ctx);
+
   C_SaferCond ctx;
   MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
                                                   mock_local_image_ctx, &ctx);
@@ -362,6 +447,12 @@ TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) {
   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);
+  expect_update_object_map(mock_local_image_ctx, mock_object_map,
+                           m_local_snap_ids[0], OBJECT_EXISTS, 0);
+  expect_update_object_map(mock_local_image_ctx, mock_object_map,
+                           m_local_snap_ids[1], OBJECT_EXISTS, 0);
+  expect_update_object_map(mock_local_image_ctx, mock_object_map,
+                           m_local_snap_ids[2], OBJECT_EXISTS_CLEAN, 0);
 
   request->send();
   ASSERT_EQ(0, ctx.wait());
@@ -370,19 +461,24 @@ TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) {
 
 TEST_F(TestMockImageSyncObjectCopyRequest, Trim) {
   // scribble some data
-  std::string remote_oid(m_remote_image_ctx->get_object_name(0));
   interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &one);
+  scribble(m_remote_image_ctx, 10, 102400, &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_LE(0, m_remote_image_ctx->aio_work_queue->discard(
+    trim_offset, one.range_end() - 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);
 
+  librbd::MockObjectMap mock_object_map;
+  mock_local_image_ctx.object_map = &mock_object_map;
+
+  expect_test_features(mock_local_image_ctx);
+
   C_SaferCond ctx;
   MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
                                                   mock_local_image_ctx, &ctx);
@@ -397,6 +493,10 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Trim) {
   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);
+  expect_update_object_map(mock_local_image_ctx, mock_object_map,
+                           m_local_snap_ids[0], OBJECT_EXISTS, 0);
+  expect_update_object_map(mock_local_image_ctx, mock_object_map,
+                           m_local_snap_ids[1], OBJECT_EXISTS, 0);
 
   request->send();
   ASSERT_EQ(0, ctx.wait());
@@ -405,17 +505,22 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Trim) {
 
 TEST_F(TestMockImageSyncObjectCopyRequest, Remove) {
   // scribble some data
-  std::string remote_oid(m_remote_image_ctx->get_object_name(0));
   interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx->data_ctx, remote_oid, 10, 1024, &one);
+  scribble(m_remote_image_ctx, 10, 102400, &one);
   ASSERT_EQ(0, create_snap("one"));
 
   // remove the object
-  ASSERT_EQ(0, m_remote_image_ctx->data_ctx.remove(remote_oid));
+  uint64_t object_size = 1 << m_remote_image_ctx->order;
+  ASSERT_LE(0, m_remote_image_ctx->aio_work_queue->discard(0, object_size));
   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);
 
+  librbd::MockObjectMap mock_object_map;
+  mock_local_image_ctx.object_map = &mock_object_map;
+
+  expect_test_features(mock_local_image_ctx);
+
   C_SaferCond ctx;
   MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
                                                   mock_local_image_ctx, &ctx);
@@ -430,6 +535,10 @@ TEST_F(TestMockImageSyncObjectCopyRequest, Remove) {
   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);
+  expect_update_object_map(mock_local_image_ctx, mock_object_map,
+                           m_local_snap_ids[0], OBJECT_EXISTS, 0);
+  expect_update_object_map(mock_local_image_ctx, mock_object_map,
+                           m_local_snap_ids[1], OBJECT_NONEXISTENT, 0);
 
   request->send();
   ASSERT_EQ(0, ctx.wait());
index 506eeddc90d8e71e84174874ca128b57b0c4accb..10c3ac36ebc5add422b3b1b40590efe93a77274e 100644 (file)
@@ -43,14 +43,6 @@ public:
 
     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));
-
-    m_threads = new rbd::mirror::Threads(reinterpret_cast<CephContext*>(
-      m_local_io_ctx.cct()));
-  }
-
-  virtual void TearDown() {
-    delete m_threads;
-    TestMockFixture::TearDown();
   }
 
   void expect_snap_create(librbd::MockImageCtx &mock_image_ctx,
@@ -118,8 +110,6 @@ public:
 
   MockSnapshotCopyRequest::SnapMap m_snap_map;
   librbd::journal::MirrorPeerClientMeta m_client_meta;
-
-  rbd::mirror::Threads *m_threads = nullptr;
 };
 
 TEST_F(TestMockImageSyncSnapshotCopyRequest, Empty) {
index 7846fcae49204bc946973ee37b003c3215b48b5c..10622a15856f6139aa19b85ba06ac3ff1a3fe652 100644 (file)
@@ -44,9 +44,6 @@ public:
     create_and_open(m_local_io_ctx, &m_local_image_ctx);
     create_and_open(m_remote_io_ctx, &m_remote_image_ctx);
 
-    m_threads = new rbd::mirror::Threads(reinterpret_cast<CephContext*>(
-      m_local_io_ctx.cct()));
-
     m_remote_journaler = new ::journal::Journaler(
       m_threads->work_queue, m_threads->timer, &m_threads->timer_lock,
       m_remote_io_ctx, m_remote_image_ctx->id, "mirror-uuid", 5);
@@ -60,11 +57,6 @@ public:
     ASSERT_EQ(0, m_remote_journaler->register_client(client_data_bl));
   }
 
-  virtual void TearDown() {
-    delete m_threads;
-    TestFixture::TearDown();
-  }
-
   void create_and_open(librados::IoCtx &io_ctx, librbd::ImageCtx **image_ctx) {
     librbd::RBD rbd;
     ASSERT_EQ(0, create_image(rbd, io_ctx, m_image_name, m_image_size));
@@ -90,8 +82,6 @@ public:
   librbd::ImageCtx *m_local_image_ctx;
   ::journal::Journaler *m_remote_journaler;
   librbd::journal::MirrorPeerClientMeta m_client_meta;
-
-  rbd::mirror::Threads *m_threads = nullptr;
 };
 
 TEST_F(TestImageSync, Empty) {
index ab24353bd1c330a902a11f146197ca3ce294cae2..56620db0cd0009bd6439742f107104b66e9a87ea 100644 (file)
@@ -8,6 +8,7 @@
 #include "librbd/ImageState.h"
 #include "librbd/Operations.h"
 #include "test/librados/test.h"
+#include "tools/rbd_mirror/Threads.h"
 
 namespace rbd {
 namespace mirror {
@@ -38,6 +39,9 @@ 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();
+
+  m_threads = new rbd::mirror::Threads(reinterpret_cast<CephContext*>(
+    m_local_io_ctx.cct()));
 }
 
 void TestFixture::TearDown() {
@@ -47,6 +51,8 @@ void TestFixture::TearDown() {
 
   m_remote_io_ctx.close();
   m_local_io_ctx.close();
+
+  delete m_threads;
 }
 
 int TestFixture::create_image(librbd::RBD &rbd, librados::IoCtx &ioctx,
index 730ffc5311366943d4de88bdc9ffba0a16cea922..79a6f86f73eea016a14b9288984d52a475ab738c 100644 (file)
@@ -17,6 +17,8 @@ class RBD;
 namespace rbd {
 namespace mirror {
 
+class Threads;
+
 class TestFixture : public ::testing::Test {
 public:
   TestFixture();
@@ -35,6 +37,8 @@ public:
 
   std::set<librbd::ImageCtx *> m_image_ctxs;
 
+  Threads *m_threads = nullptr;
+
   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,
index 21892cff726cc03531c715a435ead62ca45424f1..726fa95c3232efd36e2e61d7c068f98718f6d35f 100644 (file)
@@ -6,6 +6,7 @@
 #include "librbd/journal/Types.h"
 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
 #include "test/librbd/mock/MockImageCtx.h"
+#include "test/librbd/mock/MockObjectMap.h"
 #include "test/rbd_mirror/mock/MockJournaler.h"
 #include "tools/rbd_mirror/ImageSync.h"
 #include "tools/rbd_mirror/Threads.h"
@@ -127,6 +128,8 @@ SyncPointPruneRequest<librbd::MockImageCtx>* SyncPointPruneRequest<librbd::MockI
 using ::testing::_;
 using ::testing::InSequence;
 using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::WithArg;
 
 class TestMockImageSync : public TestMockFixture {
 public:
@@ -145,21 +148,15 @@ public:
 
     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));
-
-    m_threads = new rbd::mirror::Threads(reinterpret_cast<CephContext*>(
-      m_local_io_ctx.cct()));
-  }
-
-  virtual void TearDown() {
-    delete m_threads;
-    TestMockFixture::TearDown();
   }
 
-  void expect_create_sync_point(MockSyncPointCreateRequest &mock_sync_point_create_request,
+  void expect_create_sync_point(librbd::MockImageCtx &mock_local_image_ctx,
+                                MockSyncPointCreateRequest &mock_sync_point_create_request,
                                 int r) {
     EXPECT_CALL(mock_sync_point_create_request, send())
-      .WillOnce(Invoke([this, &mock_sync_point_create_request, r]() {
+      .WillOnce(Invoke([this, &mock_local_image_ctx, &mock_sync_point_create_request, r]() {
           if (r == 0) {
+            mock_local_image_ctx.snap_ids["snap1"] = 123;
             m_client_meta.sync_points.emplace_back("snap1", boost::none);
           }
           m_threads->work_queue->queue(mock_sync_point_create_request.on_finish, r);
@@ -180,6 +177,29 @@ public:
         }));
   }
 
+  void expect_rollback_object_map(librbd::MockObjectMap &mock_object_map, int r) {
+    if ((m_local_image_ctx->features & RBD_FEATURE_OBJECT_MAP) != 0) {
+      EXPECT_CALL(mock_object_map, rollback(_, _))
+        .WillOnce(WithArg<1>(Invoke([this, r](Context *ctx) {
+            m_threads->work_queue->queue(ctx, r);
+          })));
+    }
+  }
+
+  void expect_create_object_map(librbd::MockImageCtx &mock_image_ctx,
+                                librbd::MockObjectMap *mock_object_map) {
+    EXPECT_CALL(mock_image_ctx, create_object_map(CEPH_NOSNAP))
+      .WillOnce(Return(mock_object_map));
+  }
+
+  void expect_open_object_map(librbd::MockImageCtx &mock_image_ctx,
+                              librbd::MockObjectMap &mock_object_map) {
+    EXPECT_CALL(mock_object_map, open(_))
+      .WillOnce(Invoke([this](Context *ctx) {
+          m_threads->work_queue->queue(ctx, 0);
+        }));
+  }
+
   void expect_prune_sync_point(MockSyncPointPruneRequest &mock_sync_point_prune_request,
                                bool sync_complete, int r) {
     EXPECT_CALL(mock_sync_point_prune_request, send())
@@ -211,8 +231,6 @@ public:
   librbd::ImageCtx *m_remote_image_ctx;
   librbd::ImageCtx *m_local_image_ctx;
   librbd::journal::MirrorPeerClientMeta m_client_meta;
-
-  rbd::mirror::Threads *m_threads = nullptr;
 };
 
 TEST_F(TestMockImageSync, SimpleSync) {
@@ -224,10 +242,17 @@ TEST_F(TestMockImageSync, SimpleSync) {
   MockSyncPointCreateRequest mock_sync_point_create_request;
   MockSyncPointPruneRequest mock_sync_point_prune_request;
 
+  librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
+  mock_local_image_ctx.object_map = mock_object_map;
+  expect_test_features(mock_local_image_ctx);
+
   InSequence seq;
-  expect_create_sync_point(mock_sync_point_create_request, 0);
+  expect_create_sync_point(mock_local_image_ctx, mock_sync_point_create_request, 0);
   expect_copy_snapshots(mock_snapshot_copy_request, 0);
   expect_copy_image(mock_image_copy_request, 0);
+  expect_rollback_object_map(*mock_object_map, 0);
+  expect_create_object_map(mock_local_image_ctx, mock_object_map);
+  expect_open_object_map(mock_local_image_ctx, *mock_object_map);
   expect_prune_sync_point(mock_sync_point_prune_request, true, 0);
 
   C_SaferCond ctx;
@@ -249,11 +274,20 @@ TEST_F(TestMockImageSync, RestartSync) {
 
   m_client_meta.sync_points = {{"snap1", boost::none},
                                {"snap2", "snap1", boost::none}};
+  mock_local_image_ctx.snap_ids["snap1"] = 123;
+  mock_local_image_ctx.snap_ids["snap2"] = 234;
+
+  librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
+  mock_local_image_ctx.object_map = mock_object_map;
+  expect_test_features(mock_local_image_ctx);
 
   InSequence seq;
   expect_prune_sync_point(mock_sync_point_prune_request, false, 0);
   expect_copy_snapshots(mock_snapshot_copy_request, 0);
   expect_copy_image(mock_image_copy_request, 0);
+  expect_rollback_object_map(*mock_object_map, 0);
+  expect_create_object_map(mock_local_image_ctx, mock_object_map);
+  expect_open_object_map(mock_local_image_ctx, *mock_object_map);
   expect_prune_sync_point(mock_sync_point_prune_request, true, 0);
 
   C_SaferCond ctx;
index 0863c40b909da234871b278138e4ecfe6196bb69..6f45ca9528d5eaedf4098999e2368e0c3ccd9996 100644 (file)
@@ -2,12 +2,18 @@
 // vim: ts=8 sw=2 smarttab
 
 #include "test/rbd_mirror/test_mock_fixture.h"
+#include "include/rbd/librbd.hpp"
 #include "test/librados_test_stub/LibradosTestStub.h"
 #include "test/librados_test_stub/MockTestMemRadosClient.h"
+#include "test/librbd/mock/MockImageCtx.h"
 
 namespace rbd {
 namespace mirror {
 
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::WithArg;
+
 TestMockFixture::TestRadosClientPtr TestMockFixture::s_test_rados_client;
 ::testing::NiceMock<librados::MockTestMemRadosClient> *
   TestMockFixture::s_mock_rados_client = NULL;
@@ -41,6 +47,13 @@ void TestMockFixture::TearDown() {
   s_mock_rados_client->default_to_dispatch();
 }
 
+void TestMockFixture::expect_test_features(librbd::MockImageCtx &mock_image_ctx) {
+  EXPECT_CALL(mock_image_ctx, test_features(_, _))
+    .WillRepeatedly(WithArg<0>(Invoke([&mock_image_ctx](uint64_t features) {
+        return (mock_image_ctx.features & features) != 0;
+      })));
+}
+
 } // namespace mirror
 } // namespace rbd
 
index 2231095936b13b77f20e9c650457a724edc5c319..5ce1a748bd675b162ee2873a2238422c7bbc7390 100644 (file)
@@ -15,6 +15,10 @@ class MockTestMemIoCtxImpl;
 class MockTestMemRadosClient;
 }
 
+namespace librbd {
+class MockImageCtx;
+}
+
 ACTION_P(CompleteContext, r) {
   arg0->complete(r);
 }
@@ -32,6 +36,8 @@ public:
   virtual void SetUp();
   virtual void TearDown();
 
+  void expect_test_features(librbd::MockImageCtx &mock_image_ctx);
+
   ::testing::NiceMock<librados::MockTestMemRadosClient> &get_mock_rados_client() {
     return *s_mock_rados_client;
   }