summaryrefslogtreecommitdiffstats
path: root/src/test/librados/asio.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/librados/asio.cc')
-rw-r--r--src/test/librados/asio.cc369
1 files changed, 369 insertions, 0 deletions
diff --git a/src/test/librados/asio.cc b/src/test/librados/asio.cc
new file mode 100644
index 000000000..9f86b4472
--- /dev/null
+++ b/src/test/librados/asio.cc
@@ -0,0 +1,369 @@
+// -*- 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) 2017 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ */
+
+#include "librados/librados_asio.h"
+#include <gtest/gtest.h>
+
+#include "common/ceph_argparse.h"
+#include "common/debug.h"
+#include "common/errno.h"
+#include "global/global_init.h"
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <spawn/spawn.hpp>
+#include <boost/asio/use_future.hpp>
+
+#define dout_subsys ceph_subsys_rados
+#define dout_context g_ceph_context
+
+using namespace std;
+
+// test fixture for global setup/teardown
+class AsioRados : public ::testing::Test {
+ static constexpr auto poolname = "ceph_test_rados_api_asio";
+
+ protected:
+ static librados::Rados rados;
+ static librados::IoCtx io;
+ // writes to snapio fail immediately with -EROFS. this is used to test errors
+ // that come from inside the initiating function, rather than passed to the
+ // AioCompletion callback
+ static librados::IoCtx snapio;
+
+ public:
+ static void SetUpTestCase() {
+ ASSERT_EQ(0, rados.init_with_context(g_ceph_context));
+ ASSERT_EQ(0, rados.connect());
+ // open/create test pool
+ int r = rados.ioctx_create(poolname, io);
+ if (r == -ENOENT) {
+ r = rados.pool_create(poolname);
+ if (r == -EEXIST) {
+ r = 0;
+ } else if (r == 0) {
+ r = rados.ioctx_create(poolname, io);
+ }
+ }
+ ASSERT_EQ(0, r);
+ ASSERT_EQ(0, rados.ioctx_create(poolname, snapio));
+ snapio.snap_set_read(1);
+ // initialize the "exist" object
+ bufferlist bl;
+ bl.append("hello");
+ ASSERT_EQ(0, io.write_full("exist", bl));
+ }
+
+ static void TearDownTestCase() {
+ rados.shutdown();
+ }
+};
+librados::Rados AsioRados::rados;
+librados::IoCtx AsioRados::io;
+librados::IoCtx AsioRados::snapio;
+
+TEST_F(AsioRados, AsyncReadCallback)
+{
+ boost::asio::io_service service;
+
+ auto success_cb = [&] (boost::system::error_code ec, bufferlist bl) {
+ EXPECT_FALSE(ec);
+ EXPECT_EQ("hello", bl.to_str());
+ };
+ librados::async_read(service, io, "exist", 256, 0, success_cb);
+
+ auto failure_cb = [&] (boost::system::error_code ec, bufferlist bl) {
+ EXPECT_EQ(boost::system::errc::no_such_file_or_directory, ec);
+ };
+ librados::async_read(service, io, "noexist", 256, 0, failure_cb);
+
+ service.run();
+}
+
+TEST_F(AsioRados, AsyncReadFuture)
+{
+ boost::asio::io_service service;
+
+ std::future<bufferlist> f1 = librados::async_read(service, io, "exist", 256,
+ 0, boost::asio::use_future);
+ std::future<bufferlist> f2 = librados::async_read(service, io, "noexist", 256,
+ 0, boost::asio::use_future);
+
+ service.run();
+
+ EXPECT_NO_THROW({
+ auto bl = f1.get();
+ EXPECT_EQ("hello", bl.to_str());
+ });
+ EXPECT_THROW(f2.get(), boost::system::system_error);
+}
+
+TEST_F(AsioRados, AsyncReadYield)
+{
+ boost::asio::io_service service;
+
+ auto success_cr = [&] (spawn::yield_context yield) {
+ boost::system::error_code ec;
+ auto bl = librados::async_read(service, io, "exist", 256, 0, yield[ec]);
+ EXPECT_FALSE(ec);
+ EXPECT_EQ("hello", bl.to_str());
+ };
+ spawn::spawn(service, success_cr);
+
+ auto failure_cr = [&] (spawn::yield_context yield) {
+ boost::system::error_code ec;
+ auto bl = librados::async_read(service, io, "noexist", 256, 0, yield[ec]);
+ EXPECT_EQ(boost::system::errc::no_such_file_or_directory, ec);
+ };
+ spawn::spawn(service, failure_cr);
+
+ service.run();
+}
+
+TEST_F(AsioRados, AsyncWriteCallback)
+{
+ boost::asio::io_service service;
+
+ bufferlist bl;
+ bl.append("hello");
+
+ auto success_cb = [&] (boost::system::error_code ec) {
+ EXPECT_FALSE(ec);
+ };
+ librados::async_write(service, io, "exist", bl, bl.length(), 0,
+ success_cb);
+
+ auto failure_cb = [&] (boost::system::error_code ec) {
+ EXPECT_EQ(boost::system::errc::read_only_file_system, ec);
+ };
+ librados::async_write(service, snapio, "exist", bl, bl.length(), 0,
+ failure_cb);
+
+ service.run();
+}
+
+TEST_F(AsioRados, AsyncWriteFuture)
+{
+ boost::asio::io_service service;
+
+ bufferlist bl;
+ bl.append("hello");
+
+ auto f1 = librados::async_write(service, io, "exist", bl, bl.length(), 0,
+ boost::asio::use_future);
+ auto f2 = librados::async_write(service, snapio, "exist", bl, bl.length(), 0,
+ boost::asio::use_future);
+
+ service.run();
+
+ EXPECT_NO_THROW(f1.get());
+ EXPECT_THROW(f2.get(), boost::system::system_error);
+}
+
+TEST_F(AsioRados, AsyncWriteYield)
+{
+ boost::asio::io_service service;
+
+ bufferlist bl;
+ bl.append("hello");
+
+ auto success_cr = [&] (spawn::yield_context yield) {
+ boost::system::error_code ec;
+ librados::async_write(service, io, "exist", bl, bl.length(), 0,
+ yield[ec]);
+ EXPECT_FALSE(ec);
+ EXPECT_EQ("hello", bl.to_str());
+ };
+ spawn::spawn(service, success_cr);
+
+ auto failure_cr = [&] (spawn::yield_context yield) {
+ boost::system::error_code ec;
+ librados::async_write(service, snapio, "exist", bl, bl.length(), 0,
+ yield[ec]);
+ EXPECT_EQ(boost::system::errc::read_only_file_system, ec);
+ };
+ spawn::spawn(service, failure_cr);
+
+ service.run();
+}
+
+TEST_F(AsioRados, AsyncReadOperationCallback)
+{
+ boost::asio::io_service service;
+ {
+ librados::ObjectReadOperation op;
+ op.read(0, 0, nullptr, nullptr);
+ auto success_cb = [&] (boost::system::error_code ec, bufferlist bl) {
+ EXPECT_FALSE(ec);
+ EXPECT_EQ("hello", bl.to_str());
+ };
+ librados::async_operate(service, io, "exist", &op, 0, success_cb);
+ }
+ {
+ librados::ObjectReadOperation op;
+ op.read(0, 0, nullptr, nullptr);
+ auto failure_cb = [&] (boost::system::error_code ec, bufferlist bl) {
+ EXPECT_EQ(boost::system::errc::no_such_file_or_directory, ec);
+ };
+ librados::async_operate(service, io, "noexist", &op, 0, failure_cb);
+ }
+ service.run();
+}
+
+TEST_F(AsioRados, AsyncReadOperationFuture)
+{
+ boost::asio::io_service service;
+ std::future<bufferlist> f1;
+ {
+ librados::ObjectReadOperation op;
+ op.read(0, 0, nullptr, nullptr);
+ f1 = librados::async_operate(service, io, "exist", &op, 0,
+ boost::asio::use_future);
+ }
+ std::future<bufferlist> f2;
+ {
+ librados::ObjectReadOperation op;
+ op.read(0, 0, nullptr, nullptr);
+ f2 = librados::async_operate(service, io, "noexist", &op, 0,
+ boost::asio::use_future);
+ }
+ service.run();
+
+ EXPECT_NO_THROW({
+ auto bl = f1.get();
+ EXPECT_EQ("hello", bl.to_str());
+ });
+ EXPECT_THROW(f2.get(), boost::system::system_error);
+}
+
+TEST_F(AsioRados, AsyncReadOperationYield)
+{
+ boost::asio::io_service service;
+
+ auto success_cr = [&] (spawn::yield_context yield) {
+ librados::ObjectReadOperation op;
+ op.read(0, 0, nullptr, nullptr);
+ boost::system::error_code ec;
+ auto bl = librados::async_operate(service, io, "exist", &op, 0,
+ yield[ec]);
+ EXPECT_FALSE(ec);
+ EXPECT_EQ("hello", bl.to_str());
+ };
+ spawn::spawn(service, success_cr);
+
+ auto failure_cr = [&] (spawn::yield_context yield) {
+ librados::ObjectReadOperation op;
+ op.read(0, 0, nullptr, nullptr);
+ boost::system::error_code ec;
+ auto bl = librados::async_operate(service, io, "noexist", &op, 0,
+ yield[ec]);
+ EXPECT_EQ(boost::system::errc::no_such_file_or_directory, ec);
+ };
+ spawn::spawn(service, failure_cr);
+
+ service.run();
+}
+
+TEST_F(AsioRados, AsyncWriteOperationCallback)
+{
+ boost::asio::io_service service;
+
+ bufferlist bl;
+ bl.append("hello");
+
+ {
+ librados::ObjectWriteOperation op;
+ op.write_full(bl);
+ auto success_cb = [&] (boost::system::error_code ec) {
+ EXPECT_FALSE(ec);
+ };
+ librados::async_operate(service, io, "exist", &op, 0, success_cb);
+ }
+ {
+ librados::ObjectWriteOperation op;
+ op.write_full(bl);
+ auto failure_cb = [&] (boost::system::error_code ec) {
+ EXPECT_EQ(boost::system::errc::read_only_file_system, ec);
+ };
+ librados::async_operate(service, snapio, "exist", &op, 0, failure_cb);
+ }
+ service.run();
+}
+
+TEST_F(AsioRados, AsyncWriteOperationFuture)
+{
+ boost::asio::io_service service;
+
+ bufferlist bl;
+ bl.append("hello");
+
+ std::future<void> f1;
+ {
+ librados::ObjectWriteOperation op;
+ op.write_full(bl);
+ f1 = librados::async_operate(service, io, "exist", &op, 0,
+ boost::asio::use_future);
+ }
+ std::future<void> f2;
+ {
+ librados::ObjectWriteOperation op;
+ op.write_full(bl);
+ f2 = librados::async_operate(service, snapio, "exist", &op, 0,
+ boost::asio::use_future);
+ }
+ service.run();
+
+ EXPECT_NO_THROW(f1.get());
+ EXPECT_THROW(f2.get(), boost::system::system_error);
+}
+
+TEST_F(AsioRados, AsyncWriteOperationYield)
+{
+ boost::asio::io_service service;
+
+ bufferlist bl;
+ bl.append("hello");
+
+ auto success_cr = [&] (spawn::yield_context yield) {
+ librados::ObjectWriteOperation op;
+ op.write_full(bl);
+ boost::system::error_code ec;
+ librados::async_operate(service, io, "exist", &op, 0, yield[ec]);
+ EXPECT_FALSE(ec);
+ };
+ spawn::spawn(service, success_cr);
+
+ auto failure_cr = [&] (spawn::yield_context yield) {
+ librados::ObjectWriteOperation op;
+ op.write_full(bl);
+ boost::system::error_code ec;
+ librados::async_operate(service, snapio, "exist", &op, 0, yield[ec]);
+ EXPECT_EQ(boost::system::errc::read_only_file_system, ec);
+ };
+ spawn::spawn(service, failure_cr);
+
+ service.run();
+}
+
+int main(int argc, char **argv)
+{
+ auto args = argv_to_vec(argc, argv);
+ env_to_vec(args);
+
+ auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
+ CODE_ENVIRONMENT_UTILITY, 0);
+ common_init_finish(cct.get());
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}