]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados/io.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / librados / io.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*
2// vim: ts=8 sw=2 smarttab
3
4#include <climits>
5
6#include "include/rados/librados.h"
7c673cae 7#include "include/encoding.h"
c07f9fc5 8#include "include/err.h"
7c673cae
FG
9#include "include/scope_guard.h"
10#include "test/librados/test.h"
11#include "test/librados/TestCase.h"
12
13#include <errno.h>
14#include "gtest/gtest.h"
15
7c673cae
FG
16using std::string;
17
18typedef RadosTest LibRadosIo;
19typedef RadosTestEC LibRadosIoEC;
7c673cae
FG
20
21TEST_F(LibRadosIo, SimpleWrite) {
22 char buf[128];
23 memset(buf, 0xcc, sizeof(buf));
24 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
25 rados_ioctx_set_namespace(ioctx, "nspace");
26 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
27}
28
29TEST_F(LibRadosIo, TooBig) {
30 char buf[1];
31 ASSERT_EQ(-E2BIG, rados_write(ioctx, "A", buf, UINT_MAX, 0));
32 ASSERT_EQ(-E2BIG, rados_append(ioctx, "A", buf, UINT_MAX));
33 ASSERT_EQ(-E2BIG, rados_write_full(ioctx, "A", buf, UINT_MAX));
34 ASSERT_EQ(-E2BIG, rados_writesame(ioctx, "A", buf, sizeof(buf), UINT_MAX, 0));
7c673cae
FG
35}
36
37TEST_F(LibRadosIo, ReadTimeout) {
38 char buf[128];
39 memset(buf, 'a', sizeof(buf));
40 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
41
42 {
43 // set up a second client
44 rados_t cluster;
45 rados_ioctx_t ioctx;
46 ASSERT_EQ(0, rados_create(&cluster, "admin"));
47 ASSERT_EQ(0, rados_conf_read_file(cluster, NULL));
48 ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL));
49 ASSERT_EQ(0, rados_conf_set(cluster, "rados_osd_op_timeout", "0.00001")); // use any small value that will result in a timeout
50 ASSERT_EQ(0, rados_connect(cluster));
51 ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
52 rados_ioctx_set_namespace(ioctx, nspace.c_str());
53
54 // then we show that the buffer is changed after rados_read returned
55 // with a timeout
56 for (int i=0; i<5; i++) {
57 char buf2[sizeof(buf)];
58 memset(buf2, 0, sizeof(buf2));
59 int err = rados_read(ioctx, "foo", buf2, sizeof(buf2), 0);
60 if (err == -110) {
61 int startIndex = 0;
62 // find the index until which librados already read the object before the timeout occurred
63 for (unsigned b=0; b<sizeof(buf); b++) {
64 if (buf2[b] != buf[b]) {
65 startIndex = b;
66 break;
67 }
68 }
69
70 // wait some time to give librados a change to do something
71 sleep(1);
72
73 // then check if the buffer was changed after the call
74 if (buf2[startIndex] == 'a') {
75 printf("byte at index %d was changed after the timeout to %d\n",
76 startIndex, (int)buf[startIndex]);
77 ASSERT_TRUE(0);
78 break;
79 }
80 } else {
81 printf("no timeout :/\n");
82 }
83 }
84 rados_ioctx_destroy(ioctx);
85 rados_shutdown(cluster);
86 }
87}
88
7c673cae
FG
89
90TEST_F(LibRadosIo, RoundTrip) {
91 char buf[128];
92 char buf2[128];
93 memset(buf, 0xcc, sizeof(buf));
94 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
95 memset(buf2, 0, sizeof(buf2));
96 ASSERT_EQ((int)sizeof(buf2), rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
97 ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
98
99 uint64_t off = 19;
100 memset(buf, 0xcc, sizeof(buf));
101 ASSERT_EQ(0, rados_write(ioctx, "bar", buf, sizeof(buf), off));
102 memset(buf2, 0, sizeof(buf2));
103 ASSERT_EQ((int)sizeof(buf2), rados_read(ioctx, "bar", buf2, sizeof(buf2), off));
104 ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
105}
106
7c673cae
FG
107TEST_F(LibRadosIo, Checksum) {
108 char buf[128];
109 memset(buf, 0xcc, sizeof(buf));
110 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
111
112 uint32_t expected_crc = ceph_crc32c(-1, reinterpret_cast<const uint8_t*>(buf),
113 sizeof(buf));
114 uint32_t init_value = -1;
115 uint32_t crc[2];
116 ASSERT_EQ(0, rados_checksum(ioctx, "foo", LIBRADOS_CHECKSUM_TYPE_CRC32C,
117 reinterpret_cast<char*>(&init_value),
118 sizeof(init_value), sizeof(buf), 0, 0,
119 reinterpret_cast<char*>(&crc), sizeof(crc)));
120 ASSERT_EQ(1U, crc[0]);
121 ASSERT_EQ(expected_crc, crc[1]);
122}
123
7c673cae
FG
124TEST_F(LibRadosIo, OverlappingWriteRoundTrip) {
125 char buf[128];
126 char buf2[64];
127 char buf3[128];
128 memset(buf, 0xcc, sizeof(buf));
129 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
130 memset(buf2, 0xdd, sizeof(buf2));
131 ASSERT_EQ(0, rados_write(ioctx, "foo", buf2, sizeof(buf2), 0));
132 memset(buf3, 0xdd, sizeof(buf3));
133 ASSERT_EQ((int)sizeof(buf3), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
134 ASSERT_EQ(0, memcmp(buf3, buf2, sizeof(buf2)));
135 ASSERT_EQ(0, memcmp(buf3 + sizeof(buf2), buf, sizeof(buf) - sizeof(buf2)));
136}
137
7c673cae
FG
138TEST_F(LibRadosIo, WriteFullRoundTrip) {
139 char buf[128];
140 char buf2[64];
141 char buf3[128];
142 memset(buf, 0xcc, sizeof(buf));
143 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
144 memset(buf2, 0xdd, sizeof(buf2));
145 ASSERT_EQ(0, rados_write_full(ioctx, "foo", buf2, sizeof(buf2)));
146 memset(buf3, 0x00, sizeof(buf3));
147 ASSERT_EQ((int)sizeof(buf2), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
148 ASSERT_EQ(0, memcmp(buf2, buf3, sizeof(buf2)));
149}
150
7c673cae
FG
151TEST_F(LibRadosIo, AppendRoundTrip) {
152 char buf[64];
153 char buf2[64];
154 char buf3[sizeof(buf) + sizeof(buf2)];
155 memset(buf, 0xde, sizeof(buf));
156 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
157 memset(buf2, 0xad, sizeof(buf2));
158 ASSERT_EQ(0, rados_append(ioctx, "foo", buf2, sizeof(buf2)));
159 memset(buf3, 0, sizeof(buf3));
160 ASSERT_EQ((int)sizeof(buf3), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
161 ASSERT_EQ(0, memcmp(buf3, buf, sizeof(buf)));
162 ASSERT_EQ(0, memcmp(buf3 + sizeof(buf), buf2, sizeof(buf2)));
163}
164
7c673cae
FG
165TEST_F(LibRadosIo, TruncTest) {
166 char buf[128];
167 char buf2[sizeof(buf)];
168 memset(buf, 0xaa, sizeof(buf));
169 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
170 ASSERT_EQ(0, rados_trunc(ioctx, "foo", sizeof(buf) / 2));
171 memset(buf2, 0, sizeof(buf2));
172 ASSERT_EQ((int)(sizeof(buf)/2), rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
173 ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)/2));
174}
175
7c673cae
FG
176TEST_F(LibRadosIo, RemoveTest) {
177 char buf[128];
178 char buf2[sizeof(buf)];
179 memset(buf, 0xaa, sizeof(buf));
180 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
181 ASSERT_EQ(0, rados_remove(ioctx, "foo"));
182 memset(buf2, 0, sizeof(buf2));
183 ASSERT_EQ(-ENOENT, rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
184}
185
7c673cae
FG
186TEST_F(LibRadosIo, XattrsRoundTrip) {
187 char buf[128];
188 char attr1[] = "attr1";
189 char attr1_buf[] = "foo bar baz";
190 memset(buf, 0xaa, sizeof(buf));
191 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
192 ASSERT_EQ(-ENODATA, rados_getxattr(ioctx, "foo", attr1, buf, sizeof(buf)));
193 ASSERT_EQ(0, rados_setxattr(ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
194 ASSERT_EQ((int)sizeof(attr1_buf),
195 rados_getxattr(ioctx, "foo", attr1, buf, sizeof(buf)));
196 ASSERT_EQ(0, memcmp(attr1_buf, buf, sizeof(attr1_buf)));
197}
198
7c673cae
FG
199TEST_F(LibRadosIo, RmXattr) {
200 char buf[128];
201 char attr1[] = "attr1";
202 char attr1_buf[] = "foo bar baz";
203 memset(buf, 0xaa, sizeof(buf));
204 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
205 ASSERT_EQ(0,
206 rados_setxattr(ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
207 ASSERT_EQ(0, rados_rmxattr(ioctx, "foo", attr1));
208 ASSERT_EQ(-ENODATA, rados_getxattr(ioctx, "foo", attr1, buf, sizeof(buf)));
209
210 // Test rmxattr on a removed object
211 char buf2[128];
212 char attr2[] = "attr2";
213 char attr2_buf[] = "foo bar baz";
214 memset(buf2, 0xbb, sizeof(buf2));
215 ASSERT_EQ(0, rados_write(ioctx, "foo_rmxattr", buf2, sizeof(buf2), 0));
216 ASSERT_EQ(0,
217 rados_setxattr(ioctx, "foo_rmxattr", attr2, attr2_buf, sizeof(attr2_buf)));
218 ASSERT_EQ(0, rados_remove(ioctx, "foo_rmxattr"));
219 ASSERT_EQ(-ENOENT, rados_rmxattr(ioctx, "foo_rmxattr", attr2));
220}
221
7c673cae
FG
222TEST_F(LibRadosIo, XattrIter) {
223 char buf[128];
224 char attr1[] = "attr1";
225 char attr1_buf[] = "foo bar baz";
226 char attr2[] = "attr2";
227 char attr2_buf[256];
228 for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
229 attr2_buf[j] = j % 0xff;
230 }
231 memset(buf, 0xaa, sizeof(buf));
232 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
233 ASSERT_EQ(0, rados_setxattr(ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
234 ASSERT_EQ(0, rados_setxattr(ioctx, "foo", attr2, attr2_buf, sizeof(attr2_buf)));
235 rados_xattrs_iter_t iter;
236 ASSERT_EQ(0, rados_getxattrs(ioctx, "foo", &iter));
237 int num_seen = 0;
238 while (true) {
239 const char *name;
240 const char *val;
241 size_t len;
242 ASSERT_EQ(0, rados_getxattrs_next(iter, &name, &val, &len));
243 if (name == NULL) {
244 break;
245 }
246 ASSERT_LT(num_seen, 2);
247 if ((strcmp(name, attr1) == 0) && (val != NULL) && (memcmp(val, attr1_buf, len) == 0)) {
248 num_seen++;
249 continue;
250 }
251 else if ((strcmp(name, attr2) == 0) && (val != NULL) && (memcmp(val, attr2_buf, len) == 0)) {
252 num_seen++;
253 continue;
254 }
255 else {
256 ASSERT_EQ(0, 1);
257 }
258 }
259 rados_getxattrs_end(iter);
260}
261
7c673cae
FG
262TEST_F(LibRadosIoEC, SimpleWrite) {
263 char buf[128];
264 memset(buf, 0xcc, sizeof(buf));
265 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
266 rados_ioctx_set_namespace(ioctx, "nspace");
267 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
268}
269
7c673cae
FG
270TEST_F(LibRadosIoEC, RoundTrip) {
271 char buf[128];
272 char buf2[128];
273 memset(buf, 0xcc, sizeof(buf));
274 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
275 memset(buf2, 0, sizeof(buf2));
276 ASSERT_EQ((int)sizeof(buf2), rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
277 ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
278
279 uint64_t off = 19;
280 ASSERT_EQ(-EOPNOTSUPP, rados_write(ioctx, "bar", buf, sizeof(buf), off));
281}
282
7c673cae
FG
283TEST_F(LibRadosIoEC, OverlappingWriteRoundTrip) {
284 int bsize = alignment;
285 int dbsize = bsize * 2;
286 char *buf = (char *)new char[dbsize];
287 char *buf2 = (char *)new char[bsize];
288 char *buf3 = (char *)new char[dbsize];
289 auto cleanup = [&] {
290 delete[] buf;
291 delete[] buf2;
292 delete[] buf3;
293 };
294 scope_guard<decltype(cleanup)> sg(std::move(cleanup));
295 memset(buf, 0xcc, dbsize);
296 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, dbsize, 0));
297 memset(buf2, 0xdd, bsize);
298 ASSERT_EQ(-EOPNOTSUPP, rados_write(ioctx, "foo", buf2, bsize, 0));
299 memset(buf3, 0xdd, dbsize);
300 ASSERT_EQ(dbsize, rados_read(ioctx, "foo", buf3, dbsize, 0));
301 // Read the same as first write
302 ASSERT_EQ(0, memcmp(buf3, buf, dbsize));
303}
304
7c673cae
FG
305TEST_F(LibRadosIoEC, WriteFullRoundTrip) {
306 char buf[128];
307 char buf2[64];
308 char buf3[128];
309 memset(buf, 0xcc, sizeof(buf));
310 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
311 memset(buf2, 0xdd, sizeof(buf2));
312 ASSERT_EQ(0, rados_write_full(ioctx, "foo", buf2, sizeof(buf2)));
313 memset(buf3, 0xee, sizeof(buf3));
314 ASSERT_EQ((int)sizeof(buf2), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
315 ASSERT_EQ(0, memcmp(buf3, buf2, sizeof(buf2)));
316}
317
7c673cae
FG
318TEST_F(LibRadosIoEC, AppendRoundTrip) {
319 char *buf = (char *)new char[alignment];
320 char *buf2 = (char *)new char[alignment];
321 char *buf3 = (char *)new char[alignment *2];
322 int uasize = alignment/2;
323 char *unalignedbuf = (char *)new char[uasize];
324 auto cleanup = [&] {
325 delete[] buf;
326 delete[] buf2;
327 delete[] buf3;
328 delete[] unalignedbuf;
329 };
330 scope_guard<decltype(cleanup)> sg(std::move(cleanup));
331 memset(buf, 0xde, alignment);
332 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, alignment));
333 memset(buf2, 0xad, alignment);
334 ASSERT_EQ(0, rados_append(ioctx, "foo", buf2, alignment));
335 memset(buf3, 0, alignment*2);
336 ASSERT_EQ((int)alignment*2, rados_read(ioctx, "foo", buf3, alignment*2, 0));
337 ASSERT_EQ(0, memcmp(buf3, buf, alignment));
338 ASSERT_EQ(0, memcmp(buf3 + alignment, buf2, alignment));
339 memset(unalignedbuf, 0, uasize);
340 ASSERT_EQ(0, rados_append(ioctx, "foo", unalignedbuf, uasize));
341 ASSERT_EQ(-EOPNOTSUPP, rados_append(ioctx, "foo", unalignedbuf, uasize));
342}
343
7c673cae
FG
344TEST_F(LibRadosIoEC, TruncTest) {
345 char buf[128];
346 char buf2[sizeof(buf)];
347 memset(buf, 0xaa, sizeof(buf));
348 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
349 ASSERT_EQ(-EOPNOTSUPP, rados_trunc(ioctx, "foo", sizeof(buf) / 2));
350 memset(buf2, 0, sizeof(buf2));
351 // Same size
352 ASSERT_EQ((int)sizeof(buf), rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
353 // No change
354 ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
355}
356
7c673cae
FG
357TEST_F(LibRadosIoEC, RemoveTest) {
358 char buf[128];
359 char buf2[sizeof(buf)];
360 memset(buf, 0xaa, sizeof(buf));
361 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
362 ASSERT_EQ(0, rados_remove(ioctx, "foo"));
363 memset(buf2, 0, sizeof(buf2));
364 ASSERT_EQ(-ENOENT, rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
365}
366
7c673cae
FG
367TEST_F(LibRadosIoEC, XattrsRoundTrip) {
368 char buf[128];
369 char attr1[] = "attr1";
370 char attr1_buf[] = "foo bar baz";
371 memset(buf, 0xaa, sizeof(buf));
372 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
373 ASSERT_EQ(-ENODATA, rados_getxattr(ioctx, "foo", attr1, buf, sizeof(buf)));
374 ASSERT_EQ(0, rados_setxattr(ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
375 ASSERT_EQ((int)sizeof(attr1_buf),
376 rados_getxattr(ioctx, "foo", attr1, buf, sizeof(buf)));
377 ASSERT_EQ(0, memcmp(attr1_buf, buf, sizeof(attr1_buf)));
378}
379
7c673cae
FG
380TEST_F(LibRadosIoEC, RmXattr) {
381 char buf[128];
382 char attr1[] = "attr1";
383 char attr1_buf[] = "foo bar baz";
384 memset(buf, 0xaa, sizeof(buf));
385 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
386 ASSERT_EQ(0,
387 rados_setxattr(ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
388 ASSERT_EQ(0, rados_rmxattr(ioctx, "foo", attr1));
389 ASSERT_EQ(-ENODATA, rados_getxattr(ioctx, "foo", attr1, buf, sizeof(buf)));
390
391 // Test rmxattr on a removed object
392 char buf2[128];
393 char attr2[] = "attr2";
394 char attr2_buf[] = "foo bar baz";
395 memset(buf2, 0xbb, sizeof(buf2));
396 ASSERT_EQ(0, rados_write(ioctx, "foo_rmxattr", buf2, sizeof(buf2), 0));
397 ASSERT_EQ(0,
398 rados_setxattr(ioctx, "foo_rmxattr", attr2, attr2_buf, sizeof(attr2_buf)));
399 ASSERT_EQ(0, rados_remove(ioctx, "foo_rmxattr"));
400 ASSERT_EQ(-ENOENT, rados_rmxattr(ioctx, "foo_rmxattr", attr2));
401}
402
7c673cae
FG
403TEST_F(LibRadosIoEC, XattrIter) {
404 char buf[128];
405 char attr1[] = "attr1";
406 char attr1_buf[] = "foo bar baz";
407 char attr2[] = "attr2";
408 char attr2_buf[256];
409 for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
410 attr2_buf[j] = j % 0xff;
411 }
412 memset(buf, 0xaa, sizeof(buf));
413 ASSERT_EQ(0, rados_append(ioctx, "foo", buf, sizeof(buf)));
414 ASSERT_EQ(0, rados_setxattr(ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
415 ASSERT_EQ(0, rados_setxattr(ioctx, "foo", attr2, attr2_buf, sizeof(attr2_buf)));
416 rados_xattrs_iter_t iter;
417 ASSERT_EQ(0, rados_getxattrs(ioctx, "foo", &iter));
418 int num_seen = 0;
419 while (true) {
420 const char *name;
421 const char *val;
422 size_t len;
423 ASSERT_EQ(0, rados_getxattrs_next(iter, &name, &val, &len));
424 if (name == NULL) {
425 break;
426 }
427 ASSERT_LT(num_seen, 2);
428 if ((strcmp(name, attr1) == 0) && (val != NULL) && (memcmp(val, attr1_buf, len) == 0)) {
429 num_seen++;
430 continue;
431 }
432 else if ((strcmp(name, attr2) == 0) && (val != NULL) && (memcmp(val, attr2_buf, len) == 0)) {
433 num_seen++;
434 continue;
435 }
436 else {
437 ASSERT_EQ(0, 1);
438 }
439 }
440 rados_getxattrs_end(iter);
441}