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