]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: move c++ tests to gtest
authorSage Weil <sage@newdream.net>
Mon, 12 Sep 2011 17:55:08 +0000 (10:55 -0700)
committerSage Weil <sage@newdream.net>
Mon, 12 Sep 2011 17:55:08 +0000 (10:55 -0700)
Signed-off-by: Sage Weil <sage@newdream.net>
src/Makefile.am
src/test/test_librbd.cc
src/testlibrbdpp.cc [deleted file]

index a89304964fd633fd2cf37ba430300d377a447a2d..ba08c301c81d11b94e761679f656c456523260f0 100644 (file)
@@ -294,11 +294,6 @@ rbd_CXXFLAGS = ${AM_CXXFLAGS}
 rbd_LDADD = libglobal.la librbd.la librados.la -lpthread -lm -lkeyutils $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += rbd
 
-testlibrbdpp_SOURCES = testlibrbdpp.cc
-testlibrbdpp_LDADD = librbd.la librados.la -lpthread -lm \
-                    $(CRYPTO_LIBS) $(EXTRALIBS)
-bin_DEBUGPROGRAMS += testlibrbd testlibrbdpp
-
 if WITH_RADOSGW
 my_libradosgw_src = \
        rgw/librgw.cc \
index 43d78082bcac4dc711ed699bbb3478dc26381ec4..53d7d3cac8e61c77034db401cd87ca88cccf1c32 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "include/rados/librados.h"
 #include "include/rbd/librbd.h"
+#include "include/rbd/librbd.hpp"
 
 #include "gtest/gtest.h"
 
 #include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
+#include <iostream>
+#include <algorithm>
 
 #include "rados-api/test.cc"
 
+using namespace std;
+
 TEST(LibRBD, CreateAndStat)
 {
   rados_t cluster;
   rados_ioctx_t ioctx;
-  std::string pool_name = get_temp_pool_name();
+  string pool_name = get_temp_pool_name();
   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
-  rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
+  ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
 
   rbd_image_info_t info;
   rbd_image_t image;
@@ -54,11 +59,39 @@ TEST(LibRBD, CreateAndStat)
   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
 }
 
+TEST(LibRBD, CreateAndStatPP)
+{
+  librados::Rados rados;
+  librados::IoCtx ioctx;
+  string pool_name = get_temp_pool_name();
+
+  ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
+  ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
+
+  {
+    librbd::RBD rbd;
+    librbd::image_info_t info;
+    librbd::Image image;
+    int order = 0;
+    const char *name = "testimg";
+    uint64_t size = 2 << 20;
+    
+    ASSERT_EQ(0, rbd.create(ioctx, name, size, &order));
+    ASSERT_EQ(0, rbd.open(ioctx, image, name, NULL));
+    ASSERT_EQ(0, image.stat(info, sizeof(info)));
+    ASSERT_EQ(info.size, size);
+    ASSERT_EQ(info.order, order);
+  }
+
+  ioctx.close();
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
+}
+
 TEST(LibRBD, ResizeAndStat)
 {
   rados_t cluster;
   rados_ioctx_t ioctx;
-  std::string pool_name = get_temp_pool_name();
+  string pool_name = get_temp_pool_name();
   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
 
@@ -85,6 +118,38 @@ TEST(LibRBD, ResizeAndStat)
   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
 }
 
+TEST(LibRBD, ResizeAndStatPP)
+{
+  librados::Rados rados;
+  librados::IoCtx ioctx;
+  string pool_name = get_temp_pool_name();
+
+  ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
+  ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
+
+  {
+    librbd::RBD rbd;
+    librbd::image_info_t info;
+    librbd::Image image;
+    int order = 0;
+    const char *name = "testimg";
+    uint64_t size = 2 << 20;
+    
+    ASSERT_EQ(0, rbd.create(ioctx, name, size, &order));
+    ASSERT_EQ(0, rbd.open(ioctx, image, name, NULL));
+    
+    ASSERT_EQ(0, image.resize(size * 4));
+    ASSERT_EQ(0, image.stat(info, sizeof(info)));
+    ASSERT_EQ(info.size, size * 4);
+    
+    ASSERT_EQ(0, image.resize(size / 2));
+    ASSERT_EQ(0, image.stat(info, sizeof(info)));
+    ASSERT_EQ(info.size, size / 2);
+  }
+
+  ioctx.close();
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
+}
 
 int test_ls(rados_ioctx_t io_ctx, size_t num_expected, ...)
 {
@@ -136,7 +201,7 @@ TEST(LibRBD, TestCreateLsDelete)
 {
   rados_t cluster;
   rados_ioctx_t ioctx;
-  std::string pool_name = get_temp_pool_name();
+  string pool_name = get_temp_pool_name();
   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
 
@@ -156,6 +221,67 @@ TEST(LibRBD, TestCreateLsDelete)
   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
 }
 
+int test_ls_pp(librbd::RBD& rbd, librados::IoCtx& io_ctx, size_t num_expected, ...)
+{
+  int r;
+  size_t i;
+  char *expected;
+  va_list ap;
+  vector<string> names;
+  r = rbd.list(io_ctx, names);
+  if (r == -ENOENT)
+    r = 0;
+  assert(r >= 0);
+  cout << "num images is: " << names.size() << endl
+           << "expected: " << num_expected << endl;
+  int num = names.size();
+
+  for (i = 0; i < names.size(); i++) {
+    cout << "image: " << names[i] << endl;
+  }
+
+  va_start(ap, num_expected);
+  for (i = num_expected; i > 0; i--) {
+    expected = va_arg(ap, char *);
+    cout << "expected = " << expected << endl;
+    vector<string>::iterator listed_name = find(names.begin(), names.end(), string(expected));
+    assert(listed_name != names.end());
+    names.erase(listed_name);
+  }
+  assert(names.empty());
+
+  return num;
+}
+
+TEST(LibRBD, TestCreateLsDeletePP)
+{
+  librados::Rados rados;
+  librados::IoCtx ioctx;
+  string pool_name = get_temp_pool_name();
+
+  ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
+  ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
+
+  {
+    librbd::RBD rbd;
+    librbd::Image image;
+    int order = 0;
+    const char *name = "testimg";
+    const char *name2 = "testimg2";
+    uint64_t size = 2 << 20;  
+    
+    ASSERT_EQ(0, rbd.create(ioctx, name, size, &order));
+    ASSERT_EQ(1, test_ls_pp(rbd, ioctx, 1, name));
+    ASSERT_EQ(0, rbd.create(ioctx, name2, size, &order));
+    ASSERT_EQ(2, test_ls_pp(rbd, ioctx, 2, name, name2));
+    ASSERT_EQ(0, rbd.remove(ioctx, name));
+    ASSERT_EQ(1, test_ls_pp(rbd, ioctx, 1, name2));
+  }
+
+  ioctx.close();
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
+}
+
 
 static int print_progress_percent(uint64_t offset, uint64_t src_size,
                                     void *data)
@@ -169,7 +295,7 @@ TEST(LibRBD, TestCopy)
 {
   rados_t cluster;
   rados_ioctx_t ioctx;
-  std::string pool_name = get_temp_pool_name();
+  string pool_name = get_temp_pool_name();
   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
 
@@ -195,6 +321,49 @@ TEST(LibRBD, TestCopy)
   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
 }
 
+class PrintProgress : public librbd::ProgressContext
+{
+public:
+  int update_progress(uint64_t offset, uint64_t src_size)
+  {
+    float percent = ((float)offset * 100) / src_size;
+    printf("%3.2f%% done\n", percent);
+    return 0;
+  }
+};
+
+TEST(LibRBD, TestCopyPP)
+{
+  librados::Rados rados;
+  librados::IoCtx ioctx;
+  string pool_name = get_temp_pool_name();
+  
+  ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
+  ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
+
+  {
+    librbd::RBD rbd;
+    librbd::Image image;
+    int order = 0;
+    const char *name = "testimg";
+    const char *name2 = "testimg2";
+    const char *name3 = "testimg3";
+    uint64_t size = 2 << 20;
+    PrintProgress pp;
+
+    ASSERT_EQ(0, rbd.create(ioctx, name, size, &order));
+    ASSERT_EQ(0, rbd.open(ioctx, image, name, NULL));
+    ASSERT_EQ(1, test_ls_pp(rbd, ioctx, 1, name));
+    ASSERT_LT(0, image.copy(ioctx, name2));
+    ASSERT_EQ(2, test_ls_pp(rbd, ioctx, 2, name, name2));
+    ASSERT_LT(0, image.copy_with_progress(ioctx, name3, pp));
+    ASSERT_EQ(3, test_ls_pp(rbd, ioctx, 3, name, name2, name3));
+  }
+
+  ioctx.close();
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
+}
+
 int test_ls_snaps(rbd_image_t image, int num_expected, ...)
 {
   rbd_snap_info_t *snaps;
@@ -242,7 +411,7 @@ TEST(LibRBD, TestCreateLsDeleteSnap)
 {
   rados_t cluster;
   rados_ioctx_t ioctx;
-  std::string pool_name = get_temp_pool_name();
+  string pool_name = get_temp_pool_name();
   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
 
@@ -271,6 +440,84 @@ TEST(LibRBD, TestCreateLsDeleteSnap)
   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
 }
 
+int test_ls_snaps(librbd::Image& image, size_t num_expected, ...)
+{
+  int r;
+  size_t i, j, expected_size;
+  char *expected;
+  va_list ap;
+  vector<librbd::snap_info_t> snaps;
+  r = image.snap_list(snaps);
+  assert(r >= 0);
+  cout << "num snaps is: " << snaps.size() << endl
+           << "expected: " << num_expected << endl;
+
+  for (i = 0; i < snaps.size(); i++) {
+    cout << "snap: " << snaps[i].name << endl;
+  }
+
+  va_start(ap, num_expected);
+  for (i = num_expected; i > 0; i--) {
+    expected = va_arg(ap, char *);
+    expected_size = va_arg(ap, int);
+    int found = 0;
+    for (j = 0; j < snaps.size(); j++) {
+      if (snaps[j].name == "")
+       continue;
+      if (strcmp(snaps[j].name.c_str(), expected) == 0) {
+       cout << "found " << snaps[j].name << " with size " << snaps[j].size << endl;
+       assert(snaps[j].size == (size_t) expected_size);
+       snaps[j].name = "";
+       found = 1;
+       break;
+      }
+    }
+    assert(found);
+  }
+
+  for (i = 0; i < snaps.size(); i++) {
+    assert(snaps[i].name == "");
+  }
+
+  return snaps.size();
+}
+
+TEST(LibRBD, TestCreateLsDeleteSnapPP)
+{
+  librados::Rados rados;
+  librados::IoCtx ioctx;
+  string pool_name = get_temp_pool_name();
+
+  ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
+  ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
+
+  {
+    librbd::RBD rbd;
+    librbd::Image image;
+    int order = 0;
+    const char *name = "testimg";
+    uint64_t size = 2 << 20;
+    uint64_t size2 = 4 << 20;
+    
+    ASSERT_EQ(0, rbd.create(ioctx, name, size, &order));
+    ASSERT_EQ(0, rbd.open(ioctx, image, name, NULL));
+
+    ASSERT_EQ(0, image.snap_create("snap1"));
+    ASSERT_EQ(1, test_ls_snaps(image, 1, "snap1", size));
+    ASSERT_EQ(0, image.resize(size2));
+    ASSERT_EQ(0, image.snap_create("snap2"));
+    ASSERT_EQ(2, test_ls_snaps(image, 2, "snap1", size, "snap2", size2));
+    ASSERT_EQ(0, image.snap_remove("snap1"));
+    ASSERT_EQ(1, test_ls_snaps(image, 1, "snap2", size2));
+    ASSERT_EQ(0, image.snap_remove("snap2"));
+    ASSERT_EQ(0, test_ls_snaps(image, 0));
+  }
+
+  ioctx.close();
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
+}
+
+
 
 #define TEST_IO_SIZE 512
 #define TEST_IO_TO_SNAP_SIZE 80
@@ -347,7 +594,7 @@ TEST(LibRBD, TestIO)
 {
   rados_t cluster;
   rados_ioctx_t ioctx;
-  std::string pool_name = get_temp_pool_name();
+  string pool_name = get_temp_pool_name();
   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
 
@@ -394,11 +641,124 @@ TEST(LibRBD, TestIO)
   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
 }
 
+
+void simple_write_cb_pp(librbd::completion_t cb, void *arg)
+{
+  cout << "write completion cb called!" << endl;
+}
+
+void simple_read_cb_pp(librbd::completion_t cb, void *arg)
+{
+  cout << "read completion cb called!" << endl;
+}
+
+void aio_write_test_data(librbd::Image& image, const char *test_data, off_t off)
+{
+  ceph::bufferlist bl;
+  bl.append(test_data, strlen(test_data));
+  librbd::RBD::AioCompletion *comp = new librbd::RBD::AioCompletion(NULL, (librbd::callback_t) simple_write_cb_pp);
+  printf("created completion\n");
+  image.aio_write(off, strlen(test_data), bl, comp);
+  printf("started write\n");
+  comp->wait_for_complete();
+  int r = comp->get_return_value();
+  printf("return value is: %d\n", r);
+  assert(r >= 0);
+  printf("finished write\n");
+  comp->release();
+}
+
+void write_test_data(librbd::Image& image, const char *test_data, off_t off)
+{
+  int written;
+  size_t len = strlen(test_data);
+  ceph::bufferlist bl;
+  bl.append(test_data, len);
+  written = image.write(off, len, bl);
+  printf("wrote: %u\n", (unsigned int) written);
+  assert(written == bl.length());
+}
+
+void aio_read_test_data(librbd::Image& image, const char *expected, off_t off)
+{
+  librbd::RBD::AioCompletion *comp = new librbd::RBD::AioCompletion(NULL, (librbd::callback_t) simple_read_cb_pp);
+  ceph::bufferlist bl;
+  printf("created completion\n");
+  image.aio_read(off, strlen(expected), bl, comp);
+  printf("started read\n");
+  comp->wait_for_complete();
+  int r = comp->get_return_value();
+  printf("return value is: %d\n", r);
+  assert(r == TEST_IO_SIZE - 1);
+  assert(strncmp(expected, bl.c_str(), TEST_IO_SIZE - 1) == 0);
+  printf("finished read\n");
+  comp->release();
+}
+
+void read_test_data(librbd::Image& image, const char *expected, off_t off)
+{
+  int read, total_read = 0;
+  size_t expected_len = strlen(expected);
+  size_t len = expected_len;
+  ceph::bufferlist bl;
+  read = image.read(off + total_read, len, bl);
+  assert(read >= 0);
+  printf("read: %u\n", (unsigned int) read);
+  printf("read: %s\nexpected: %s\n", bl.c_str(), expected);
+  assert(strncmp(bl.c_str(), expected, expected_len) == 0);
+}
+
+TEST(LibRBD, TestIOPP) 
+{
+  librados::Rados rados;
+  librados::IoCtx ioctx;
+  string pool_name = get_temp_pool_name();
+
+  ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
+  ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
+
+  {
+    librbd::RBD rbd;
+    librbd::Image image;
+    int order = 0;
+    const char *name = "testimg";
+    uint64_t size = 2 << 20;
+    
+    ASSERT_EQ(0, rbd.create(ioctx, name, size, &order));
+    ASSERT_EQ(0, rbd.open(ioctx, image, name, NULL));
+
+    char test_data[TEST_IO_SIZE];
+    int i;
+    
+    srand(time(0));
+    for (i = 0; i < TEST_IO_SIZE - 1; ++i) {
+      test_data[i] = (char) (rand() % (126 - 33) + 33);
+    }
+    test_data[TEST_IO_SIZE - 1] = '\0';
+    
+    for (i = 0; i < 5; ++i)
+      write_test_data(image, test_data, strlen(test_data) * i);
+    
+    for (i = 5; i < 10; ++i)
+      aio_write_test_data(image, test_data, strlen(test_data) * i);
+    
+    for (i = 0; i < 5; ++i)
+      read_test_data(image, test_data, strlen(test_data) * i);
+    
+    for (i = 5; i < 10; ++i)
+      aio_read_test_data(image, test_data, strlen(test_data) * i);
+  }
+
+  ioctx.close();
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
+}
+
+
 TEST(LibRBD, TestIOToSnapshot)
 {
   rados_t cluster;
   rados_ioctx_t ioctx;
-  std::string pool_name = get_temp_pool_name();
+  string pool_name = get_temp_pool_name();
   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
   rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
 
diff --git a/src/testlibrbdpp.cc b/src/testlibrbdpp.cc
deleted file mode 100644 (file)
index 319ff52..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2011 New Dream Network
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License version 2, as published by the Free Software
- * Foundation.  See file COPYING.
- *
- */
-
-#include "include/assert.h"
-#include "include/rbd/librbd.hpp"
-#include "include/rados/librados.hpp"
-#include "include/buffer.h"
-
-#include <algorithm>
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
-#include <ctime>
-#include <errno.h>
-#include <memory>
-#include <sys/types.h>
-#include <string>
-#include <vector>
-
-using namespace std;
-
-#define TEST_IMAGE "testimg"
-#define TEST_IMAGE2 "testimg2"
-#define TEST_POOL "librbdtest"
-#define TEST_SNAP "testsnap"
-#define TEST_IO_SIZE 513
-#define MB_BYTES(mb) (mb << 20)
-
-librbd::RBD *rbd;
-
-void test_create_and_stat(librados::IoCtx& io_ctx, const char *name, size_t size)
-{
-  librbd::image_info_t info;
-  librbd::Image image;
-  int order = 0;
-  assert(rbd->create(io_ctx, name, size, &order) == 0);
-  assert(rbd->open(io_ctx, image, name, NULL) == 0);
-  assert(image.stat(info, sizeof(info)) == 0);
-  cout << "image has size " << info.size << " and order " << info.order << endl;
-  assert(info.size == size);
-  assert(info.order == order);
-}
-
-void test_resize_and_stat(librbd::Image& image, size_t size)
-{
-  librbd::image_info_t info;
-  assert(image.resize(size) == 0);
-  assert(image.stat(info, sizeof(info)) == 0);
-  cout << "image has size " << info.size << " and order " << info.order << endl;
-  assert(info.size == size);
-}
-
-void test_ls(librados::IoCtx& io_ctx, size_t num_expected, ...)
-{
-  int r;
-  size_t i;
-  char *expected;
-  va_list ap;
-  vector<string> names;
-  r = rbd->list(io_ctx, names);
-  if (r == -ENOENT)
-    r = 0;
-  assert(r >= 0);
-  cout << "num images is: " << names.size() << endl
-       << "expected: " << num_expected << endl;
-  assert(names.size() == num_expected);
-
-  for (i = 0; i < names.size(); i++) {
-    cout << "image: " << names[i] << endl;
-  }
-
-  va_start(ap, num_expected);
-  for (i = num_expected; i > 0; i--) {
-    expected = va_arg(ap, char *);
-    cout << "expected = " << expected << endl;
-    vector<string>::iterator listed_name = find(names.begin(), names.end(), string(expected));
-    assert(listed_name != names.end());
-    names.erase(listed_name);
-  }
-  assert(names.empty());
-}
-
-void test_delete(librados::IoCtx& io_ctx, const char *name)
-{
-  assert(rbd->remove(io_ctx, name) == 0);
-}
-
-void test_create_snap(librbd::Image& image, const char *name)
-{
-  assert(image.snap_create(name) == 0);
-}
-
-void test_ls_snaps(librbd::Image& image, size_t num_expected, ...)
-{
-  int r;
-  size_t i, j, expected_size;
-  char *expected;
-  va_list ap;
-  vector<librbd::snap_info_t> snaps;
-  r = image.snap_list(snaps);
-  assert(r >= 0);
-  cout << "num snaps is: " << snaps.size() << endl
-       << "expected: " << num_expected << endl;
-  assert(snaps.size() == num_expected);
-
-  for (i = 0; i < snaps.size(); i++) {
-    cout << "snap: " << snaps[i].name << endl;
-  }
-
-  va_start(ap, num_expected);
-  for (i = num_expected; i > 0; i--) {
-    expected = va_arg(ap, char *);
-    expected_size = va_arg(ap, int);
-    int found = 0;
-    for (j = 0; j < snaps.size(); j++) {
-      if (snaps[j].name == "")
-       continue;
-      if (strcmp(snaps[j].name.c_str(), expected) == 0) {
-       cout << "found " << snaps[j].name << " with size " << snaps[j].size << endl;
-       assert(snaps[j].size == (size_t) expected_size);
-       snaps[j].name = "";
-       found = 1;
-       break;
-      }
-    }
-    assert(found);
-  }
-
-  for (i = 0; i < snaps.size(); i++) {
-    assert(snaps[i].name == "");
-  }
-}
-
-void test_delete_snap(librbd::Image& image, const char *name)
-{
-  assert(image.snap_remove(name) == 0);
-}
-
-void simple_write_cb(librbd::completion_t cb, void *arg)
-{
-  cout << "write completion cb called!" << endl;
-}
-
-void simple_read_cb(librbd::completion_t cb, void *arg)
-{
-  cout << "read completion cb called!" << endl;
-}
-
-void aio_write_test_data(librbd::Image& image, const char *test_data, off_t off)
-{
-  ceph::bufferlist bl;
-  bl.append(test_data, strlen(test_data));
-  librbd::RBD::AioCompletion *comp = new librbd::RBD::AioCompletion(NULL, (librbd::callback_t) simple_write_cb);
-  printf("created completion\n");
-  image.aio_write(off, strlen(test_data), bl, comp);
-  printf("started write\n");
-  comp->wait_for_complete();
-  int r = comp->get_return_value();
-  printf("return value is: %d\n", r);
-  assert(r == 0);
-  printf("finished write\n");
-  comp->release();
-}
-
-void write_test_data(librbd::Image& image, const char *test_data, off_t off)
-{
-  int written;
-  size_t len = strlen(test_data);
-  ceph::bufferlist bl;
-  bl.append(test_data, len);
-  written = image.write(off, len, bl);
-  assert(written >= 0);
-  printf("wrote: %u\n", (unsigned int) written);
-}
-
-void aio_read_test_data(librbd::Image& image, const char *expected, off_t off)
-{
-  librbd::RBD::AioCompletion *comp = new librbd::RBD::AioCompletion(NULL, (librbd::callback_t) simple_read_cb);
-  ceph::bufferlist bl;
-  printf("created completion\n");
-  image.aio_read(off, strlen(expected), bl, comp);
-  printf("started read\n");
-  comp->wait_for_complete();
-  int r = comp->get_return_value();
-  printf("return value is: %d\n", r);
-  assert(r == TEST_IO_SIZE - 1);
-  assert(strncmp(expected, bl.c_str(), TEST_IO_SIZE - 1) == 0);
-  printf("finished read\n");
-  comp->release();
-}
-
-void read_test_data(librbd::Image& image, const char *expected, off_t off)
-{
-  int read, total_read = 0;
-  size_t expected_len = strlen(expected);
-  size_t len = expected_len;
-  ceph::bufferlist bl;
-  read = image.read(off + total_read, len, bl);
-  assert(read >= 0);
-  printf("read: %u\n", (unsigned int) read);
-  printf("read: %s\nexpected: %s\n", bl.c_str(), expected);
-  assert(strncmp(bl.c_str(), expected, expected_len) == 0);
-}
-
-void test_io(librados::IoCtx& io_ctx, librbd::Image& image)
-{
-  char test_data[TEST_IO_SIZE];
-  int i;
-
-  srand(time(0));
-  for (i = 0; i < TEST_IO_SIZE - 1; ++i) {
-    test_data[i] = (char) (rand() % (126 - 33) + 33);
-  }
-  test_data[TEST_IO_SIZE - 1] = '\0';
-
-  for (i = 0; i < 5; ++i)
-    write_test_data(image, test_data, strlen(test_data) * i);
-
-  for (i = 5; i < 10; ++i)
-    aio_write_test_data(image, test_data, strlen(test_data) * i);
-
-  for (i = 0; i < 5; ++i)
-    read_test_data(image, test_data, strlen(test_data) * i);
-
-  for (i = 5; i < 10; ++i)
-    aio_read_test_data(image, test_data, strlen(test_data) * i);
-
-}
-
-void test_rbd_copy(librados::IoCtx& io_ctx, librbd::Image& image)
-{
-  int ret;
-  ret = image.copy(io_ctx, TEST_IMAGE2);
-  if (ret < 0) {
-    fprintf(stderr, "image.copy returned %d!\n", ret);
-    abort();
-  }
-}
-
-class PrintProgress : public librbd::ProgressContext
-{
-public:
-  int update_progress(uint64_t offset, uint64_t src_size)
-  {
-    float percent = ((float)offset * 100) / src_size;
-    printf("%3.2f%% done\n", percent);
-    return 0;
-  }
-};
-
-
-void test_rbd_copy_with_progress(librados::IoCtx& io_ctx, librbd::Image& image)
-{
-  int ret;
-  PrintProgress prog_ctx;
-  ret = image.copy_with_progress(io_ctx, TEST_IMAGE2, prog_ctx);
-  if (ret < 0) {
-    fprintf(stderr, "image.copy returned %d!\n", ret);
-    abort();
-  }
-}
-
-int main(int argc, const char **argv) 
-{
-  librados::Rados rados;
-  librados::IoCtx io_ctx;
-  librbd::Image image;
-  rbd = new librbd::RBD();
-  assert(rados.init(NULL) == 0);
-  assert(rados.conf_parse_argv(argc, argv) == 0);
-  assert(rados.conf_read_file(NULL) == 0);
-  assert(rados.connect() == 0);
-  if (rados.pool_lookup(TEST_POOL) != -ENOENT) {
-    int r = rados.pool_delete(TEST_POOL);
-    printf("rados.pool_delete returned %d\n", r);
-  }
-  int r = rados.pool_create(TEST_POOL);
-  printf("rados.pool_create returned %d\n", r);
-  assert(rados.ioctx_create(TEST_POOL, io_ctx) == 0);
-  test_ls(io_ctx, 0);
-  test_create_and_stat(io_ctx, TEST_IMAGE, MB_BYTES(1));
-  assert(rbd->open(io_ctx, image, TEST_IMAGE, NULL) == 0);
-  test_ls(io_ctx, 1, TEST_IMAGE);
-  test_ls_snaps(image, 0);
-  test_create_snap(image, TEST_SNAP);
-  test_ls_snaps(image, 1, TEST_SNAP, MB_BYTES(1));
-  test_resize_and_stat(image, MB_BYTES(2));
-  test_io(io_ctx, image);
-  test_create_snap(image, TEST_SNAP "1");
-  test_ls_snaps(image, 2, TEST_SNAP, MB_BYTES(1), TEST_SNAP "1", MB_BYTES(2));
-  test_delete_snap(image, TEST_SNAP);
-  test_ls_snaps(image, 1, TEST_SNAP "1", MB_BYTES(2));
-  test_delete_snap(image, TEST_SNAP "1");
-  test_ls_snaps(image, 0);
-  test_create_and_stat(io_ctx, TEST_IMAGE "1", MB_BYTES(2));
-  test_ls(io_ctx, 2, TEST_IMAGE, TEST_IMAGE "1");
-  test_delete(io_ctx, TEST_IMAGE);
-  test_ls(io_ctx, 1, TEST_IMAGE "1");
-  test_delete(io_ctx, TEST_IMAGE "1");
-  test_ls(io_ctx, 0);
-  test_rbd_copy(io_ctx, image);
-  test_delete(io_ctx, TEST_IMAGE2);
-  test_rbd_copy_with_progress(io_ctx, image);
-  delete rbd;
-  return 0;
-}