]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tests: base gmock class support for librbd 5816/head
authorJason Dillaman <dillaman@redhat.com>
Fri, 4 Sep 2015 19:01:38 +0000 (15:01 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 4 Sep 2015 19:01:38 +0000 (15:01 -0400)
Created mock classes to represent a few central librbd classes
and a basic gmock test fixture for future gmock-based unit tests.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/Makefile-client.am
src/test/Makefile.am
src/test/librbd/mock/MockContextWQ.h [new file with mode: 0644]
src/test/librbd/mock/MockImageCtx.h [new file with mode: 0644]
src/test/librbd/mock/MockImageWatcher.h [new file with mode: 0644]
src/test/librbd/mock/MockObjectMap.h [new file with mode: 0644]
src/test/librbd/test_mock_fixture.cc [new file with mode: 0644]
src/test/librbd/test_mock_fixture.h [new file with mode: 0644]

index 0ea7b80ad3a3f38c9c22e8f4beedc9bff5485f90..49e17f6e61d6f20111863f68e856244b61d592b7 100644 (file)
@@ -321,7 +321,8 @@ librbd_test_la_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 noinst_LTLIBRARIES += librbd_test.la
 
 unittest_librbd_SOURCES = \
-        test/librbd/test_main.cc
+        test/librbd/test_main.cc \
+       test/librbd/test_mock_fixture.cc
 unittest_librbd_CXXFLAGS = $(UNITTEST_CXXFLAGS) -DTEST_LIBRBD_INTERNALS
 unittest_librbd_LDADD = \
        librbd_test.la librbd_api.la librbd_internal.la $(LIBRBD_TYPES) \
@@ -351,6 +352,15 @@ ceph_test_librbd_api_LDADD = \
        $(LIBRBD) $(LIBRADOS) $(LIBCOMMON) $(UNITTEST_LDADD) $(RADOS_TEST_LDADD)
 bin_DEBUGPROGRAMS += ceph_test_librbd_api
 
+noinst_HEADERS += \
+       test/librbd/test_fixture.h \
+       test/librbd/test_mock_fixture.h \
+       test/librbd/test_support.h \
+       test/librbd/mock/MockContextWQ.h \
+       test/librbd/mock/MockImageCtx.h \
+       test/librbd/mock/MockImageWatcher.h \
+       test/librbd/mock/MockObjectMap.h
+
 if WITH_LTTNG
 unittest_librbd_LDADD += $(LIBRBD_TP)
 ceph_test_librbd_LDADD += $(LIBRBD_TP)
index f6373c76d6d5672d0634d10ea2c877557df7e8df..73c2da1a15f4d24c96927e40d0cc02d1d5b013d9 100644 (file)
@@ -449,8 +449,6 @@ noinst_HEADERS += \
        test/librados/test.h \
        test/librados/TestCase.h \
        test/libradosstriper/TestCase.h \
-       test/librbd/test_fixture.h \
-       test/librbd/test_support.h \
        test/ObjectMap/KeyValueDBMemory.h \
        test/omap_bench.h \
        test/osdc/FakeWriteback.h \
diff --git a/src/test/librbd/mock/MockContextWQ.h b/src/test/librbd/mock/MockContextWQ.h
new file mode 100644 (file)
index 0000000..a690d4e
--- /dev/null
@@ -0,0 +1,17 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_TEST_LIBRBD_MOCK_CONTEXT_WQ_H
+#define CEPH_TEST_LIBRBD_MOCK_CONTEXT_WQ_H
+
+#include "gmock/gmock.h"
+
+namespace librbd {
+
+struct MockContextWQ {
+  MOCK_METHOD2(queue, void(Context *, int r));
+};
+
+} // namespace librbd
+
+#endif // CEPH_TEST_LIBRBD_MOCK_CONTEXT_WQ_H
diff --git a/src/test/librbd/mock/MockImageCtx.h b/src/test/librbd/mock/MockImageCtx.h
new file mode 100644 (file)
index 0000000..53d6fd0
--- /dev/null
@@ -0,0 +1,112 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_TEST_LIBRBD_MOCK_IMAGE_CTX_H
+#define CEPH_TEST_LIBRBD_MOCK_IMAGE_CTX_H
+
+#include "test/librbd/mock/MockContextWQ.h"
+#include "test/librbd/mock/MockImageWatcher.h"
+#include "test/librbd/mock/MockObjectMap.h"
+#include "common/RWLock.h"
+#include "librbd/ImageCtx.h"
+#include "gmock/gmock.h"
+
+namespace librbd {
+
+struct MockImageCtx {
+  MockImageCtx(librbd::ImageCtx &image_ctx)
+    : image_ctx(&image_ctx),
+      cct(image_ctx.cct),
+      snapc(image_ctx.snapc),
+      snaps(image_ctx.snaps),
+      snap_info(image_ctx.snap_info),
+      old_format(image_ctx.old_format),
+      read_only(image_ctx.read_only),
+      owner_lock("owner_lock"),
+      md_lock("md_lock"),
+      snap_lock("snap_lock"),
+      parent_lock("parent_lock"),
+      object_map_lock("object_map_lock"),
+      async_ops_lock("async_ops_lock"),
+      size(image_ctx.size),
+      features(image_ctx.features),
+      header_oid(image_ctx.header_oid),
+      id(image_ctx.id),
+      parent_md(image_ctx.parent_md),
+      aio_work_queue(new MockContextWQ()),
+      op_work_queue(new MockContextWQ()),
+      image_watcher(NULL),
+      concurrent_management_ops(image_ctx.concurrent_management_ops)
+  {
+    md_ctx.dup(image_ctx.md_ctx);
+    data_ctx.dup(image_ctx.data_ctx);
+
+    if (image_ctx.image_watcher != NULL) {
+      image_watcher = new MockImageWatcher();
+    }
+  }
+
+  ~MockImageCtx() {
+    delete image_watcher;
+    delete op_work_queue;
+    delete aio_work_queue;
+  }
+
+  MOCK_CONST_METHOD1(get_snap_id, librados::snap_t(std::string in_snap_name));
+  MOCK_CONST_METHOD1(get_snap_info, const SnapInfo*(librados::snap_t));
+  MOCK_CONST_METHOD2(get_parent_spec, int(librados::snap_t in_snap_id,
+                                          parent_spec *pspec));
+
+  MOCK_CONST_METHOD2(is_snap_protected, int(librados::snap_t in_snap_id,
+                                            bool *is_protected));
+  MOCK_CONST_METHOD2(is_snap_unprotected, int(librados::snap_t in_snap_id,
+                                              bool *is_unprotected));
+
+  MOCK_METHOD6(add_snap, void(std::string in_snap_name, librados::snap_t id,
+                              uint64_t in_size, parent_info parent,
+                              uint8_t protection_status, uint64_t flags));
+  MOCK_METHOD2(rm_snap, void(std::string in_snap_name, librados::snap_t id));
+  MOCK_METHOD1(flush, void(Context *));
+
+  ImageCtx *image_ctx;
+  CephContext *cct;
+
+  ::SnapContext snapc;
+  std::vector<librados::snap_t> snaps;
+  std::map<librados::snap_t, SnapInfo> snap_info;
+
+
+  bool old_format;
+  bool read_only;
+
+  librados::IoCtx md_ctx;
+  librados::IoCtx data_ctx;
+
+  RWLock owner_lock;
+  RWLock md_lock;
+  RWLock snap_lock;
+  RWLock parent_lock;
+  RWLock object_map_lock;
+  Mutex async_ops_lock;
+
+  uint64_t size;
+  uint64_t features;
+  std::string header_oid;
+  std::string id;
+  parent_info parent_md;
+
+  xlist<AsyncRequest<MockImageCtx>*> async_requests;
+  Cond async_requests_cond;
+
+  MockContextWQ *aio_work_queue;
+  MockContextWQ *op_work_queue;
+
+  MockImageWatcher *image_watcher;
+  MockObjectMap object_map;
+
+  int concurrent_management_ops;
+};
+
+} // namespace librbd
+
+#endif // CEPH_TEST_LIBRBD_MOCK_IMAGE_CTX_H
diff --git a/src/test/librbd/mock/MockImageWatcher.h b/src/test/librbd/mock/MockImageWatcher.h
new file mode 100644 (file)
index 0000000..1c339bc
--- /dev/null
@@ -0,0 +1,19 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_TEST_LIBRBD_MOCK_IMAGE_WATCHER_H
+#define CEPH_TEST_LIBRBD_MOCK_IMAGE_WATCHER_H
+
+#include "gmock/gmock.h"
+
+namespace librbd {
+
+struct MockImageWatcher {
+  MOCK_CONST_METHOD0(is_lock_owner, bool());
+  MOCK_CONST_METHOD1(is_lock_supported, bool(const RWLock &));
+  MOCK_METHOD1(assert_header_locked, void (librados::ObjectWriteOperation *));
+};
+
+} // namespace librbd
+
+#endif // CEPH_TEST_LIBRBD_MOCK_IMAGE_WATCHER_H
diff --git a/src/test/librbd/mock/MockObjectMap.h b/src/test/librbd/mock/MockObjectMap.h
new file mode 100644 (file)
index 0000000..7f2f84b
--- /dev/null
@@ -0,0 +1,20 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_TEST_LIBRBD_MOCK_OBJECT_MAP_H
+#define CEPH_TEST_LIBRBD_MOCK_OBJECT_MAP_H
+
+#include "gmock/gmock.h"
+
+namespace librbd {
+
+struct MockObjectMap {
+  MOCK_CONST_METHOD1(enabled, bool(const RWLock &object_map_lock));
+
+  MOCK_METHOD2(snapshot_add, void(uint64_t snap_id, Context *on_finish));
+  MOCK_METHOD2(snapshot_remove, void(uint64_t snap_id, Context *on_finish));
+};
+
+} // namespace librbd
+
+#endif // CEPH_TEST_LIBRBD_MOCK_OBJECT_MAP_H
diff --git a/src/test/librbd/test_mock_fixture.cc b/src/test/librbd/test_mock_fixture.cc
new file mode 100644 (file)
index 0000000..1839b91
--- /dev/null
@@ -0,0 +1,68 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/librbd/test_mock_fixture.h"
+#include "test/librbd/mock/MockImageCtx.h"
+#include "test/librados_test_stub/LibradosTestStub.h"
+#include "test/librados_test_stub/MockTestMemRadosClient.h"
+
+// template definitions
+#include "librbd/AsyncRequest.cc"
+#include "librbd/AsyncObjectThrottle.cc"
+
+template class librbd::AsyncRequest<librbd::MockImageCtx>;
+template class librbd::AsyncObjectThrottle<librbd::MockImageCtx>;
+
+using ::testing::_;
+using ::testing::DoDefault;
+
+TestMockFixture::TestRadosClientPtr TestMockFixture::s_test_rados_client;
+::testing::NiceMock<librados::MockTestMemRadosClient> *
+  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<librados::MockTestMemRadosClient>(
+      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);
+}
+
+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();
+}
+
+void TestMockFixture::expect_unlock_exclusive_lock(librbd::ImageCtx &ictx) {
+  EXPECT_CALL(get_mock_io_ctx(ictx.md_ctx),
+              exec(_, _, "lock", "unlock", _, _, _))
+                .WillRepeatedly(DoDefault());
+}
+
+void TestMockFixture::expect_op_work_queue(librbd::MockImageCtx &mock_image_ctx) {
+  EXPECT_CALL(*mock_image_ctx.op_work_queue, queue(_, _))
+                .WillRepeatedly(DispatchContext(
+                  mock_image_ctx.image_ctx->op_work_queue));
+}
+
+librados::MockTestMemIoCtxImpl &TestMockFixture::get_mock_io_ctx(
+    librados::IoCtx &ioctx) {
+  // TODO become friend of IoCtx so that we can cleanly extract io_ctx_impl
+  librados::MockTestMemIoCtxImpl **mock =
+    reinterpret_cast<librados::MockTestMemIoCtxImpl **>(&ioctx);
+  return **mock;
+}
diff --git a/src/test/librbd/test_mock_fixture.h b/src/test/librbd/test_mock_fixture.h
new file mode 100644 (file)
index 0000000..150e312
--- /dev/null
@@ -0,0 +1,64 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_TEST_LIBRBD_TEST_MOCK_FIXTURE_H
+#define CEPH_TEST_LIBRBD_TEST_MOCK_FIXTURE_H
+
+#include "test/librbd/test_fixture.h"
+#include "common/WorkQueue.h"
+#include <boost/shared_ptr.hpp>
+#include <gmock/gmock.h>
+
+namespace librados {
+class TestRadosClient;
+class MockTestMemIoCtxImpl;
+class MockTestMemRadosClient;
+}
+namespace librbd {
+class MockImageCtx;
+}
+
+ACTION_P2(CompleteContext, r, wq) {
+  ContextWQ *context_wq = reinterpret_cast<ContextWQ *>(wq);
+  if (context_wq != NULL) {
+    context_wq->queue(arg0, r);
+  } else {
+    arg0->complete(r);
+  }
+}
+
+ACTION_P(DispatchContext, wq) {
+  wq->queue(arg0, arg1);
+}
+
+ACTION_P(GetReference, ref_object) {
+  ref_object->get();
+}
+
+MATCHER_P(ContentsEqual, bl, "") {
+  // TODO fix const-correctness of bufferlist
+  return const_cast<bufferlist &>(arg).contents_equal(
+    const_cast<bufferlist &>(bl));
+}
+
+class TestMockFixture : public TestFixture {
+public:
+  typedef boost::shared_ptr<librados::TestRadosClient> TestRadosClientPtr;
+
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+
+  virtual void SetUp();
+  virtual void TearDown();
+
+  librados::MockTestMemIoCtxImpl &get_mock_io_ctx(librados::IoCtx &ioctx);
+
+  void expect_op_work_queue(librbd::MockImageCtx &mock_image_ctx);
+  void expect_unlock_exclusive_lock(librbd::ImageCtx &ictx);
+
+private:
+  static TestRadosClientPtr s_test_rados_client;
+  static ::testing::NiceMock<librados::MockTestMemRadosClient> *s_mock_rados_client;
+};
+
+#endif // CEPH_TEST_LIBRBD_TEST_MOCK_FIXTURE_H