]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados/asio.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / librados / asio.cc
CommitLineData
11fdf7f2
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2017 Red Hat, Inc.
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 */
13
14#include "librados/librados_asio.h"
15#include <gtest/gtest.h>
16
17#include "common/ceph_argparse.h"
18#include "common/debug.h"
19#include "common/errno.h"
20#include "global/global_init.h"
21
11fdf7f2 22#define BOOST_COROUTINES_NO_DEPRECATION_WARNING
92f5a8d4
TL
23#include <boost/range/begin.hpp>
24#include <boost/range/end.hpp>
11fdf7f2 25#include <boost/asio/spawn.hpp>
11fdf7f2
TL
26#include <boost/asio/use_future.hpp>
27
28#define dout_subsys ceph_subsys_rados
29#define dout_context g_ceph_context
30
20effc67
TL
31using namespace std;
32
11fdf7f2
TL
33// test fixture for global setup/teardown
34class AsioRados : public ::testing::Test {
35 static constexpr auto poolname = "ceph_test_rados_api_asio";
36
37 protected:
38 static librados::Rados rados;
39 static librados::IoCtx io;
40 // writes to snapio fail immediately with -EROFS. this is used to test errors
41 // that come from inside the initiating function, rather than passed to the
42 // AioCompletion callback
43 static librados::IoCtx snapio;
44
45 public:
46 static void SetUpTestCase() {
47 ASSERT_EQ(0, rados.init_with_context(g_ceph_context));
48 ASSERT_EQ(0, rados.connect());
49 // open/create test pool
50 int r = rados.ioctx_create(poolname, io);
51 if (r == -ENOENT) {
52 r = rados.pool_create(poolname);
53 if (r == -EEXIST) {
54 r = 0;
55 } else if (r == 0) {
56 r = rados.ioctx_create(poolname, io);
57 }
58 }
59 ASSERT_EQ(0, r);
60 ASSERT_EQ(0, rados.ioctx_create(poolname, snapio));
61 snapio.snap_set_read(1);
62 // initialize the "exist" object
63 bufferlist bl;
64 bl.append("hello");
65 ASSERT_EQ(0, io.write_full("exist", bl));
66 }
67
68 static void TearDownTestCase() {
69 rados.shutdown();
70 }
71};
72librados::Rados AsioRados::rados;
73librados::IoCtx AsioRados::io;
74librados::IoCtx AsioRados::snapio;
75
76TEST_F(AsioRados, AsyncReadCallback)
77{
78 boost::asio::io_service service;
79
80 auto success_cb = [&] (boost::system::error_code ec, bufferlist bl) {
81 EXPECT_FALSE(ec);
82 EXPECT_EQ("hello", bl.to_str());
83 };
84 librados::async_read(service, io, "exist", 256, 0, success_cb);
85
86 auto failure_cb = [&] (boost::system::error_code ec, bufferlist bl) {
87 EXPECT_EQ(boost::system::errc::no_such_file_or_directory, ec);
88 };
89 librados::async_read(service, io, "noexist", 256, 0, failure_cb);
90
91 service.run();
92}
93
94TEST_F(AsioRados, AsyncReadFuture)
95{
96 boost::asio::io_service service;
97
98 std::future<bufferlist> f1 = librados::async_read(service, io, "exist", 256,
99 0, boost::asio::use_future);
100 std::future<bufferlist> f2 = librados::async_read(service, io, "noexist", 256,
101 0, boost::asio::use_future);
102
103 service.run();
104
105 EXPECT_NO_THROW({
106 auto bl = f1.get();
107 EXPECT_EQ("hello", bl.to_str());
108 });
109 EXPECT_THROW(f2.get(), boost::system::system_error);
110}
111
11fdf7f2
TL
112TEST_F(AsioRados, AsyncReadYield)
113{
114 boost::asio::io_service service;
115
116 auto success_cr = [&] (boost::asio::yield_context yield) {
117 boost::system::error_code ec;
118 auto bl = librados::async_read(service, io, "exist", 256, 0, yield[ec]);
119 EXPECT_FALSE(ec);
120 EXPECT_EQ("hello", bl.to_str());
121 };
122 boost::asio::spawn(service, success_cr);
123
124 auto failure_cr = [&] (boost::asio::yield_context yield) {
125 boost::system::error_code ec;
126 auto bl = librados::async_read(service, io, "noexist", 256, 0, yield[ec]);
127 EXPECT_EQ(boost::system::errc::no_such_file_or_directory, ec);
128 };
129 boost::asio::spawn(service, failure_cr);
130
131 service.run();
132}
11fdf7f2
TL
133
134TEST_F(AsioRados, AsyncWriteCallback)
135{
136 boost::asio::io_service service;
137
138 bufferlist bl;
139 bl.append("hello");
140
141 auto success_cb = [&] (boost::system::error_code ec) {
142 EXPECT_FALSE(ec);
143 };
144 librados::async_write(service, io, "exist", bl, bl.length(), 0,
145 success_cb);
146
147 auto failure_cb = [&] (boost::system::error_code ec) {
148 EXPECT_EQ(boost::system::errc::read_only_file_system, ec);
149 };
150 librados::async_write(service, snapio, "exist", bl, bl.length(), 0,
151 failure_cb);
152
153 service.run();
154}
155
156TEST_F(AsioRados, AsyncWriteFuture)
157{
158 boost::asio::io_service service;
159
160 bufferlist bl;
161 bl.append("hello");
162
163 auto f1 = librados::async_write(service, io, "exist", bl, bl.length(), 0,
164 boost::asio::use_future);
165 auto f2 = librados::async_write(service, snapio, "exist", bl, bl.length(), 0,
166 boost::asio::use_future);
167
168 service.run();
169
170 EXPECT_NO_THROW(f1.get());
171 EXPECT_THROW(f2.get(), boost::system::system_error);
172}
173
11fdf7f2
TL
174TEST_F(AsioRados, AsyncWriteYield)
175{
176 boost::asio::io_service service;
177
178 bufferlist bl;
179 bl.append("hello");
180
181 auto success_cr = [&] (boost::asio::yield_context yield) {
182 boost::system::error_code ec;
183 librados::async_write(service, io, "exist", bl, bl.length(), 0,
184 yield[ec]);
185 EXPECT_FALSE(ec);
186 EXPECT_EQ("hello", bl.to_str());
187 };
188 boost::asio::spawn(service, success_cr);
189
190 auto failure_cr = [&] (boost::asio::yield_context yield) {
191 boost::system::error_code ec;
192 librados::async_write(service, snapio, "exist", bl, bl.length(), 0,
193 yield[ec]);
194 EXPECT_EQ(boost::system::errc::read_only_file_system, ec);
195 };
196 boost::asio::spawn(service, failure_cr);
197
198 service.run();
199}
11fdf7f2
TL
200
201TEST_F(AsioRados, AsyncReadOperationCallback)
202{
203 boost::asio::io_service service;
204 {
205 librados::ObjectReadOperation op;
206 op.read(0, 0, nullptr, nullptr);
207 auto success_cb = [&] (boost::system::error_code ec, bufferlist bl) {
208 EXPECT_FALSE(ec);
209 EXPECT_EQ("hello", bl.to_str());
210 };
211 librados::async_operate(service, io, "exist", &op, 0, success_cb);
212 }
213 {
214 librados::ObjectReadOperation op;
215 op.read(0, 0, nullptr, nullptr);
216 auto failure_cb = [&] (boost::system::error_code ec, bufferlist bl) {
217 EXPECT_EQ(boost::system::errc::no_such_file_or_directory, ec);
218 };
219 librados::async_operate(service, io, "noexist", &op, 0, failure_cb);
220 }
221 service.run();
222}
223
224TEST_F(AsioRados, AsyncReadOperationFuture)
225{
226 boost::asio::io_service service;
227 std::future<bufferlist> f1;
228 {
229 librados::ObjectReadOperation op;
230 op.read(0, 0, nullptr, nullptr);
231 f1 = librados::async_operate(service, io, "exist", &op, 0,
232 boost::asio::use_future);
233 }
234 std::future<bufferlist> f2;
235 {
236 librados::ObjectReadOperation op;
237 op.read(0, 0, nullptr, nullptr);
238 f2 = librados::async_operate(service, io, "noexist", &op, 0,
239 boost::asio::use_future);
240 }
241 service.run();
242
243 EXPECT_NO_THROW({
244 auto bl = f1.get();
245 EXPECT_EQ("hello", bl.to_str());
246 });
247 EXPECT_THROW(f2.get(), boost::system::system_error);
248}
249
11fdf7f2
TL
250TEST_F(AsioRados, AsyncReadOperationYield)
251{
252 boost::asio::io_service service;
253
254 auto success_cr = [&] (boost::asio::yield_context yield) {
255 librados::ObjectReadOperation op;
256 op.read(0, 0, nullptr, nullptr);
257 boost::system::error_code ec;
258 auto bl = librados::async_operate(service, io, "exist", &op, 0,
259 yield[ec]);
260 EXPECT_FALSE(ec);
261 EXPECT_EQ("hello", bl.to_str());
262 };
263 boost::asio::spawn(service, success_cr);
264
265 auto failure_cr = [&] (boost::asio::yield_context yield) {
266 librados::ObjectReadOperation op;
267 op.read(0, 0, nullptr, nullptr);
268 boost::system::error_code ec;
269 auto bl = librados::async_operate(service, io, "noexist", &op, 0,
270 yield[ec]);
271 EXPECT_EQ(boost::system::errc::no_such_file_or_directory, ec);
272 };
273 boost::asio::spawn(service, failure_cr);
274
275 service.run();
276}
11fdf7f2
TL
277
278TEST_F(AsioRados, AsyncWriteOperationCallback)
279{
280 boost::asio::io_service service;
281
282 bufferlist bl;
283 bl.append("hello");
284
285 {
286 librados::ObjectWriteOperation op;
287 op.write_full(bl);
288 auto success_cb = [&] (boost::system::error_code ec) {
289 EXPECT_FALSE(ec);
290 };
291 librados::async_operate(service, io, "exist", &op, 0, success_cb);
292 }
293 {
294 librados::ObjectWriteOperation op;
295 op.write_full(bl);
296 auto failure_cb = [&] (boost::system::error_code ec) {
297 EXPECT_EQ(boost::system::errc::read_only_file_system, ec);
298 };
299 librados::async_operate(service, snapio, "exist", &op, 0, failure_cb);
300 }
301 service.run();
302}
303
304TEST_F(AsioRados, AsyncWriteOperationFuture)
305{
306 boost::asio::io_service service;
307
308 bufferlist bl;
309 bl.append("hello");
310
311 std::future<void> f1;
312 {
313 librados::ObjectWriteOperation op;
314 op.write_full(bl);
315 f1 = librados::async_operate(service, io, "exist", &op, 0,
316 boost::asio::use_future);
317 }
318 std::future<void> f2;
319 {
320 librados::ObjectWriteOperation op;
321 op.write_full(bl);
322 f2 = librados::async_operate(service, snapio, "exist", &op, 0,
323 boost::asio::use_future);
324 }
325 service.run();
326
327 EXPECT_NO_THROW(f1.get());
328 EXPECT_THROW(f2.get(), boost::system::system_error);
329}
330
11fdf7f2
TL
331TEST_F(AsioRados, AsyncWriteOperationYield)
332{
333 boost::asio::io_service service;
334
335 bufferlist bl;
336 bl.append("hello");
337
338 auto success_cr = [&] (boost::asio::yield_context yield) {
339 librados::ObjectWriteOperation op;
340 op.write_full(bl);
341 boost::system::error_code ec;
342 librados::async_operate(service, io, "exist", &op, 0, yield[ec]);
343 EXPECT_FALSE(ec);
344 };
345 boost::asio::spawn(service, success_cr);
346
347 auto failure_cr = [&] (boost::asio::yield_context yield) {
348 librados::ObjectWriteOperation op;
349 op.write_full(bl);
350 boost::system::error_code ec;
351 librados::async_operate(service, snapio, "exist", &op, 0, yield[ec]);
352 EXPECT_EQ(boost::system::errc::read_only_file_system, ec);
353 };
354 boost::asio::spawn(service, failure_cr);
355
356 service.run();
357}
11fdf7f2
TL
358
359int main(int argc, char **argv)
360{
20effc67 361 auto args = argv_to_vec(argc, argv);
11fdf7f2
TL
362 env_to_vec(args);
363
364 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
365 CODE_ENVIRONMENT_UTILITY, 0);
366 common_init_finish(cct.get());
367
368 ::testing::InitGoogleTest(&argc, argv);
369 return RUN_ALL_TESTS();
370}