]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librados/io_cxx.cc
import quincy 17.2.0
[ceph.git] / ceph / src / test / librados / io_cxx.cc
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 #include <errno.h>
6
7 #include "gtest/gtest.h"
8
9 #include "include/rados/librados.hpp"
10 #include "include/encoding.h"
11 #include "include/err.h"
12 #include "include/scope_guard.h"
13 #include "test/librados/test_cxx.h"
14 #include "test/librados/testcase_cxx.h"
15
16 using namespace librados;
17 using std::string;
18
19 typedef RadosTestPP LibRadosIoPP;
20 typedef RadosTestECPP LibRadosIoECPP;
21
22 TEST_F(LibRadosIoPP, TooBigPP) {
23 IoCtx ioctx;
24 bufferlist bl;
25 ASSERT_EQ(-E2BIG, ioctx.write("foo", bl, UINT_MAX, 0));
26 ASSERT_EQ(-E2BIG, ioctx.append("foo", bl, UINT_MAX));
27 // ioctx.write_full no way to overflow bl.length()
28 ASSERT_EQ(-E2BIG, ioctx.writesame("foo", bl, UINT_MAX, 0));
29 }
30
31 TEST_F(LibRadosIoPP, SimpleWritePP) {
32 char buf[128];
33 memset(buf, 0xcc, sizeof(buf));
34 bufferlist bl;
35 bl.append(buf, sizeof(buf));
36 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
37 ioctx.set_namespace("nspace");
38 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
39 }
40
41 TEST_F(LibRadosIoPP, ReadOpPP) {
42 char buf[128];
43 memset(buf, 0xcc, sizeof(buf));
44 bufferlist bl;
45 bl.append(buf, sizeof(buf));
46 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
47
48 {
49 bufferlist op_bl;
50 ObjectReadOperation op;
51 op.read(0, sizeof(buf), NULL, NULL);
52 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
53 ASSERT_EQ(sizeof(buf), op_bl.length());
54 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
55 }
56
57 {
58 bufferlist op_bl;
59 ObjectReadOperation op;
60 op.read(0, 0, NULL, NULL); //len=0 mean read the whole object data.
61 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
62 ASSERT_EQ(sizeof(buf), op_bl.length());
63 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
64 }
65
66 {
67 bufferlist read_bl, op_bl;
68 ObjectReadOperation op;
69 op.read(0, sizeof(buf), &read_bl, NULL);
70 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
71 ASSERT_EQ(sizeof(buf), read_bl.length());
72 ASSERT_EQ(sizeof(buf), op_bl.length());
73 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
74 ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
75 }
76
77 {
78 bufferlist op_bl;
79 int rval = 1000;
80 ObjectReadOperation op;
81 op.read(0, sizeof(buf), NULL, &rval);
82 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
83 ASSERT_EQ(sizeof(buf), op_bl.length());
84 ASSERT_EQ(0, rval);
85 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
86 }
87
88 {
89 bufferlist read_bl, op_bl;
90 int rval = 1000;
91 ObjectReadOperation op;
92 op.read(0, sizeof(buf), &read_bl, &rval);
93 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
94 ASSERT_EQ(sizeof(buf), read_bl.length());
95 ASSERT_EQ(sizeof(buf), op_bl.length());
96 ASSERT_EQ(0, rval);
97 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
98 ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
99 }
100
101 {
102 bufferlist read_bl1, read_bl2, op_bl;
103 int rval1 = 1000, rval2 = 1002;
104 ObjectReadOperation op;
105 op.read(0, sizeof(buf), &read_bl1, &rval1);
106 op.read(0, sizeof(buf), &read_bl2, &rval2);
107 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
108 ASSERT_EQ(sizeof(buf), read_bl1.length());
109 ASSERT_EQ(sizeof(buf), read_bl2.length());
110 ASSERT_EQ(sizeof(buf) * 2, op_bl.length());
111 ASSERT_EQ(0, rval1);
112 ASSERT_EQ(0, rval2);
113 ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
114 ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
115 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
116 ASSERT_EQ(0, memcmp(op_bl.c_str() + sizeof(buf), buf, sizeof(buf)));
117 }
118
119 {
120 bufferlist op_bl;
121 ObjectReadOperation op;
122 op.read(0, sizeof(buf), NULL, NULL);
123 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
124 ASSERT_EQ(sizeof(buf), op_bl.length());
125 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
126 }
127
128 {
129 bufferlist read_bl;
130 ObjectReadOperation op;
131 op.read(0, sizeof(buf), &read_bl, NULL);
132 ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
133 ASSERT_EQ(sizeof(buf), read_bl.length());
134 ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
135 }
136
137 {
138 int rval = 1000;
139 ObjectReadOperation op;
140 op.read(0, sizeof(buf), NULL, &rval);
141 ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
142 ASSERT_EQ(0, rval);
143 }
144
145 {
146 bufferlist read_bl;
147 int rval = 1000;
148 ObjectReadOperation op;
149 op.read(0, sizeof(buf), &read_bl, &rval);
150 ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
151 ASSERT_EQ(sizeof(buf), read_bl.length());
152 ASSERT_EQ(0, rval);
153 ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
154 }
155
156 {
157 bufferlist read_bl1, read_bl2;
158 int rval1 = 1000, rval2 = 1002;
159 ObjectReadOperation op;
160 op.read(0, sizeof(buf), &read_bl1, &rval1);
161 op.read(0, sizeof(buf), &read_bl2, &rval2);
162 ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
163 ASSERT_EQ(sizeof(buf), read_bl1.length());
164 ASSERT_EQ(sizeof(buf), read_bl2.length());
165 ASSERT_EQ(0, rval1);
166 ASSERT_EQ(0, rval2);
167 ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
168 ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
169 }
170
171 // read into a preallocated buffer with a cached crc
172 {
173 bufferlist op_bl;
174 op_bl.append(std::string(sizeof(buf), 'x'));
175 ASSERT_NE(op_bl.crc32c(0), bl.crc32c(0)); // cache 'x' crc
176
177 ObjectReadOperation op;
178 op.read(0, sizeof(buf), NULL, NULL);
179 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
180
181 ASSERT_EQ(sizeof(buf), op_bl.length());
182 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
183 ASSERT_EQ(op_bl.crc32c(0), bl.crc32c(0));
184 }
185 }
186
187 TEST_F(LibRadosIoPP, SparseReadOpPP) {
188 char buf[128];
189 memset(buf, 0xcc, sizeof(buf));
190 bufferlist bl;
191 bl.append(buf, sizeof(buf));
192 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
193
194 {
195 std::map<uint64_t, uint64_t> extents;
196 bufferlist read_bl;
197 int rval = -1;
198 ObjectReadOperation op;
199 op.sparse_read(0, sizeof(buf), &extents, &read_bl, &rval);
200 ASSERT_EQ(0, ioctx.operate("foo", &op, nullptr));
201 ASSERT_EQ(0, rval);
202 assert_eq_sparse(bl, extents, read_bl);
203 }
204 {
205 bufferlist bl;
206 bl.append(buf, sizeof(buf) / 2);
207
208 std::map<uint64_t, uint64_t> extents;
209 bufferlist read_bl;
210 int rval = -1;
211 ObjectReadOperation op;
212 op.sparse_read(0, sizeof(buf), &extents, &read_bl, &rval, sizeof(buf) / 2, 1);
213 ASSERT_EQ(0, ioctx.operate("foo", &op, nullptr));
214 ASSERT_EQ(0, rval);
215 assert_eq_sparse(bl, extents, read_bl);
216 }
217 }
218
219 TEST_F(LibRadosIoPP, RoundTripPP) {
220 char buf[128];
221 Rados cluster;
222 memset(buf, 0xcc, sizeof(buf));
223 bufferlist bl;
224 bl.append(buf, sizeof(buf));
225 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
226 bufferlist cl;
227 ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", cl, sizeof(buf), 0));
228 ASSERT_EQ(0, memcmp(buf, cl.c_str(), sizeof(buf)));
229 }
230
231 TEST_F(LibRadosIoPP, RoundTripPP2)
232 {
233 bufferlist bl;
234 bl.append("ceph");
235 ObjectWriteOperation write;
236 write.write(0, bl);
237 write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
238 ASSERT_EQ(0, ioctx.operate("foo", &write));
239
240 ObjectReadOperation read;
241 read.read(0, bl.length(), NULL, NULL);
242 read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
243 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
244 ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
245 }
246
247 TEST_F(LibRadosIoPP, Checksum) {
248 char buf[128];
249 Rados cluster;
250 memset(buf, 0xcc, sizeof(buf));
251 bufferlist bl;
252 bl.append(buf, sizeof(buf));
253 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
254 bufferlist init_value_bl;
255 encode(static_cast<uint32_t>(-1), init_value_bl);
256 bufferlist csum_bl;
257 ASSERT_EQ(0, ioctx.checksum("foo", LIBRADOS_CHECKSUM_TYPE_CRC32C,
258 init_value_bl, sizeof(buf), 0, 0, &csum_bl));
259 auto csum_bl_it = csum_bl.cbegin();
260 uint32_t csum_count;
261 decode(csum_count, csum_bl_it);
262 ASSERT_EQ(1U, csum_count);
263 uint32_t csum;
264 decode(csum, csum_bl_it);
265 ASSERT_EQ(bl.crc32c(-1), csum);
266 }
267
268 TEST_F(LibRadosIoPP, ReadIntoBufferlist) {
269
270 // here we test reading into a non-empty bufferlist referencing existing
271 // buffers
272
273 char buf[128];
274 Rados cluster;
275 memset(buf, 0xcc, sizeof(buf));
276 bufferlist bl;
277 bl.append(buf, sizeof(buf));
278 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
279 bufferlist bl2;
280 char buf2[sizeof(buf)];
281 memset(buf2, 0xbb, sizeof(buf2));
282 bl2.append(buffer::create_static(sizeof(buf2), buf2));
283 ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl2, sizeof(buf), 0));
284 ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
285 ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
286 }
287
288 TEST_F(LibRadosIoPP, OverlappingWriteRoundTripPP) {
289 char buf[128];
290 char buf2[64];
291 memset(buf, 0xcc, sizeof(buf));
292 bufferlist bl1;
293 bl1.append(buf, sizeof(buf));
294 ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
295 memset(buf2, 0xdd, sizeof(buf2));
296 bufferlist bl2;
297 bl2.append(buf2, sizeof(buf2));
298 ASSERT_EQ(0, ioctx.write("foo", bl2, sizeof(buf2), 0));
299 bufferlist bl3;
300 ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
301 ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
302 ASSERT_EQ(0, memcmp(bl3.c_str() + sizeof(buf2), buf, sizeof(buf) - sizeof(buf2)));
303 }
304
305 TEST_F(LibRadosIoPP, WriteFullRoundTripPP) {
306 char buf[128];
307 char buf2[64];
308 memset(buf, 0xcc, sizeof(buf));
309 bufferlist bl1;
310 bl1.append(buf, sizeof(buf));
311 ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
312 memset(buf2, 0xdd, sizeof(buf2));
313 bufferlist bl2;
314 bl2.append(buf2, sizeof(buf2));
315 ASSERT_EQ(0, ioctx.write_full("foo", bl2));
316 bufferlist bl3;
317 ASSERT_EQ((int)sizeof(buf2), ioctx.read("foo", bl3, sizeof(buf), 0));
318 ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
319 }
320
321 TEST_F(LibRadosIoPP, WriteFullRoundTripPP2)
322 {
323 bufferlist bl;
324 bl.append("ceph");
325 ObjectWriteOperation write;
326 write.write_full(bl);
327 write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
328 ASSERT_EQ(0, ioctx.operate("foo", &write));
329
330 ObjectReadOperation read;
331 read.read(0, bl.length(), NULL, NULL);
332 read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
333 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
334 ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
335 }
336
337 TEST_F(LibRadosIoPP, AppendRoundTripPP) {
338 char buf[64];
339 char buf2[64];
340 memset(buf, 0xde, sizeof(buf));
341 bufferlist bl1;
342 bl1.append(buf, sizeof(buf));
343 ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
344 memset(buf2, 0xad, sizeof(buf2));
345 bufferlist bl2;
346 bl2.append(buf2, sizeof(buf2));
347 ASSERT_EQ(0, ioctx.append("foo", bl2, sizeof(buf2)));
348 bufferlist bl3;
349 ASSERT_EQ((int)(sizeof(buf) + sizeof(buf2)),
350 ioctx.read("foo", bl3, (sizeof(buf) + sizeof(buf2)), 0));
351 const char *bl3_str = bl3.c_str();
352 ASSERT_EQ(0, memcmp(bl3_str, buf, sizeof(buf)));
353 ASSERT_EQ(0, memcmp(bl3_str + sizeof(buf), buf2, sizeof(buf2)));
354 }
355
356 TEST_F(LibRadosIoPP, TruncTestPP) {
357 char buf[128];
358 memset(buf, 0xaa, sizeof(buf));
359 bufferlist bl;
360 bl.append(buf, sizeof(buf));
361 ASSERT_EQ(0, ioctx.append("foo", bl, sizeof(buf)));
362 ASSERT_EQ(0, ioctx.trunc("foo", sizeof(buf) / 2));
363 bufferlist bl2;
364 ASSERT_EQ((int)(sizeof(buf)/2), ioctx.read("foo", bl2, sizeof(buf), 0));
365 ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)/2));
366 }
367
368 TEST_F(LibRadosIoPP, RemoveTestPP) {
369 char buf[128];
370 memset(buf, 0xaa, sizeof(buf));
371 bufferlist bl1;
372 bl1.append(buf, sizeof(buf));
373 ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
374 ASSERT_EQ(0, ioctx.remove("foo"));
375 bufferlist bl2;
376 ASSERT_EQ(-ENOENT, ioctx.read("foo", bl2, sizeof(buf), 0));
377 }
378
379 TEST_F(LibRadosIoPP, XattrsRoundTripPP) {
380 char buf[128];
381 char attr1[] = "attr1";
382 char attr1_buf[] = "foo bar baz";
383 memset(buf, 0xaa, sizeof(buf));
384 bufferlist bl1;
385 bl1.append(buf, sizeof(buf));
386 ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
387 bufferlist bl2;
388 ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl2));
389 bufferlist bl3;
390 bl3.append(attr1_buf, sizeof(attr1_buf));
391 ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl3));
392 bufferlist bl4;
393 ASSERT_EQ((int)sizeof(attr1_buf),
394 ioctx.getxattr("foo", attr1, bl4));
395 ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
396 }
397
398 TEST_F(LibRadosIoPP, RmXattrPP) {
399 char buf[128];
400 char attr1[] = "attr1";
401 char attr1_buf[] = "foo bar baz";
402 memset(buf, 0xaa, sizeof(buf));
403 bufferlist bl1;
404 bl1.append(buf, sizeof(buf));
405 ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
406 bufferlist bl2;
407 bl2.append(attr1_buf, sizeof(attr1_buf));
408 ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
409 ASSERT_EQ(0, ioctx.rmxattr("foo", attr1));
410 bufferlist bl3;
411 ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl3));
412
413 // Test rmxattr on a removed object
414 char buf2[128];
415 char attr2[] = "attr2";
416 char attr2_buf[] = "foo bar baz";
417 memset(buf2, 0xbb, sizeof(buf2));
418 bufferlist bl21;
419 bl21.append(buf, sizeof(buf));
420 ASSERT_EQ(0, ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
421 bufferlist bl22;
422 bl22.append(attr2_buf, sizeof(attr2_buf));
423 ASSERT_EQ(0, ioctx.setxattr("foo_rmxattr", attr2, bl22));
424 ASSERT_EQ(0, ioctx.remove("foo_rmxattr"));
425 ASSERT_EQ(-ENOENT, ioctx.rmxattr("foo_rmxattr", attr2));
426 }
427
428 TEST_F(LibRadosIoPP, XattrListPP) {
429 char buf[128];
430 char attr1[] = "attr1";
431 char attr1_buf[] = "foo bar baz";
432 char attr2[] = "attr2";
433 char attr2_buf[256];
434 for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
435 attr2_buf[j] = j % 0xff;
436 }
437 memset(buf, 0xaa, sizeof(buf));
438 bufferlist bl1;
439 bl1.append(buf, sizeof(buf));
440 ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
441 bufferlist bl2;
442 bl2.append(attr1_buf, sizeof(attr1_buf));
443 ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
444 bufferlist bl3;
445 bl3.append(attr2_buf, sizeof(attr2_buf));
446 ASSERT_EQ(0, ioctx.setxattr("foo", attr2, bl3));
447 std::map<std::string, bufferlist> attrset;
448 ASSERT_EQ(0, ioctx.getxattrs("foo", attrset));
449 for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
450 i != attrset.end(); ++i) {
451 if (i->first == string(attr1)) {
452 ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
453 }
454 else if (i->first == string(attr2)) {
455 ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
456 }
457 else {
458 ASSERT_EQ(0, 1);
459 }
460 }
461 }
462
463 TEST_F(LibRadosIoECPP, SimpleWritePP) {
464 char buf[128];
465 memset(buf, 0xcc, sizeof(buf));
466 bufferlist bl;
467 bl.append(buf, sizeof(buf));
468 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
469 ioctx.set_namespace("nspace");
470 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
471 }
472
473 TEST_F(LibRadosIoECPP, ReadOpPP) {
474 char buf[128];
475 memset(buf, 0xcc, sizeof(buf));
476 bufferlist bl;
477 bl.append(buf, sizeof(buf));
478 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
479
480 {
481 bufferlist op_bl;
482 ObjectReadOperation op;
483 op.read(0, sizeof(buf), NULL, NULL);
484 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
485 ASSERT_EQ(sizeof(buf), op_bl.length());
486 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
487 }
488
489 {
490 bufferlist op_bl;
491 ObjectReadOperation op;
492 op.read(0, 0, NULL, NULL); //len=0 mean read the whole object data
493 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
494 ASSERT_EQ(sizeof(buf), op_bl.length());
495 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
496 }
497
498 {
499 bufferlist read_bl, op_bl;
500 ObjectReadOperation op;
501 op.read(0, sizeof(buf), &read_bl, NULL);
502 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
503 ASSERT_EQ(sizeof(buf), read_bl.length());
504 ASSERT_EQ(sizeof(buf), op_bl.length());
505 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
506 ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
507 }
508
509 {
510 bufferlist op_bl;
511 int rval = 1000;
512 ObjectReadOperation op;
513 op.read(0, sizeof(buf), NULL, &rval);
514 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
515 ASSERT_EQ(sizeof(buf), op_bl.length());
516 ASSERT_EQ(0, rval);
517 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
518 }
519
520 {
521 bufferlist read_bl, op_bl;
522 int rval = 1000;
523 ObjectReadOperation op;
524 op.read(0, sizeof(buf), &read_bl, &rval);
525 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
526 ASSERT_EQ(sizeof(buf), read_bl.length());
527 ASSERT_EQ(sizeof(buf), op_bl.length());
528 ASSERT_EQ(0, rval);
529 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
530 ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
531 }
532
533 {
534 bufferlist read_bl1, read_bl2, op_bl;
535 int rval1 = 1000, rval2 = 1002;
536 ObjectReadOperation op;
537 op.read(0, sizeof(buf), &read_bl1, &rval1);
538 op.read(0, sizeof(buf), &read_bl2, &rval2);
539 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
540 ASSERT_EQ(sizeof(buf), read_bl1.length());
541 ASSERT_EQ(sizeof(buf), read_bl2.length());
542 ASSERT_EQ(sizeof(buf) * 2, op_bl.length());
543 ASSERT_EQ(0, rval1);
544 ASSERT_EQ(0, rval2);
545 ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
546 ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
547 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
548 ASSERT_EQ(0, memcmp(op_bl.c_str() + sizeof(buf), buf, sizeof(buf)));
549 }
550
551 {
552 bufferlist op_bl;
553 ObjectReadOperation op;
554 op.read(0, sizeof(buf), NULL, NULL);
555 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
556 ASSERT_EQ(sizeof(buf), op_bl.length());
557 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
558 }
559
560 {
561 bufferlist read_bl;
562 ObjectReadOperation op;
563 op.read(0, sizeof(buf), &read_bl, NULL);
564 ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
565 ASSERT_EQ(sizeof(buf), read_bl.length());
566 ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
567 }
568
569 {
570 int rval = 1000;
571 ObjectReadOperation op;
572 op.read(0, sizeof(buf), NULL, &rval);
573 ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
574 ASSERT_EQ(0, rval);
575 }
576
577 {
578 bufferlist read_bl;
579 int rval = 1000;
580 ObjectReadOperation op;
581 op.read(0, sizeof(buf), &read_bl, &rval);
582 ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
583 ASSERT_EQ(sizeof(buf), read_bl.length());
584 ASSERT_EQ(0, rval);
585 ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
586 }
587
588 {
589 bufferlist read_bl1, read_bl2;
590 int rval1 = 1000, rval2 = 1002;
591 ObjectReadOperation op;
592 op.read(0, sizeof(buf), &read_bl1, &rval1);
593 op.read(0, sizeof(buf), &read_bl2, &rval2);
594 ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
595 ASSERT_EQ(sizeof(buf), read_bl1.length());
596 ASSERT_EQ(sizeof(buf), read_bl2.length());
597 ASSERT_EQ(0, rval1);
598 ASSERT_EQ(0, rval2);
599 ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
600 ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
601 }
602
603 // read into a preallocated buffer with a cached crc
604 {
605 bufferlist op_bl;
606 op_bl.append(std::string(sizeof(buf), 'x'));
607 ASSERT_NE(op_bl.crc32c(0), bl.crc32c(0)); // cache 'x' crc
608
609 ObjectReadOperation op;
610 op.read(0, sizeof(buf), NULL, NULL);
611 ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
612
613 ASSERT_EQ(sizeof(buf), op_bl.length());
614 ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
615 ASSERT_EQ(op_bl.crc32c(0), bl.crc32c(0));
616 }
617 }
618
619 TEST_F(LibRadosIoECPP, SparseReadOpPP) {
620 char buf[128];
621 memset(buf, 0xcc, sizeof(buf));
622 bufferlist bl;
623 bl.append(buf, sizeof(buf));
624 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
625
626 {
627 std::map<uint64_t, uint64_t> extents;
628 bufferlist read_bl;
629 int rval = -1;
630 ObjectReadOperation op;
631 op.sparse_read(0, sizeof(buf), &extents, &read_bl, &rval);
632 ASSERT_EQ(0, ioctx.operate("foo", &op, nullptr));
633 ASSERT_EQ(0, rval);
634 assert_eq_sparse(bl, extents, read_bl);
635 }
636 }
637
638 TEST_F(LibRadosIoECPP, RoundTripPP) {
639 char buf[128];
640 Rados cluster;
641 memset(buf, 0xcc, sizeof(buf));
642 bufferlist bl;
643 bl.append(buf, sizeof(buf));
644 ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
645 bufferlist cl;
646 ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", cl, sizeof(buf) * 3, 0));
647 ASSERT_EQ(0, memcmp(buf, cl.c_str(), sizeof(buf)));
648 }
649
650 TEST_F(LibRadosIoECPP, RoundTripPP2)
651 {
652 bufferlist bl;
653 bl.append("ceph");
654 ObjectWriteOperation write;
655 write.write(0, bl);
656 write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
657 ASSERT_EQ(0, ioctx.operate("foo", &write));
658
659 ObjectReadOperation read;
660 read.read(0, bl.length(), NULL, NULL);
661 read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
662 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
663 ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
664 }
665
666 TEST_F(LibRadosIoECPP, OverlappingWriteRoundTripPP) {
667 int bsize = alignment;
668 int dbsize = bsize * 2;
669 char *buf = (char *)new char[dbsize];
670 char *buf2 = (char *)new char[bsize];
671 auto cleanup = [&] {
672 delete[] buf;
673 delete[] buf2;
674 };
675 scope_guard<decltype(cleanup)> sg(std::move(cleanup));
676 memset(buf, 0xcc, dbsize);
677 bufferlist bl1;
678 bl1.append(buf, dbsize);
679 ASSERT_EQ(0, ioctx.write("foo", bl1, dbsize, 0));
680 memset(buf2, 0xdd, bsize);
681 bufferlist bl2;
682 bl2.append(buf2, bsize);
683 ASSERT_EQ(-EOPNOTSUPP, ioctx.write("foo", bl2, bsize, 0));
684 bufferlist bl3;
685 ASSERT_EQ(dbsize, ioctx.read("foo", bl3, dbsize, 0));
686 // Read the same as first write
687 ASSERT_EQ(0, memcmp(bl3.c_str(), buf, dbsize));
688 }
689
690 TEST_F(LibRadosIoECPP, WriteFullRoundTripPP) {
691 char buf[128];
692 char buf2[64];
693 memset(buf, 0xcc, sizeof(buf));
694 bufferlist bl1;
695 bl1.append(buf, sizeof(buf));
696 ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0));
697 memset(buf2, 0xdd, sizeof(buf2));
698 bufferlist bl2;
699 bl2.append(buf2, sizeof(buf2));
700 ASSERT_EQ(0, ioctx.write_full("foo", bl2));
701 bufferlist bl3;
702 ASSERT_EQ((int)sizeof(buf2), ioctx.read("foo", bl3, sizeof(buf), 0));
703 ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
704 }
705
706 TEST_F(LibRadosIoECPP, WriteFullRoundTripPP2)
707 {
708 bufferlist bl;
709 bl.append("ceph");
710 ObjectWriteOperation write;
711 write.write_full(bl);
712 write.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
713 ASSERT_EQ(0, ioctx.operate("foo", &write));
714
715 ObjectReadOperation read;
716 read.read(0, bl.length(), NULL, NULL);
717 read.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
718 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
719 ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
720 }
721
722 TEST_F(LibRadosIoECPP, AppendRoundTripPP) {
723 char *buf = (char *)new char[alignment];
724 char *buf2 = (char *)new char[alignment];
725 auto cleanup = [&] {
726 delete[] buf;
727 delete[] buf2;
728 };
729 scope_guard<decltype(cleanup)> sg(std::move(cleanup));
730 memset(buf, 0xde, alignment);
731 bufferlist bl1;
732 bl1.append(buf, alignment);
733 ASSERT_EQ(0, ioctx.append("foo", bl1, alignment));
734 memset(buf2, 0xad, alignment);
735 bufferlist bl2;
736 bl2.append(buf2, alignment);
737 ASSERT_EQ(0, ioctx.append("foo", bl2, alignment));
738 bufferlist bl3;
739 ASSERT_EQ((int)(alignment * 2),
740 ioctx.read("foo", bl3, (alignment * 4), 0));
741 const char *bl3_str = bl3.c_str();
742 ASSERT_EQ(0, memcmp(bl3_str, buf, alignment));
743 ASSERT_EQ(0, memcmp(bl3_str + alignment, buf2, alignment));
744 }
745
746 TEST_F(LibRadosIoECPP, TruncTestPP) {
747 char buf[128];
748 memset(buf, 0xaa, sizeof(buf));
749 bufferlist bl;
750 bl.append(buf, sizeof(buf));
751 ASSERT_EQ(0, ioctx.append("foo", bl, sizeof(buf)));
752 ASSERT_EQ(-EOPNOTSUPP, ioctx.trunc("foo", sizeof(buf) / 2));
753 bufferlist bl2;
754 // Same size
755 ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl2, sizeof(buf), 0));
756 // No change
757 ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)));
758 }
759
760 TEST_F(LibRadosIoECPP, RemoveTestPP) {
761 char buf[128];
762 memset(buf, 0xaa, sizeof(buf));
763 bufferlist bl1;
764 bl1.append(buf, sizeof(buf));
765 ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
766 ASSERT_EQ(0, ioctx.remove("foo"));
767 bufferlist bl2;
768 ASSERT_EQ(-ENOENT, ioctx.read("foo", bl2, sizeof(buf), 0));
769 }
770
771 TEST_F(LibRadosIoECPP, XattrsRoundTripPP) {
772 char buf[128];
773 char attr1[] = "attr1";
774 char attr1_buf[] = "foo bar baz";
775 memset(buf, 0xaa, sizeof(buf));
776 bufferlist bl1;
777 bl1.append(buf, sizeof(buf));
778 ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
779 bufferlist bl2;
780 ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl2));
781 bufferlist bl3;
782 bl3.append(attr1_buf, sizeof(attr1_buf));
783 ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl3));
784 bufferlist bl4;
785 ASSERT_EQ((int)sizeof(attr1_buf),
786 ioctx.getxattr("foo", attr1, bl4));
787 ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
788 }
789
790 TEST_F(LibRadosIoECPP, RmXattrPP) {
791 char buf[128];
792 char attr1[] = "attr1";
793 char attr1_buf[] = "foo bar baz";
794 memset(buf, 0xaa, sizeof(buf));
795 bufferlist bl1;
796 bl1.append(buf, sizeof(buf));
797 ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
798 bufferlist bl2;
799 bl2.append(attr1_buf, sizeof(attr1_buf));
800 ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
801 ASSERT_EQ(0, ioctx.rmxattr("foo", attr1));
802 bufferlist bl3;
803 ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl3));
804
805 // Test rmxattr on a removed object
806 char buf2[128];
807 char attr2[] = "attr2";
808 char attr2_buf[] = "foo bar baz";
809 memset(buf2, 0xbb, sizeof(buf2));
810 bufferlist bl21;
811 bl21.append(buf, sizeof(buf));
812 ASSERT_EQ(0, ioctx.write("foo_rmxattr", bl21, sizeof(buf2), 0));
813 bufferlist bl22;
814 bl22.append(attr2_buf, sizeof(attr2_buf));
815 ASSERT_EQ(0, ioctx.setxattr("foo_rmxattr", attr2, bl22));
816 ASSERT_EQ(0, ioctx.remove("foo_rmxattr"));
817 ASSERT_EQ(-ENOENT, ioctx.rmxattr("foo_rmxattr", attr2));
818 }
819
820 TEST_F(LibRadosIoECPP, XattrListPP) {
821 char buf[128];
822 char attr1[] = "attr1";
823 char attr1_buf[] = "foo bar baz";
824 char attr2[] = "attr2";
825 char attr2_buf[256];
826 for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
827 attr2_buf[j] = j % 0xff;
828 }
829 memset(buf, 0xaa, sizeof(buf));
830 bufferlist bl1;
831 bl1.append(buf, sizeof(buf));
832 ASSERT_EQ(0, ioctx.append("foo", bl1, sizeof(buf)));
833 bufferlist bl2;
834 bl2.append(attr1_buf, sizeof(attr1_buf));
835 ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
836 bufferlist bl3;
837 bl3.append(attr2_buf, sizeof(attr2_buf));
838 ASSERT_EQ(0, ioctx.setxattr("foo", attr2, bl3));
839 std::map<std::string, bufferlist> attrset;
840 ASSERT_EQ(0, ioctx.getxattrs("foo", attrset));
841 for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
842 i != attrset.end(); ++i) {
843 if (i->first == string(attr1)) {
844 ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
845 }
846 else if (i->first == string(attr2)) {
847 ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
848 }
849 else {
850 ASSERT_EQ(0, 1);
851 }
852 }
853 }
854
855 TEST_F(LibRadosIoPP, CmpExtPP) {
856 bufferlist bl;
857 bl.append("ceph");
858 ObjectWriteOperation write1;
859 write1.write(0, bl);
860 ASSERT_EQ(0, ioctx.operate("foo", &write1));
861
862 bufferlist new_bl;
863 new_bl.append("CEPH");
864 ObjectWriteOperation write2;
865 write2.cmpext(0, bl, nullptr);
866 write2.write(0, new_bl);
867 ASSERT_EQ(0, ioctx.operate("foo", &write2));
868
869 ObjectReadOperation read;
870 read.read(0, bl.length(), NULL, NULL);
871 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
872 ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
873 }
874
875 TEST_F(LibRadosIoPP, CmpExtDNEPP) {
876 bufferlist bl;
877 bl.append(std::string(4, '\0'));
878
879 bufferlist new_bl;
880 new_bl.append("CEPH");
881 ObjectWriteOperation write;
882 write.cmpext(0, bl, nullptr);
883 write.write(0, new_bl);
884 ASSERT_EQ(0, ioctx.operate("foo", &write));
885
886 ObjectReadOperation read;
887 read.read(0, bl.length(), NULL, NULL);
888 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
889 ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
890 }
891
892 TEST_F(LibRadosIoPP, CmpExtMismatchPP) {
893 bufferlist bl;
894 bl.append("ceph");
895 ObjectWriteOperation write1;
896 write1.write(0, bl);
897 ASSERT_EQ(0, ioctx.operate("foo", &write1));
898
899 bufferlist new_bl;
900 new_bl.append("CEPH");
901 ObjectWriteOperation write2;
902 write2.cmpext(0, new_bl, nullptr);
903 write2.write(0, new_bl);
904 ASSERT_EQ(-MAX_ERRNO, ioctx.operate("foo", &write2));
905
906 ObjectReadOperation read;
907 read.read(0, bl.length(), NULL, NULL);
908 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
909 ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
910 }
911
912 TEST_F(LibRadosIoECPP, CmpExtPP) {
913 bufferlist bl;
914 bl.append("ceph");
915 ObjectWriteOperation write1;
916 write1.write(0, bl);
917 ASSERT_EQ(0, ioctx.operate("foo", &write1));
918
919 bufferlist new_bl;
920 new_bl.append("CEPH");
921 ObjectWriteOperation write2;
922 write2.cmpext(0, bl, nullptr);
923 write2.write_full(new_bl);
924 ASSERT_EQ(0, ioctx.operate("foo", &write2));
925
926 ObjectReadOperation read;
927 read.read(0, bl.length(), NULL, NULL);
928 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
929 ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
930 }
931
932 TEST_F(LibRadosIoECPP, CmpExtDNEPP) {
933 bufferlist bl;
934 bl.append(std::string(4, '\0'));
935
936 bufferlist new_bl;
937 new_bl.append("CEPH");
938 ObjectWriteOperation write;
939 write.cmpext(0, bl, nullptr);
940 write.write_full(new_bl);
941 ASSERT_EQ(0, ioctx.operate("foo", &write));
942
943 ObjectReadOperation read;
944 read.read(0, bl.length(), NULL, NULL);
945 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
946 ASSERT_EQ(0, memcmp(bl.c_str(), "CEPH", 4));
947 }
948
949 TEST_F(LibRadosIoECPP, CmpExtMismatchPP) {
950 bufferlist bl;
951 bl.append("ceph");
952 ObjectWriteOperation write1;
953 write1.write(0, bl);
954 ASSERT_EQ(0, ioctx.operate("foo", &write1));
955
956 bufferlist new_bl;
957 new_bl.append("CEPH");
958 ObjectWriteOperation write2;
959 write2.cmpext(0, new_bl, nullptr);
960 write2.write_full(new_bl);
961 ASSERT_EQ(-MAX_ERRNO, ioctx.operate("foo", &write2));
962
963 ObjectReadOperation read;
964 read.read(0, bl.length(), NULL, NULL);
965 ASSERT_EQ(0, ioctx.operate("foo", &read, &bl));
966 ASSERT_EQ(0, memcmp(bl.c_str(), "ceph", 4));
967 }