]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/gtest_seastar: add helpers for building seastar gtest unit tests
authorSamuel Just <sjust@redhat.com>
Mon, 4 May 2020 18:48:10 +0000 (11:48 -0700)
committerSamuel Just <sjust@redhat.com>
Fri, 15 May 2020 05:52:46 +0000 (22:52 -0700)
Also adds unsafe_get methods for errorator for use within unit tests.

Signed-off-by: Samuel Just <sjust@redhat.com>
src/crimson/common/errorator.h
src/test/crimson/gtest_seastar.cc [new file with mode: 0644]
src/test/crimson/gtest_seastar.h [new file with mode: 0644]

index b0030142ad2f07bd75005a7ea68f9a8d288de936..b7a7c8eff0031e480582119bb1d7c9894e0e9c89 100644 (file)
@@ -564,6 +564,23 @@ private:
         });
     }
 
+    /**
+     * unsafe_thread_get
+     *
+     * Only valid within a seastar_thread.  Ignores errorator protections
+     * and throws any contained exceptions.
+     *
+     * Should really only be used within test code
+     * (see test/crimson/gtest_seastar.h).
+     */
+    auto &&unsafe_get() {
+      return seastar::future<ValuesT...>::get();
+    }
+    auto unsafe_get0() {
+      return seastar::future<ValuesT...>::get0();
+    }
+
+
     template <class FuncT>
     auto finally(FuncT &&func) {
       using func_result_t = std::invoke_result_t<FuncT>;
diff --git a/src/test/crimson/gtest_seastar.cc b/src/test/crimson/gtest_seastar.cc
new file mode 100644 (file)
index 0000000..e8d6ae2
--- /dev/null
@@ -0,0 +1,72 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "include/ceph_assert.h"
+#include "gtest_seastar.h"
+
+seastar_gtest_env_t seastar_test_suite_t::seastar_env;
+
+seastar_gtest_env_t::seastar_gtest_env_t() :
+  begin_fd{seastar::file_desc::eventfd(0, 0)} {}
+
+void seastar_gtest_env_t::init(int _argc, char **_argv)
+{
+  argc = _argc;
+  argv = new char *[argc];
+  for (int i = 0; i < argc; ++i) argv[i] = strdup(_argv[i]);
+
+  thread = std::thread([this] { reactor(); });
+  eventfd_t result = 0;
+  if (int r = ::eventfd_read(begin_fd.get(), &result); r < 0) {
+    std::cerr << "unable to eventfd_read():" << errno << std::endl;
+    throw std::runtime_error("Cannot start seastar");
+  }
+}
+
+void seastar_gtest_env_t::stop()
+{
+  run([this] {
+    on_end->write_side().signal(1);
+    return seastar::now();
+  });
+  thread.join();
+}
+
+seastar_gtest_env_t::~seastar_gtest_env_t()
+{
+  ceph_assert(argv);
+  for (int i = 0; i < argc; ++i) free(argv[i]);
+  delete[] argv;
+}
+
+void seastar_gtest_env_t::reactor()
+{
+  app.run(argc, argv, [this] {
+    on_end.reset(new seastar::readable_eventfd);
+    return seastar::now().then([this] {
+      ::eventfd_write(begin_fd.get(), 1);
+       return seastar::now();
+    }).then([this] {
+      return on_end->wait().then([](size_t){});
+    }).handle_exception([](auto ep) {
+      std::cerr << "Error: " << ep << std::endl;
+    }).finally([this] {
+      on_end.reset();
+    });
+  });
+}
+
+int main(int argc, char **argv)
+{
+  seastar_test_suite_t::seastar_env.init(argc, argv);
+
+  seastar::global_logger_registry().set_all_loggers_level(
+    seastar::log_level::debug
+  );
+
+  ::testing::InitGoogleTest(&argc, argv);
+  int ret = RUN_ALL_TESTS();
+
+  seastar_test_suite_t::seastar_env.stop();
+  return ret;
+}
diff --git a/src/test/crimson/gtest_seastar.h b/src/test/crimson/gtest_seastar.h
new file mode 100644 (file)
index 0000000..ed02891
--- /dev/null
@@ -0,0 +1,66 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include <stdio.h>
+#include <signal.h>
+#include <thread>
+
+#include <seastar/core/app-template.hh>
+#include <seastar/core/future-util.hh>
+#include <seastar/core/reactor.hh>
+#include <seastar/core/alien.hh>
+#include <seastar/core/thread.hh>
+
+#include "gtest/gtest.h"
+
+struct seastar_gtest_env_t {
+  seastar::app_template app;
+  seastar::file_desc begin_fd;
+  std::unique_ptr<seastar::readable_eventfd> on_end;
+
+  int argc = 0;
+  char **argv = nullptr;
+  std::thread thread;
+
+  seastar_gtest_env_t();
+  ~seastar_gtest_env_t();
+
+  void init(int argc, char **argv);
+  void stop();
+  void reactor();
+
+  template <typename Func>
+  void run(Func &&func) {
+    auto fut = seastar::alien::submit_to(0, std::forward<Func>(func));
+    fut.get();
+  }
+};
+
+struct seastar_test_suite_t : public ::testing::Test {
+  static seastar_gtest_env_t seastar_env;
+
+  template <typename Func>
+  void run(Func &&func) {
+    return seastar_env.run(std::forward<Func>(func));
+  }
+
+  template <typename Func>
+  void run_async(Func &&func) {
+    run(
+      [func=std::forward<Func>(func)]() mutable {
+       return seastar::async(std::forward<Func>(func));
+      });
+  }
+
+  virtual seastar::future<> set_up_fut() { return seastar::now(); }
+  void SetUp() final {
+    return run([this] { return set_up_fut(); });
+  }
+
+  virtual seastar::future<> tear_down_fut() { return seastar::now(); }
+  void TearDown() final {
+    return run([this] { return tear_down_fut(); });
+  }
+};