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