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