]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
test / librbd: move non-public api usage tests to internal 13806/head
authorVenky Shankar <vshankar@redhat.com>
Mon, 6 Mar 2017 06:52:27 +0000 (12:22 +0530)
committerVenky Shankar <vshankar@redhat.com>
Mon, 6 Mar 2017 11:38:16 +0000 (17:08 +0530)
Signed-off-by: Venky Shankar <vshankar@redhat.com>
src/test/librbd/test_fixture.cc
src/test/librbd/test_fixture.h
src/test/librbd/test_internal.cc
src/test/librbd/test_librbd.cc
src/test/librbd/test_support.h

index 38614c1432ba30a408f27946b3ce3d70b6d8062e..73a66f4308355b5622d3cba13b9ed22f2410a196 100644 (file)
@@ -19,6 +19,7 @@
 
 std::string TestFixture::_pool_name;
 librados::Rados TestFixture::_rados;
+rados_t TestFixture::_cluster;
 uint64_t TestFixture::_image_number = 0;
 std::string TestFixture::_data_pool;
 
@@ -26,6 +27,7 @@ TestFixture::TestFixture() : m_image_size(0) {
 }
 
 void TestFixture::SetUpTestCase() {
+  ASSERT_EQ("", connect_cluster(&_cluster));
   _pool_name = get_temp_pool_name("test-librbd-");
   ASSERT_EQ("", create_one_pool_pp(_pool_name, _rados));
 
@@ -40,6 +42,7 @@ void TestFixture::SetUpTestCase() {
 }
 
 void TestFixture::TearDownTestCase() {
+  rados_shutdown(_cluster);
   if (!_data_pool.empty()) {
     ASSERT_EQ(0, _rados.pool_delete(_data_pool.c_str()));
   }
index faa20382f651724cde270264b3a661d17ce11c52..27eea61be442dd7df8171694238a1833fab2db9b 100644 (file)
@@ -39,6 +39,7 @@ public:
 
   static std::string _pool_name;
   static librados::Rados _rados;
+  static rados_t _cluster;
   static uint64_t _image_number;
   static std::string _data_pool;
 
index fea96009931851f0d0ebbf2c244bd58e9ac150e6..c262a070527ea0c0908c3c30650389e61915cd0b 100644 (file)
@@ -3,6 +3,7 @@
 #include "cls/rbd/cls_rbd_types.h"
 #include "test/librbd/test_fixture.h"
 #include "test/librbd/test_support.h"
+#include "include/rbd/librbd.h"
 #include "librbd/ExclusiveLock.h"
 #include "librbd/ImageState.h"
 #include "librbd/ImageWatcher.h"
@@ -12,6 +13,7 @@
 #include "librbd/io/AioCompletion.h"
 #include "librbd/io/ImageRequest.h"
 #include "librbd/io/ImageRequestWQ.h"
+#include "osdc/Striper.h"
 #include <boost/scope_exit.hpp>
 #include <boost/assign/list_of.hpp>
 #include <utility>
@@ -73,6 +75,51 @@ public:
   }
 };
 
+void generate_random_iomap(librbd::Image &image, int num_objects, int object_size,
+                           int max_count, map<uint64_t, uint64_t> &iomap)
+{
+  uint64_t stripe_unit, stripe_count;
+
+  stripe_unit = image.get_stripe_unit();
+  stripe_count = image.get_stripe_count();
+
+  while (max_count-- > 0) {
+    // generate random image offset based on base random object
+    // number and object offset and then map that back to an
+    // object number based on stripe unit and count.
+    uint64_t ono = rand() % num_objects;
+    uint64_t offset = rand() % (object_size - TEST_IO_SIZE);
+    uint64_t imageoff = (ono * object_size) + offset;
+
+    file_layout_t layout;
+    layout.object_size = object_size;
+    layout.stripe_unit = stripe_unit;
+    layout.stripe_count = stripe_count;
+
+    vector<ObjectExtent> ex;
+    Striper::file_to_extents(g_ceph_context, 1, &layout, imageoff, TEST_IO_SIZE, 0, ex);
+
+    // lets not worry if IO spans multiple extents (>1 object). in such
+    // as case we would perform the write multiple times to the same
+    // offset, but we record all objects that would be generated with
+    // this IO. TODO: fix this if such a need is required by your
+    // test.
+    vector<ObjectExtent>::iterator it;
+    map<uint64_t, uint64_t> curr_iomap;
+    for (it = ex.begin(); it != ex.end(); ++it) {
+      if (iomap.find((*it).objectno) != iomap.end()) {
+        break;
+      }
+
+      curr_iomap.insert(make_pair((*it).objectno, imageoff));
+    }
+
+    if (it == ex.end()) {
+      iomap.insert(curr_iomap.begin(), curr_iomap.end());
+    }
+  }
+}
+
 TEST_F(TestInternal, OpenByID) {
    REQUIRE_FORMAT_V2();
 
@@ -924,3 +971,260 @@ TEST_F(TestInternal, DiffIterateCloneOverwrite) {
   ASSERT_EQ(one, diff);
 }
 
+TEST_F(TestInternal, TestCoR)
+{
+  REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+  std::string config_value;
+  ASSERT_EQ(0, _rados.conf_get("rbd_clone_copy_on_read", config_value));
+  if (config_value == "false") {
+    std::cout << "SKIPPING due to disabled rbd_copy_on_read" << std::endl;
+    return;
+  }
+
+  m_image_name = get_temp_image_name();
+  m_image_size = 4 << 20;
+
+  int order = 12; // smallest object size is 4K
+  uint64_t features;
+  ASSERT_TRUE(get_features(&features));
+
+  ASSERT_EQ(0, create_image_full_pp(m_rbd, m_ioctx, m_image_name, m_image_size,
+                                    features, false, &order));
+
+  librbd::Image image;
+  ASSERT_EQ(0, m_rbd.open(m_ioctx, image, m_image_name.c_str(), NULL));
+
+  librbd::image_info_t info;
+  ASSERT_EQ(0, image.stat(info, sizeof(info)));
+
+  const int object_num = info.size / info.obj_size;
+  printf("made parent image \"%s\": %ldK (%d * %ldK)\n", m_image_name.c_str(),
+         (unsigned long)m_image_size, object_num, info.obj_size/1024);
+
+  // write something into parent
+  char test_data[TEST_IO_SIZE + 1];
+  for (int i = 0; i < TEST_IO_SIZE; ++i) {
+    test_data[i] = (char) (rand() % (126 - 33) + 33);
+  }
+  test_data[TEST_IO_SIZE] = '\0';
+
+  // generate a random map which covers every objects with random
+  // offset
+  map<uint64_t, uint64_t> write_tracker;
+  generate_random_iomap(image, object_num, info.obj_size, 100, write_tracker);
+
+  printf("generated random write map:\n");
+  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
+       itr != write_tracker.end(); ++itr)
+    printf("\t [%-8ld, %-8ld]\n",
+           (unsigned long)itr->first, (unsigned long)itr->second);
+
+  bufferlist bl;
+  bl.append(test_data, TEST_IO_SIZE);
+
+  printf("write data based on random map\n");
+  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
+       itr != write_tracker.end(); ++itr) {
+    printf("\twrite object-%-4ld\t\n", (unsigned long)itr->first);
+    ASSERT_EQ(TEST_IO_SIZE, image.write(itr->second, TEST_IO_SIZE, bl));
+  }
+
+  bufferlist readbl;
+  printf("verify written data by reading\n");
+  {
+    map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
+    printf("\tread object-%-4ld\n", (unsigned long)itr->first);
+    ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl));
+    ASSERT_TRUE(readbl.contents_equal(bl));
+  }
+
+  int64_t data_pool_id = image.get_data_pool_id();
+  rados_ioctx_t d_ioctx;
+  rados_ioctx_create2(_cluster, data_pool_id, &d_ioctx);
+
+  const char *entry;
+  rados_list_ctx_t list_ctx;
+  set<string> obj_checker;
+  ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx));
+  while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) {
+    if (strstr(entry, info.block_name_prefix)) {
+      const char *block_name_suffix = entry + strlen(info.block_name_prefix) + 1;
+      obj_checker.insert(block_name_suffix);
+    }
+  }
+  rados_nobjects_list_close(list_ctx);
+
+  std::string snapname = "snap";
+  std::string clonename = get_temp_image_name();
+  ASSERT_EQ(0, image.snap_create(snapname.c_str()));
+  ASSERT_EQ(0, image.close());
+  ASSERT_EQ(0, m_rbd.open(m_ioctx, image, m_image_name.c_str(), snapname.c_str()));
+  ASSERT_EQ(0, image.snap_protect(snapname.c_str()));
+  printf("made snapshot \"%s@parent_snap\" and protect it\n", m_image_name.c_str());
+
+  ASSERT_EQ(0, clone_image_pp(m_rbd, image, m_ioctx, m_image_name.c_str(), snapname.c_str(),
+                              m_ioctx, clonename.c_str(), features));
+  ASSERT_EQ(0, image.close());
+  ASSERT_EQ(0, m_rbd.open(m_ioctx, image, clonename.c_str(), NULL));
+  printf("made and opened clone \"%s\"\n", clonename.c_str());
+
+  printf("read from \"child\"\n");
+  {
+    map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
+    printf("\tread object-%-4ld\n", (unsigned long)itr->first);
+    ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl));
+    ASSERT_TRUE(readbl.contents_equal(bl));
+  }
+
+  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
+       itr != write_tracker.end(); ++itr) {
+    printf("\tread object-%-4ld\n", (unsigned long)itr->first);
+    ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl));
+    ASSERT_TRUE(readbl.contents_equal(bl));
+  }
+
+  printf("read again reversely\n");
+  for (map<uint64_t, uint64_t>::iterator itr = --write_tracker.end();
+       itr != write_tracker.begin(); --itr) {
+    printf("\tread object-%-4ld\n", (unsigned long)itr->first);
+    ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl));
+    ASSERT_TRUE(readbl.contents_equal(bl));
+  }
+
+  // close child to flush all copy-on-read
+  ASSERT_EQ(0, image.close());
+
+  printf("check whether child image has the same set of objects as parent\n");
+  ASSERT_EQ(0, m_rbd.open(m_ioctx, image, clonename.c_str(), NULL));
+  ASSERT_EQ(0, image.stat(info, sizeof(info)));
+
+  ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx));
+  while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) {
+    if (strstr(entry, info.block_name_prefix)) {
+      const char *block_name_suffix = entry + strlen(info.block_name_prefix) + 1;
+      set<string>::iterator it = obj_checker.find(block_name_suffix);
+      ASSERT_TRUE(it != obj_checker.end());
+      obj_checker.erase(it);
+    }
+  }
+  rados_nobjects_list_close(list_ctx);
+  ASSERT_TRUE(obj_checker.empty());
+  ASSERT_EQ(0, image.close());
+
+  rados_ioctx_destroy(d_ioctx);
+}
+
+TEST_F(TestInternal, FlattenNoEmptyObjects)
+{
+  REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
+
+  m_image_name = get_temp_image_name();
+  m_image_size = 4 << 20;
+
+  int order = 12; // smallest object size is 4K
+  uint64_t features;
+  ASSERT_TRUE(get_features(&features));
+
+  ASSERT_EQ(0, create_image_full_pp(m_rbd, m_ioctx, m_image_name, m_image_size,
+                                    features, false, &order));
+
+  librbd::Image image;
+  ASSERT_EQ(0, m_rbd.open(m_ioctx, image, m_image_name.c_str(), NULL));
+
+  librbd::image_info_t info;
+  ASSERT_EQ(0, image.stat(info, sizeof(info)));
+
+  const int object_num = info.size / info.obj_size;
+  printf("made parent image \"%s\": %ldK (%d * %ldK)\n", m_image_name.c_str(),
+         (unsigned long)m_image_size, object_num, info.obj_size/1024);
+
+  // write something into parent
+  char test_data[TEST_IO_SIZE + 1];
+  for (int i = 0; i < TEST_IO_SIZE; ++i) {
+    test_data[i] = (char) (rand() % (126 - 33) + 33);
+  }
+  test_data[TEST_IO_SIZE] = '\0';
+
+  // generate a random map which covers every objects with random
+  // offset
+  map<uint64_t, uint64_t> write_tracker;
+  generate_random_iomap(image, object_num, info.obj_size, 100, write_tracker);
+
+  printf("generated random write map:\n");
+  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
+       itr != write_tracker.end(); ++itr)
+    printf("\t [%-8ld, %-8ld]\n",
+           (unsigned long)itr->first, (unsigned long)itr->second);
+
+  bufferlist bl;
+  bl.append(test_data, TEST_IO_SIZE);
+
+  printf("write data based on random map\n");
+  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
+       itr != write_tracker.end(); ++itr) {
+    printf("\twrite object-%-4ld\t\n", (unsigned long)itr->first);
+    ASSERT_EQ(TEST_IO_SIZE, image.write(itr->second, TEST_IO_SIZE, bl));
+  }
+
+  bufferlist readbl;
+  printf("verify written data by reading\n");
+  {
+    map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
+    printf("\tread object-%-4ld\n", (unsigned long)itr->first);
+    ASSERT_EQ(TEST_IO_SIZE, image.read(itr->second, TEST_IO_SIZE, readbl));
+    ASSERT_TRUE(readbl.contents_equal(bl));
+  }
+
+  int64_t data_pool_id = image.get_data_pool_id();
+  rados_ioctx_t d_ioctx;
+  rados_ioctx_create2(_cluster, data_pool_id, &d_ioctx);
+
+  const char *entry;
+  rados_list_ctx_t list_ctx;
+  set<string> obj_checker;
+  ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx));
+  while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) {
+    if (strstr(entry, info.block_name_prefix)) {
+      const char *block_name_suffix = entry + strlen(info.block_name_prefix) + 1;
+      obj_checker.insert(block_name_suffix);
+    }
+  }
+  rados_nobjects_list_close(list_ctx);
+
+  std::string snapname = "snap";
+  std::string clonename = get_temp_image_name();
+  ASSERT_EQ(0, image.snap_create(snapname.c_str()));
+  ASSERT_EQ(0, image.close());
+  ASSERT_EQ(0, m_rbd.open(m_ioctx, image, m_image_name.c_str(), snapname.c_str()));
+  ASSERT_EQ(0, image.snap_protect(snapname.c_str()));
+  printf("made snapshot \"%s@parent_snap\" and protect it\n", m_image_name.c_str());
+
+  ASSERT_EQ(0, clone_image_pp(m_rbd, image, m_ioctx, m_image_name.c_str(), snapname.c_str(),
+                              m_ioctx, clonename.c_str(), features));
+  ASSERT_EQ(0, image.close());
+
+  ASSERT_EQ(0, m_rbd.open(m_ioctx, image, clonename.c_str(), NULL));
+  printf("made and opened clone \"%s\"\n", clonename.c_str());
+
+  printf("flattening clone: \"%s\"\n", clonename.c_str());
+  ASSERT_EQ(0, image.flatten());
+
+  printf("check whether child image has the same set of objects as parent\n");
+  ASSERT_EQ(0, image.stat(info, sizeof(info)));
+
+  ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx));
+  while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) {
+    if (strstr(entry, info.block_name_prefix)) {
+      const char *block_name_suffix = entry + strlen(info.block_name_prefix) + 1;
+      set<string>::iterator it = obj_checker.find(block_name_suffix);
+      ASSERT_TRUE(it != obj_checker.end());
+      obj_checker.erase(it);
+    }
+  }
+  rados_nobjects_list_close(list_ctx);
+  ASSERT_TRUE(obj_checker.empty());
+  ASSERT_EQ(0, image.close());
+
+  rados_ioctx_destroy(d_ioctx);
+}
index 46f22decb0d77e54062d095a3e1bd08e48fb1afb..d65f2b3841815877aef2a39cad738d89dc8817d7 100644 (file)
@@ -50,9 +50,6 @@
 #include "include/interval_set.h"
 #include "include/stringify.h"
 
-#include "global/global_context.h"
-#include "osdc/Striper.h"
-
 #include <boost/assign/list_of.hpp>
 #include <boost/scope_exit.hpp>
 
@@ -1208,11 +1205,6 @@ TEST_F(TestLibRBD, TestCreateLsRenameSnapPP)
   ioctx.close();
 }
 
-
-
-#define TEST_IO_SIZE 512
-#define TEST_IO_TO_SNAP_SIZE 80
-
 void simple_write_cb(rbd_completion_t cb, void *arg)
 {
   printf("write completion cb called!\n");
@@ -1289,51 +1281,6 @@ void write_test_data(rbd_image_t image, const char *test_data, uint64_t off, siz
   *passed = true;
 }
 
-void generate_random_iomap(rbd_image_t image, int num_objects, int object_size,
-                           int max_count, map<uint64_t, uint64_t> &iomap)
-{
-  uint64_t stripe_unit, stripe_count;
-
-  ASSERT_EQ(0, rbd_get_stripe_unit(image, &stripe_unit));
-  ASSERT_EQ(0, rbd_get_stripe_count(image, &stripe_count));
-
-  while (max_count-- > 0) {
-    // generate random image offset based on base random object
-    // number and object offset and then map that back to an
-    // object number based on stripe unit and count.
-    uint64_t ono = rand() % num_objects;
-    uint64_t offset = rand() % (object_size - TEST_IO_SIZE);
-    uint64_t imageoff = (ono * object_size) + offset;
-
-    file_layout_t layout;
-    layout.object_size = object_size;
-    layout.stripe_unit = stripe_unit;
-    layout.stripe_count = stripe_count;
-
-    vector<ObjectExtent> ex;
-    Striper::file_to_extents(g_ceph_context, 1, &layout, imageoff, TEST_IO_SIZE, 0, ex);
-
-    // lets not worry if IO spans multiple extents (>1 object). in such
-    // as case we would perform the write multiple times to the same
-    // offset, but we record all objects that would be generated with
-    // this IO. TODO: fix this if such a need is required by your
-    // test.
-    vector<ObjectExtent>::iterator it;
-    map<uint64_t, uint64_t> curr_iomap;
-    for (it = ex.begin(); it != ex.end(); ++it) {
-      if (iomap.find((*it).objectno) != iomap.end()) {
-        break;
-      }
-
-      curr_iomap.insert(make_pair((*it).objectno, imageoff));
-    }
-
-    if (it == ex.end()) {
-      iomap.insert(curr_iomap.begin(), curr_iomap.end());
-    }
-  }
-}
-
 void aio_discard_test_data(rbd_image_t image, uint64_t off, uint64_t len, bool *passed)
 {
   rbd_completion_t comp;
@@ -2610,151 +2557,6 @@ TEST_F(TestLibRBD, TestClone2)
   rados_ioctx_destroy(ioctx);
 }
 
-TEST_F(TestLibRBD, TestCoR)
-{
-  REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
-
-  std::string config_value;
-  ASSERT_EQ(0, _rados.conf_get("rbd_clone_copy_on_read", config_value));
-  if (config_value == "false") {
-    std::cout << "SKIPPING due to disabled rbd_copy_on_read" << std::endl;
-    return;
-  }
-
-  bool old_format;
-  uint64_t features;
-  ASSERT_EQ(0, get_features(&old_format, &features));
-  ASSERT_FALSE(old_format);
-
-  rados_ioctx_t ioctx;
-  rados_ioctx_create(_cluster, m_pool_name.c_str(), &ioctx);
-
-  rbd_image_t parent, child;
-  int order = 12; // smallest object size is 4K
-  const uint64_t image_size = 4<<20;
-  const int object_size = 1<<12;
-  const int object_num = image_size / object_size;
-  map<uint64_t, uint64_t> write_tracker;
-  set<string> obj_checker;
-  rbd_image_info_t p_info, c_info;
-  rados_list_ctx_t list_ctx;
-  const char *entry;
-
-  // make a parent to clone from
-  ASSERT_EQ(0, create_image_full(ioctx, "parent", image_size, &order, false, features));
-  ASSERT_EQ(0, rbd_open(ioctx, "parent", &parent, NULL));
-  printf("made parent image \"parent\": %ldK (%d * %dK)\n",
-         (unsigned long)image_size, object_num, object_size/1024);
-
-  // write something into parent
-  char test_data[TEST_IO_SIZE + 1];
-  char zero_data[TEST_IO_SIZE + 1];
-  int i;
-
-  for (i = 0; i < TEST_IO_SIZE; ++i) 
-    test_data[i] = (char) (rand() % (126 - 33) + 33);
-  test_data[TEST_IO_SIZE] = '\0';
-  memset(zero_data, 0, sizeof(zero_data));
-
-  // generate a random map which covers every objects with random
-  // offset
-  generate_random_iomap(parent, object_num, object_size, 100, write_tracker);
-
-  printf("generated random write map:\n");
-  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
-       itr != write_tracker.end(); ++itr)
-    printf("\t [%-8ld, %-8ld]\n",
-           (unsigned long)itr->first, (unsigned long)itr->second);
-
-  printf("write data based on random map\n");
-  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
-       itr != write_tracker.end(); ++itr) {
-    printf("\twrite object-%-4ld\t", (unsigned long)itr->first);
-    ASSERT_PASSED(write_test_data, parent, test_data, itr->second, TEST_IO_SIZE, 0);
-  }
-
-  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
-         itr != write_tracker.end(); ++itr) {
-    printf("\tread object-%-4ld\t", (unsigned long)itr->first);
-    ASSERT_PASSED(read_test_data, parent, test_data, itr->second, TEST_IO_SIZE, 0);
-  }
-
-  // find out what objects the parent image has generated
-  ASSERT_EQ(0, rbd_stat(parent, &p_info, sizeof(p_info)));
-
-  int64_t data_pool_id = rbd_get_data_pool_id(parent);
-  rados_ioctx_t d_ioctx;
-  rados_ioctx_create2(_cluster, data_pool_id, &d_ioctx);
-
-  ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx));
-  while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) {
-    if (strstr(entry, p_info.block_name_prefix)) {
-      const char *block_name_suffix = entry + strlen(p_info.block_name_prefix) + 1;
-      obj_checker.insert(block_name_suffix);
-    }
-  }
-  rados_nobjects_list_close(list_ctx);
-  ASSERT_EQ(obj_checker.size(), write_tracker.size());
-
-  // create a snapshot, reopen as the parent we're interested in and protect it
-  ASSERT_EQ(0, rbd_snap_create(parent, "parent_snap"));
-  ASSERT_EQ(0, rbd_close(parent));
-  ASSERT_EQ(0, rbd_open(ioctx, "parent", &parent, "parent_snap"));
-  ASSERT_EQ(0, rbd_snap_protect(parent, "parent_snap"));
-  ASSERT_PASSED(validate_object_map, parent);
-  ASSERT_EQ(0, rbd_close(parent));
-  printf("made snapshot \"parent@parent_snap\" and protect it\n");
-
-  // create a copy-on-read clone and open it
-  ASSERT_EQ(0, clone_image(ioctx, parent, "parent",
-                           "parent_snap", ioctx, "child", features, &order));
-  ASSERT_EQ(0, rbd_open(ioctx, "child", &child, NULL));
-  printf("made and opened clone \"child\"\n");
-
-  printf("read from \"child\"\n");
-  {
-    map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
-    printf("\tread object-%-4ld\t", (unsigned long)itr->first);
-    ASSERT_PASSED(read_test_data, child, test_data, itr->second, TEST_IO_SIZE, 0);
-  }
-
-  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
-       itr != write_tracker.end(); ++itr) {
-    printf("\tread object-%-4ld\t", (unsigned long)itr->first);
-    ASSERT_PASSED(read_test_data, child, test_data, itr->second, TEST_IO_SIZE, 0);
-  }
-
-  printf("read again reversely\n");
-  for (map<uint64_t, uint64_t>::iterator itr = --write_tracker.end();
-     itr != write_tracker.begin(); --itr) {
-    printf("\tread object-%-4ld\t", (unsigned long)itr->first);
-    ASSERT_PASSED(read_test_data, child, test_data, itr->second, TEST_IO_SIZE, 0);
-  }
-
-  // close child to flush all copy-on-read
-  ASSERT_EQ(0, rbd_close(child));
-
-  printf("check whether child image has the same set of objects as parent\n");
-  ASSERT_EQ(0, rbd_open(ioctx, "child", &child, NULL));
-  ASSERT_EQ(0, rbd_stat(child, &c_info, sizeof(c_info)));
-  ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx));
-  while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) {
-    if (strstr(entry, c_info.block_name_prefix)) {
-      const char *block_name_suffix = entry + strlen(c_info.block_name_prefix) + 1;
-      set<string>::iterator it = obj_checker.find(block_name_suffix);
-      ASSERT_TRUE(it != obj_checker.end());
-      obj_checker.erase(it);
-    }
-  }
-  rados_nobjects_list_close(list_ctx);
-  ASSERT_TRUE(obj_checker.empty());
-  ASSERT_PASSED(validate_object_map, child);
-  ASSERT_EQ(0, rbd_close(child));
-
-  rados_ioctx_destroy(ioctx);
-  rados_ioctx_destroy(d_ioctx);
-}
-
 static void test_list_children(rbd_image_t image, ssize_t num_expected, ...)
 {
   va_list ap;
@@ -3898,131 +3700,6 @@ TEST_F(TestLibRBD, Flatten)
   ASSERT_PASSED(validate_object_map, clone_image);
 }
 
-TEST_F(TestLibRBD, FlattenNoEmptyObjects)
-{
-  REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
-
-  rados_ioctx_t ioctx;
-  rados_ioctx_create(_cluster, m_pool_name.c_str(), &ioctx);
-
-  librbd::RBD rbd;
-  std::string parent_name = get_temp_image_name();
-  uint64_t size = 4 << 20;
-  int order = 13; // smallest object size is 4K
-
-  bool old_format;
-  uint64_t features;
-  ASSERT_EQ(0, get_features(&old_format, &features));
-  ASSERT_FALSE(old_format);
-
-  // make a parent to clone from
-  ASSERT_EQ(0, create_image_full(ioctx, parent_name.c_str(), size, &order,
-                                 false, features));
-
-  rbd_image_t parent;
-  const int object_size = 1 << order;
-  const int object_num = size / object_size;
-  ASSERT_EQ(0, rbd_open(ioctx, parent_name.c_str(), &parent, NULL));
-  printf("made parent image \"%s\": %ldK (%d * %dK)\n", parent_name.c_str(),
-         (unsigned long)size, object_num, object_size/1024);
-
-  // write something into parent
-  char test_data[TEST_IO_SIZE + 1];
-  char zero_data[TEST_IO_SIZE + 1];
-  int i;
-  for (i = 0; i < TEST_IO_SIZE; ++i)
-    test_data[i] = (char) (rand() % (126 - 33) + 33);
-  test_data[TEST_IO_SIZE] = '\0';
-  memset(zero_data, 0, sizeof(zero_data));
-
-  // generate a random map which covers every objects with random
-  // offset
-  map<uint64_t, uint64_t> write_tracker;
-  generate_random_iomap(parent, object_num, object_size, 10, write_tracker);
-
-  printf("generated random write map:\n");
-  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
-       itr != write_tracker.end(); ++itr)
-    printf("\t [%-8ld, %-8ld]\n",
-          (unsigned long)itr->first, (unsigned long)itr->second);
-
-  printf("write data based on random map\n");
-  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
-       itr != write_tracker.end(); ++itr) {
-    printf("\twrite object-%-4ld\t", (unsigned long)itr->first);
-    ASSERT_PASSED(write_test_data, parent, test_data, itr->second, TEST_IO_SIZE, 0);
-  }
-
-  for (map<uint64_t, uint64_t>::iterator itr = write_tracker.begin();
-         itr != write_tracker.end(); ++itr) {
-    printf("\tread object-%-4ld\t", (unsigned long)itr->first);
-    ASSERT_PASSED(read_test_data, parent, test_data, itr->second, TEST_IO_SIZE, 0);
-  }
-
-  // find out what objects the parent image has generated
-  rbd_image_info_t p_info;
-  ASSERT_EQ(0, rbd_stat(parent, &p_info, sizeof(p_info)));
-
-  int64_t data_pool_id = rbd_get_data_pool_id(parent);
-  rados_ioctx_t d_ioctx;
-  rados_ioctx_create2(_cluster, data_pool_id, &d_ioctx);
-
-  const char *entry;
-  set<string> obj_checker;
-  rados_list_ctx_t list_ctx;
-  ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx));
-  while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) {
-    if (strstr(entry, p_info.block_name_prefix)) {
-      const char *block_name_suffix = entry + strlen(p_info.block_name_prefix) + 1;
-      printf("parent object: %s\n", entry);
-      obj_checker.insert(block_name_suffix);
-    }
-  }
-  rados_nobjects_list_close(list_ctx);
-  ASSERT_EQ(obj_checker.size(), write_tracker.size());
-
-  // create a snapshot, reopen as the parent we're interested in and protect it
-  ASSERT_EQ(0, rbd_snap_create(parent, "parent_snap"));
-  ASSERT_EQ(0, rbd_close(parent));
-  ASSERT_EQ(0, rbd_open(ioctx, parent_name.c_str(), &parent, "parent_snap"));
-  ASSERT_EQ(0, rbd_snap_protect(parent, "parent_snap"));
-  ASSERT_PASSED(validate_object_map, parent);
-  ASSERT_EQ(0, rbd_close(parent));
-  printf("made snapshot and protected: \"%s@parent_snap\"\n", parent_name.c_str());
-
-  std::string child_name = get_temp_image_name();
-  ASSERT_EQ(0, clone_image(ioctx, parent, parent_name.c_str(),
-                                  "parent_snap", ioctx, child_name.c_str(), features, &order));
-
-  rbd_image_t child;
-  ASSERT_EQ(0, rbd_open(ioctx, child_name.c_str(), &child, NULL));
-  printf("made and opened clone \"%s\"\n", child_name.c_str());
-
-  printf("flattening clone: \"%s\"\n", child_name.c_str());
-  ASSERT_EQ(0, rbd_flatten(child));
-
-  printf("check whether child image has the same set of objects as parent\n");
-  rbd_image_info_t c_info;
-  ASSERT_EQ(0, rbd_stat(child, &c_info, sizeof(c_info)));
-  ASSERT_EQ(0, rados_nobjects_list_open(d_ioctx, &list_ctx));
-  while (rados_nobjects_list_next(list_ctx, &entry, NULL, NULL) != -ENOENT) {
-    if (strstr(entry, c_info.block_name_prefix)) {
-      const char *block_name_suffix = entry + strlen(c_info.block_name_prefix) + 1;
-      set<string>::iterator it = obj_checker.find(block_name_suffix);
-      printf("child object: %s\n", entry);
-      ASSERT_TRUE(it != obj_checker.end());
-      obj_checker.erase(it);
-    }
-  }
-  rados_nobjects_list_close(list_ctx);
-  ASSERT_TRUE(obj_checker.empty());
-  ASSERT_PASSED(validate_object_map, child);
-  ASSERT_EQ(0, rbd_close(child));
-
-  rados_ioctx_destroy(ioctx);
-  rados_ioctx_destroy(d_ioctx);
-}
-
 TEST_F(TestLibRBD, SnapshotLimit)
 {
   rados_ioctx_t ioctx;
index 16e76a65147d7466d258a7d088b7eb9979d0252a..47707b1c015690934e700a8adbcc2450f7eda70b 100644 (file)
@@ -8,6 +8,9 @@
 static const uint64_t IMAGE_STRIPE_UNIT = 65536;
 static const uint64_t IMAGE_STRIPE_COUNT = 16;
 
+#define TEST_IO_SIZE 512
+#define TEST_IO_TO_SNAP_SIZE 80
+
 bool get_features(uint64_t *features);
 bool is_feature_enabled(uint64_t feature);
 int create_image_pp(librbd::RBD &rbd, librados::IoCtx &ioctx,