]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/bufferlist.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / test / bufferlist.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) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
7 *
8 * Author: Loic Dachary <loic@dachary.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Library Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library Public License for more details.
19 *
20 */
21
22 #include <limits.h>
23 #include <errno.h>
24 #include <sys/uio.h>
25
26 #include "include/buffer.h"
27 #include "include/buffer_raw.h"
28 #include "include/utime.h"
29 #include "include/coredumpctl.h"
30 #include "include/encoding.h"
31 #include "common/environment.h"
32 #include "common/Clock.h"
33 #include "common/safe_io.h"
34
35 #include "gtest/gtest.h"
36 #include "stdlib.h"
37 #include "fcntl.h"
38 #include "sys/stat.h"
39 #include "include/crc32c.h"
40 #include "common/sctp_crc32.h"
41
42 #define MAX_TEST 1000000
43 #define FILENAME "bufferlist"
44
45 static char cmd[128];
46
47 struct instrumented_bptr : public ceph::buffer::ptr {
48 const ceph::buffer::raw* get_raw() const {
49 return _raw;
50 }
51 };
52
53 TEST(Buffer, constructors) {
54 unsigned len = 17;
55 //
56 // buffer::create
57 //
58 {
59 bufferptr ptr(buffer::create(len));
60 EXPECT_EQ(len, ptr.length());
61 }
62 //
63 // buffer::claim_char
64 //
65 {
66 char* str = new char[len];
67 ::memset(str, 'X', len);
68 bufferptr ptr(buffer::claim_char(len, str));
69 EXPECT_EQ(len, ptr.length());
70 EXPECT_EQ(str, ptr.c_str());
71 bufferptr clone = ptr.clone();
72 EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
73 delete [] str;
74 }
75 //
76 // buffer::create_static
77 //
78 {
79 char* str = new char[len];
80 bufferptr ptr(buffer::create_static(len, str));
81 EXPECT_EQ(len, ptr.length());
82 EXPECT_EQ(str, ptr.c_str());
83 delete [] str;
84 }
85 //
86 // buffer::create_malloc
87 //
88 {
89 bufferptr ptr(buffer::create_malloc(len));
90 EXPECT_EQ(len, ptr.length());
91 // this doesn't throw on my x86_64 wheezy box --sage
92 //EXPECT_THROW(buffer::create_malloc((unsigned)ULLONG_MAX), buffer::bad_alloc);
93 }
94 //
95 // buffer::claim_malloc
96 //
97 {
98 char* str = (char*)malloc(len);
99 ::memset(str, 'X', len);
100 bufferptr ptr(buffer::claim_malloc(len, str));
101 EXPECT_EQ(len, ptr.length());
102 EXPECT_EQ(str, ptr.c_str());
103 bufferptr clone = ptr.clone();
104 EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
105 }
106 //
107 // buffer::copy
108 //
109 {
110 const std::string expected(len, 'X');
111 bufferptr ptr(buffer::copy(expected.c_str(), expected.size()));
112 EXPECT_NE(expected.c_str(), ptr.c_str());
113 EXPECT_EQ(0, ::memcmp(expected.c_str(), ptr.c_str(), len));
114 }
115 //
116 // buffer::create_page_aligned
117 //
118 {
119 bufferptr ptr(buffer::create_page_aligned(len));
120 ::memset(ptr.c_str(), 'X', len);
121 // doesn't throw on my x86_64 wheezy box --sage
122 //EXPECT_THROW(buffer::create_page_aligned((unsigned)ULLONG_MAX), buffer::bad_alloc);
123 #ifndef DARWIN
124 ASSERT_TRUE(ptr.is_page_aligned());
125 #endif // DARWIN
126 bufferptr clone = ptr.clone();
127 EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
128 }
129 }
130
131 void bench_buffer_alloc(int size, int num)
132 {
133 utime_t start = ceph_clock_now();
134 for (int i=0; i<num; ++i) {
135 bufferptr p = buffer::create(size);
136 p.zero();
137 }
138 utime_t end = ceph_clock_now();
139 cout << num << " alloc of size " << size
140 << " in " << (end - start) << std::endl;
141 }
142
143 TEST(Buffer, BenchAlloc) {
144 bench_buffer_alloc(16384, 1000000);
145 bench_buffer_alloc(4096, 1000000);
146 bench_buffer_alloc(1024, 1000000);
147 bench_buffer_alloc(256, 1000000);
148 bench_buffer_alloc(32, 1000000);
149 bench_buffer_alloc(4, 1000000);
150 }
151
152 TEST(BufferRaw, ostream) {
153 bufferptr ptr(1);
154 std::ostringstream stream;
155 stream << *static_cast<instrumented_bptr&>(ptr).get_raw();
156 EXPECT_GT(stream.str().size(), stream.str().find("buffer::raw("));
157 EXPECT_GT(stream.str().size(), stream.str().find("len 1 nref 1)"));
158 }
159
160 //
161 // +-----------+ +-----+
162 // | | | |
163 // | offset +----------------+ |
164 // | | | |
165 // | length +---- | |
166 // | | \------- | |
167 // +-----------+ \---+ |
168 // | ptr | +-----+
169 // +-----------+ | raw |
170 // +-----+
171 //
172 TEST(BufferPtr, constructors) {
173 unsigned len = 17;
174 //
175 // ptr::ptr()
176 //
177 {
178 buffer::ptr ptr;
179 EXPECT_FALSE(ptr.have_raw());
180 EXPECT_EQ((unsigned)0, ptr.offset());
181 EXPECT_EQ((unsigned)0, ptr.length());
182 }
183 //
184 // ptr::ptr(raw *r)
185 //
186 {
187 bufferptr ptr(buffer::create(len));
188 EXPECT_TRUE(ptr.have_raw());
189 EXPECT_EQ((unsigned)0, ptr.offset());
190 EXPECT_EQ(len, ptr.length());
191 EXPECT_EQ(ptr.raw_length(), ptr.length());
192 EXPECT_EQ(1, ptr.raw_nref());
193 }
194 //
195 // ptr::ptr(unsigned l)
196 //
197 {
198 bufferptr ptr(len);
199 EXPECT_TRUE(ptr.have_raw());
200 EXPECT_EQ((unsigned)0, ptr.offset());
201 EXPECT_EQ(len, ptr.length());
202 EXPECT_EQ(1, ptr.raw_nref());
203 }
204 //
205 // ptr(const char *d, unsigned l)
206 //
207 {
208 const std::string str(len, 'X');
209 bufferptr ptr(str.c_str(), len);
210 EXPECT_TRUE(ptr.have_raw());
211 EXPECT_EQ((unsigned)0, ptr.offset());
212 EXPECT_EQ(len, ptr.length());
213 EXPECT_EQ(1, ptr.raw_nref());
214 EXPECT_EQ(0, ::memcmp(str.c_str(), ptr.c_str(), len));
215 }
216 //
217 // ptr(const ptr& p)
218 //
219 {
220 const std::string str(len, 'X');
221 bufferptr original(str.c_str(), len);
222 bufferptr ptr(original);
223 EXPECT_TRUE(ptr.have_raw());
224 EXPECT_EQ(static_cast<instrumented_bptr&>(original).get_raw(),
225 static_cast<instrumented_bptr&>(ptr).get_raw());
226 EXPECT_EQ(2, ptr.raw_nref());
227 EXPECT_EQ(0, ::memcmp(original.c_str(), ptr.c_str(), len));
228 }
229 //
230 // ptr(const ptr& p, unsigned o, unsigned l)
231 //
232 {
233 const std::string str(len, 'X');
234 bufferptr original(str.c_str(), len);
235 bufferptr ptr(original, 0, 0);
236 EXPECT_TRUE(ptr.have_raw());
237 EXPECT_EQ(static_cast<instrumented_bptr&>(original).get_raw(),
238 static_cast<instrumented_bptr&>(ptr).get_raw());
239 EXPECT_EQ(2, ptr.raw_nref());
240 EXPECT_EQ(0, ::memcmp(original.c_str(), ptr.c_str(), len));
241 PrCtl unset_dumpable;
242 EXPECT_DEATH(bufferptr(original, 0, original.length() + 1), "");
243 EXPECT_DEATH(bufferptr(bufferptr(), 0, 0), "");
244 }
245 //
246 // ptr(ptr&& p)
247 //
248 {
249 const std::string str(len, 'X');
250 bufferptr original(str.c_str(), len);
251 bufferptr ptr(std::move(original));
252 EXPECT_TRUE(ptr.have_raw());
253 EXPECT_FALSE(original.have_raw());
254 EXPECT_EQ(0, ::memcmp(str.c_str(), ptr.c_str(), len));
255 EXPECT_EQ(1, ptr.raw_nref());
256 }
257 }
258
259 TEST(BufferPtr, operator_assign) {
260 //
261 // ptr& operator= (const ptr& p)
262 //
263 bufferptr ptr(10);
264 ptr.copy_in(0, 3, "ABC");
265 char dest[1];
266 {
267 bufferptr copy = ptr;
268 copy.copy_out(1, 1, dest);
269 ASSERT_EQ('B', dest[0]);
270 }
271
272 //
273 // ptr& operator= (ptr&& p)
274 //
275 bufferptr move = std::move(ptr);
276 {
277 move.copy_out(1, 1, dest);
278 ASSERT_EQ('B', dest[0]);
279 }
280 EXPECT_FALSE(ptr.have_raw());
281 }
282
283 TEST(BufferPtr, assignment) {
284 unsigned len = 17;
285 //
286 // override a bufferptr set with the same raw
287 //
288 {
289 bufferptr original(len);
290 bufferptr same_raw(original);
291 unsigned offset = 5;
292 unsigned length = len - offset;
293 original.set_offset(offset);
294 original.set_length(length);
295 same_raw = original;
296 ASSERT_EQ(2, original.raw_nref());
297 ASSERT_EQ(static_cast<instrumented_bptr&>(same_raw).get_raw(),
298 static_cast<instrumented_bptr&>(original).get_raw());
299 ASSERT_EQ(same_raw.offset(), original.offset());
300 ASSERT_EQ(same_raw.length(), original.length());
301 }
302
303 //
304 // self assignment is a noop
305 //
306 {
307 bufferptr original(len);
308 #pragma clang diagnostic push
309 #pragma clang diagnostic ignored "-Wself-assign-overloaded"
310 original = original;
311 #pragma clang diagnostic pop
312 ASSERT_EQ(1, original.raw_nref());
313 ASSERT_EQ((unsigned)0, original.offset());
314 ASSERT_EQ(len, original.length());
315 }
316
317 //
318 // a copy points to the same raw
319 //
320 {
321 bufferptr original(len);
322 unsigned offset = 5;
323 unsigned length = len - offset;
324 original.set_offset(offset);
325 original.set_length(length);
326 bufferptr ptr;
327 ptr = original;
328 ASSERT_EQ(2, original.raw_nref());
329 ASSERT_EQ(static_cast<instrumented_bptr&>(ptr).get_raw(),
330 static_cast<instrumented_bptr&>(original).get_raw());
331 ASSERT_EQ(original.offset(), ptr.offset());
332 ASSERT_EQ(original.length(), ptr.length());
333 }
334 }
335
336 TEST(BufferPtr, clone) {
337 unsigned len = 17;
338 bufferptr ptr(len);
339 ::memset(ptr.c_str(), 'X', len);
340 bufferptr clone = ptr.clone();
341 EXPECT_EQ(0, ::memcmp(clone.c_str(), ptr.c_str(), len));
342 }
343
344 TEST(BufferPtr, swap) {
345 unsigned len = 17;
346
347 bufferptr ptr1(len);
348 ::memset(ptr1.c_str(), 'X', len);
349 unsigned ptr1_offset = 4;
350 ptr1.set_offset(ptr1_offset);
351 unsigned ptr1_length = 3;
352 ptr1.set_length(ptr1_length);
353
354 bufferptr ptr2(len);
355 ::memset(ptr2.c_str(), 'Y', len);
356 unsigned ptr2_offset = 5;
357 ptr2.set_offset(ptr2_offset);
358 unsigned ptr2_length = 7;
359 ptr2.set_length(ptr2_length);
360
361 ptr1.swap(ptr2);
362
363 EXPECT_EQ(ptr2_length, ptr1.length());
364 EXPECT_EQ(ptr2_offset, ptr1.offset());
365 EXPECT_EQ('Y', ptr1[0]);
366
367 EXPECT_EQ(ptr1_length, ptr2.length());
368 EXPECT_EQ(ptr1_offset, ptr2.offset());
369 EXPECT_EQ('X', ptr2[0]);
370 }
371
372 TEST(BufferPtr, release) {
373 unsigned len = 17;
374
375 bufferptr ptr1(len);
376 {
377 bufferptr ptr2(ptr1);
378 EXPECT_EQ(2, ptr1.raw_nref());
379 }
380 EXPECT_EQ(1, ptr1.raw_nref());
381 }
382
383 TEST(BufferPtr, have_raw) {
384 {
385 bufferptr ptr;
386 EXPECT_FALSE(ptr.have_raw());
387 }
388 {
389 bufferptr ptr(1);
390 EXPECT_TRUE(ptr.have_raw());
391 }
392 }
393
394 TEST(BufferPtr, is_n_page_sized) {
395 {
396 bufferptr ptr(CEPH_PAGE_SIZE);
397 EXPECT_TRUE(ptr.is_n_page_sized());
398 }
399 {
400 bufferptr ptr(1);
401 EXPECT_FALSE(ptr.is_n_page_sized());
402 }
403 }
404
405 TEST(BufferPtr, is_partial) {
406 bufferptr a;
407 EXPECT_FALSE(a.is_partial());
408 bufferptr b(10);
409 EXPECT_FALSE(b.is_partial());
410 bufferptr c(b, 1, 9);
411 EXPECT_TRUE(c.is_partial());
412 bufferptr d(b, 0, 9);
413 EXPECT_TRUE(d.is_partial());
414 }
415
416 TEST(BufferPtr, accessors) {
417 unsigned len = 17;
418 bufferptr ptr(len);
419 ptr.c_str()[0] = 'X';
420 ptr[1] = 'Y';
421 const bufferptr const_ptr(ptr);
422
423 EXPECT_NE((void*)nullptr, (void*)static_cast<instrumented_bptr&>(ptr).get_raw());
424 EXPECT_EQ('X', ptr.c_str()[0]);
425 {
426 bufferptr ptr;
427 PrCtl unset_dumpable;
428 EXPECT_DEATH(ptr.c_str(), "");
429 EXPECT_DEATH(ptr[0], "");
430 }
431 EXPECT_EQ('X', const_ptr.c_str()[0]);
432 {
433 const bufferptr const_ptr;
434 PrCtl unset_dumpable;
435 EXPECT_DEATH(const_ptr.c_str(), "");
436 EXPECT_DEATH(const_ptr[0], "");
437 }
438 EXPECT_EQ(len, const_ptr.length());
439 EXPECT_EQ((unsigned)0, const_ptr.offset());
440 EXPECT_EQ((unsigned)0, const_ptr.start());
441 EXPECT_EQ(len, const_ptr.end());
442 EXPECT_EQ(len, const_ptr.end());
443 {
444 bufferptr ptr(len);
445 unsigned unused = 1;
446 ptr.set_length(ptr.length() - unused);
447 EXPECT_EQ(unused, ptr.unused_tail_length());
448 }
449 {
450 bufferptr ptr;
451 EXPECT_EQ((unsigned)0, ptr.unused_tail_length());
452 }
453 {
454 PrCtl unset_dumpable;
455 EXPECT_DEATH(ptr[len], "");
456 EXPECT_DEATH(const_ptr[len], "");
457 }
458 {
459 const bufferptr const_ptr;
460 PrCtl unset_dumpable;
461 EXPECT_DEATH(const_ptr.raw_c_str(), "");
462 EXPECT_DEATH(const_ptr.raw_length(), "");
463 EXPECT_DEATH(const_ptr.raw_nref(), "");
464 }
465 EXPECT_NE((const char *)NULL, const_ptr.raw_c_str());
466 EXPECT_EQ(len, const_ptr.raw_length());
467 EXPECT_EQ(2, const_ptr.raw_nref());
468 {
469 bufferptr ptr(len);
470 unsigned wasted = 1;
471 ptr.set_length(ptr.length() - wasted * 2);
472 ptr.set_offset(wasted);
473 EXPECT_EQ(wasted * 2, ptr.wasted());
474 }
475 }
476
477 TEST(BufferPtr, cmp) {
478 bufferptr empty;
479 bufferptr a("A", 1);
480 bufferptr ab("AB", 2);
481 bufferptr af("AF", 2);
482 bufferptr acc("ACC", 3);
483 EXPECT_GE(-1, empty.cmp(a));
484 EXPECT_LE(1, a.cmp(empty));
485 EXPECT_GE(-1, a.cmp(ab));
486 EXPECT_LE(1, ab.cmp(a));
487 EXPECT_EQ(0, ab.cmp(ab));
488 EXPECT_GE(-1, ab.cmp(af));
489 EXPECT_LE(1, af.cmp(ab));
490 EXPECT_GE(-1, acc.cmp(af));
491 EXPECT_LE(1, af.cmp(acc));
492 }
493
494 TEST(BufferPtr, is_zero) {
495 char str[2] = { '\0', 'X' };
496 {
497 const bufferptr ptr(buffer::create_static(2, str));
498 EXPECT_FALSE(ptr.is_zero());
499 }
500 {
501 const bufferptr ptr(buffer::create_static(1, str));
502 EXPECT_TRUE(ptr.is_zero());
503 }
504 }
505
506 TEST(BufferPtr, copy_out) {
507 {
508 const bufferptr ptr;
509 PrCtl unset_dumpable;
510 EXPECT_DEATH(ptr.copy_out((unsigned)0, (unsigned)0, NULL), "");
511 }
512 {
513 char in[] = "ABC";
514 const bufferptr ptr(buffer::create_static(strlen(in), in));
515 EXPECT_THROW(ptr.copy_out((unsigned)0, strlen(in) + 1, NULL), buffer::end_of_buffer);
516 EXPECT_THROW(ptr.copy_out(strlen(in) + 1, (unsigned)0, NULL), buffer::end_of_buffer);
517 char out[1] = { 'X' };
518 ptr.copy_out((unsigned)1, (unsigned)1, out);
519 EXPECT_EQ('B', out[0]);
520 }
521 }
522
523 TEST(BufferPtr, copy_out_bench) {
524 for (int s=1; s<=8; s*=2) {
525 utime_t start = ceph_clock_now();
526 int buflen = 1048576;
527 int count = 1000;
528 uint64_t v;
529 for (int i=0; i<count; ++i) {
530 bufferptr bp(buflen);
531 for (int64_t j=0; j<buflen; j += s) {
532 bp.copy_out(j, s, (char *)&v);
533 }
534 }
535 utime_t end = ceph_clock_now();
536 cout << count << " fills of buffer len " << buflen
537 << " with " << s << " byte copy_out in"
538 << (end - start) << std::endl;
539 }
540 }
541
542 TEST(BufferPtr, copy_in) {
543 {
544 bufferptr ptr;
545 PrCtl unset_dumpable;
546 EXPECT_DEATH(ptr.copy_in((unsigned)0, (unsigned)0, NULL), "");
547 }
548 {
549 char in[] = "ABCD";
550 bufferptr ptr(2);
551 {
552 PrCtl unset_dumpable;
553 EXPECT_DEATH(ptr.copy_in((unsigned)0, strlen(in) + 1, NULL), "");
554 EXPECT_DEATH(ptr.copy_in(strlen(in) + 1, (unsigned)0, NULL), "");
555 }
556 ptr.copy_in((unsigned)0, (unsigned)2, in);
557 EXPECT_EQ(in[0], ptr[0]);
558 EXPECT_EQ(in[1], ptr[1]);
559 }
560 }
561
562 TEST(BufferPtr, copy_in_bench) {
563 for (int s=1; s<=8; s*=2) {
564 utime_t start = ceph_clock_now();
565 int buflen = 1048576;
566 int count = 1000;
567 for (int i=0; i<count; ++i) {
568 bufferptr bp(buflen);
569 for (int64_t j=0; j<buflen; j += s) {
570 bp.copy_in(j, s, (char *)&j, false);
571 }
572 }
573 utime_t end = ceph_clock_now();
574 cout << count << " fills of buffer len " << buflen
575 << " with " << s << " byte copy_in in "
576 << (end - start) << std::endl;
577 }
578 }
579
580 TEST(BufferPtr, append) {
581 {
582 bufferptr ptr;
583 PrCtl unset_dumpable;
584 EXPECT_DEATH(ptr.append('A'), "");
585 EXPECT_DEATH(ptr.append("B", (unsigned)1), "");
586 }
587 {
588 bufferptr ptr(2);
589 {
590 PrCtl unset_dumpable;
591 EXPECT_DEATH(ptr.append('A'), "");
592 EXPECT_DEATH(ptr.append("B", (unsigned)1), "");
593 }
594 ptr.set_length(0);
595 ptr.append('A');
596 EXPECT_EQ((unsigned)1, ptr.length());
597 EXPECT_EQ('A', ptr[0]);
598 ptr.append("B", (unsigned)1);
599 EXPECT_EQ((unsigned)2, ptr.length());
600 EXPECT_EQ('B', ptr[1]);
601 }
602 }
603
604 TEST(BufferPtr, append_bench) {
605 char src[1048576];
606 memset(src, 0, sizeof(src));
607 for (int s=4; s<=16384; s*=4) {
608 utime_t start = ceph_clock_now();
609 int buflen = 1048576;
610 int count = 4000;
611 for (int i=0; i<count; ++i) {
612 bufferptr bp(buflen);
613 bp.set_length(0);
614 for (int64_t j=0; j<buflen; j += s) {
615 bp.append(src + j, s);
616 }
617 }
618 utime_t end = ceph_clock_now();
619 cout << count << " fills of buffer len " << buflen
620 << " with " << s << " byte appends in "
621 << (end - start) << std::endl;
622 }
623 }
624
625 TEST(BufferPtr, zero) {
626 char str[] = "XXXX";
627 bufferptr ptr(buffer::create_static(strlen(str), str));
628 {
629 PrCtl unset_dumpable;
630 EXPECT_DEATH(ptr.zero(ptr.length() + 1, 0), "");
631 }
632 ptr.zero(1, 1);
633 EXPECT_EQ('X', ptr[0]);
634 EXPECT_EQ('\0', ptr[1]);
635 EXPECT_EQ('X', ptr[2]);
636 ptr.zero();
637 EXPECT_EQ('\0', ptr[0]);
638 }
639
640 TEST(BufferPtr, ostream) {
641 {
642 bufferptr ptr;
643 std::ostringstream stream;
644 stream << ptr;
645 EXPECT_GT(stream.str().size(), stream.str().find("buffer:ptr(0~0 no raw"));
646 }
647 {
648 char str[] = "XXXX";
649 bufferptr ptr(buffer::create_static(strlen(str), str));
650 std::ostringstream stream;
651 stream << ptr;
652 EXPECT_GT(stream.str().size(), stream.str().find("len 4 nref 1)"));
653 }
654 }
655
656 //
657 // +---------+
658 // | +-----+ |
659 // list ptr | | | |
660 // +----------+ +-----+ | | | |
661 // | append_ >-------> >--------------------> | |
662 // | buffer | +-----+ | | | |
663 // +----------+ ptr | | | |
664 // | _len | list +-----+ | | | |
665 // +----------+ +------+ ,--->+ >-----> | |
666 // | _buffers >----> >----- +-----+ | +-----+ |
667 // +----------+ +----^-+ \ ptr | raw |
668 // | last_p | / `-->+-----+ | +-----+ |
669 // +--------+-+ / + >-----> | |
670 // | ,- ,--->+-----+ | | | |
671 // | / ,--- | | | |
672 // | / ,--- | | | |
673 // +-v--+-^--+--^+-------+ | | | |
674 // | bl | ls | p | p_off >--------------->| | |
675 // +----+----+-----+-----+ | +-----+ |
676 // | | off >------------->| raw |
677 // +---------------+-----+ | |
678 // iterator +---------+
679 //
680 TEST(BufferListIterator, constructors) {
681 //
682 // iterator()
683 //
684 {
685 buffer::list::iterator i;
686 EXPECT_EQ((unsigned)0, i.get_off());
687 }
688
689 //
690 // iterator(list *l, unsigned o=0)
691 //
692 {
693 bufferlist bl;
694 bl.append("ABC", 3);
695
696 {
697 bufferlist::iterator i(&bl);
698 EXPECT_EQ((unsigned)0, i.get_off());
699 EXPECT_EQ('A', *i);
700 }
701 {
702 bufferlist::iterator i(&bl, 1);
703 EXPECT_EQ('B', *i);
704 EXPECT_EQ((unsigned)2, i.get_remaining());
705 }
706 }
707
708 //
709 // iterator(list *l, unsigned o, std::list<ptr>::iterator ip, unsigned po)
710 // not tested because of http://tracker.ceph.com/issues/4101
711
712 //
713 // iterator(const iterator& other)
714 //
715 {
716 bufferlist bl;
717 bl.append("ABC", 3);
718 bufferlist::iterator i(&bl, 1);
719 bufferlist::iterator j(i);
720 EXPECT_EQ(*i, *j);
721 ++j;
722 EXPECT_NE(*i, *j);
723 EXPECT_EQ('B', *i);
724 EXPECT_EQ('C', *j);
725 bl.c_str()[1] = 'X';
726 }
727
728 //
729 // const_iterator(const iterator& other)
730 //
731 {
732 bufferlist bl;
733 bl.append("ABC", 3);
734 bufferlist::iterator i(&bl);
735 bufferlist::const_iterator ci(i);
736 EXPECT_EQ(0u, ci.get_off());
737 EXPECT_EQ('A', *ci);
738 }
739 }
740
741 TEST(BufferListIterator, empty_create_append_copy) {
742 bufferlist bl, bl2, bl3, out;
743 bl2.append("bar");
744 bl.swap(bl2);
745 bl2.append("xxx");
746 bl.append(bl2);
747 bl.rebuild();
748 bl.begin().copy(6, out);
749 ASSERT_TRUE(out.contents_equal(bl));
750 }
751
752 TEST(BufferListIterator, operator_assign) {
753 bufferlist bl;
754 bl.append("ABC", 3);
755 bufferlist::iterator i(&bl, 1);
756
757 #pragma clang diagnostic push
758 #pragma clang diagnostic ignored "-Wself-assign-overloaded"
759 i = i;
760 #pragma clang diagnostic pop
761 EXPECT_EQ('B', *i);
762 bufferlist::iterator j;
763 j = i;
764 EXPECT_EQ('B', *j);
765 }
766
767 TEST(BufferListIterator, get_off) {
768 bufferlist bl;
769 bl.append("ABC", 3);
770 bufferlist::iterator i(&bl, 1);
771 EXPECT_EQ((unsigned)1, i.get_off());
772 }
773
774 TEST(BufferListIterator, get_remaining) {
775 bufferlist bl;
776 bl.append("ABC", 3);
777 bufferlist::iterator i(&bl, 1);
778 EXPECT_EQ((unsigned)2, i.get_remaining());
779 }
780
781 TEST(BufferListIterator, end) {
782 bufferlist bl;
783 {
784 bufferlist::iterator i(&bl);
785 EXPECT_TRUE(i.end());
786 }
787 bl.append("ABC", 3);
788 {
789 bufferlist::iterator i(&bl);
790 EXPECT_FALSE(i.end());
791 }
792 }
793
794 static void bench_bufferlistiter_deref(const size_t step,
795 const size_t bufsize,
796 const size_t bufnum) {
797 const std::string buf('a', bufsize);
798 ceph::bufferlist bl;
799
800 for (size_t i = 0; i < bufnum; i++) {
801 bl.append(ceph::bufferptr(buf.c_str(), buf.size()));
802 }
803
804 utime_t start = ceph_clock_now();
805 bufferlist::iterator iter = bl.begin();
806 while (iter != bl.end()) {
807 iter += step;
808 }
809 utime_t end = ceph_clock_now();
810 cout << bufsize * bufnum << " derefs over bl with " << bufnum
811 << " buffers, each " << bufsize << " bytes long"
812 << " in " << (end - start) << std::endl;
813 }
814
815 TEST(BufferListIterator, BenchDeref) {
816 bench_bufferlistiter_deref(1, 1, 4096000);
817 bench_bufferlistiter_deref(1, 10, 409600);
818 bench_bufferlistiter_deref(1, 100, 40960);
819 bench_bufferlistiter_deref(1, 1000, 4096);
820
821 bench_bufferlistiter_deref(4, 1, 1024000);
822 bench_bufferlistiter_deref(4, 10, 102400);
823 bench_bufferlistiter_deref(4, 100, 10240);
824 bench_bufferlistiter_deref(4, 1000, 1024);
825 }
826
827 TEST(BufferListIterator, advance) {
828 bufferlist bl;
829 const std::string one("ABC");
830 bl.append(bufferptr(one.c_str(), one.size()));
831 const std::string two("DEF");
832 bl.append(bufferptr(two.c_str(), two.size()));
833
834 {
835 bufferlist::iterator i(&bl);
836 EXPECT_THROW(i += 200u, buffer::end_of_buffer);
837 }
838 {
839 bufferlist::iterator i(&bl);
840 EXPECT_EQ('A', *i);
841 i += 1u;
842 EXPECT_EQ('B', *i);
843 i += 3u;
844 EXPECT_EQ('E', *i);
845 }
846 }
847
848 TEST(BufferListIterator, iterate_with_empties) {
849 ceph::bufferlist bl;
850 EXPECT_EQ(bl.get_num_buffers(), 0u);
851
852 bl.push_back(ceph::buffer::create(0));
853 EXPECT_EQ(bl.length(), 0u);
854 EXPECT_EQ(bl.get_num_buffers(), 1u);
855
856 encode(int64_t(42), bl);
857 EXPECT_EQ(bl.get_num_buffers(), 2u);
858
859 bl.push_back(ceph::buffer::create(0));
860 EXPECT_EQ(bl.get_num_buffers(), 3u);
861
862 // append bufferlist with single, 0-sized ptr inside
863 {
864 ceph::bufferlist bl_with_empty_ptr;
865 bl_with_empty_ptr.push_back(ceph::buffer::create(0));
866 EXPECT_EQ(bl_with_empty_ptr.length(), 0u);
867 EXPECT_EQ(bl_with_empty_ptr.get_num_buffers(), 1u);
868
869 bl.append(bl_with_empty_ptr);
870 }
871
872 encode(int64_t(24), bl);
873 EXPECT_EQ(bl.get_num_buffers(), 5u);
874
875 auto i = bl.cbegin();
876 int64_t val;
877 decode(val, i);
878 EXPECT_EQ(val, 42l);
879
880 decode(val, i);
881 EXPECT_EQ(val, 24l);
882
883 val = 0;
884 i.seek(sizeof(val));
885 decode(val, i);
886 EXPECT_EQ(val, 24l);
887 EXPECT_TRUE(i == bl.end());
888
889 i.seek(0);
890 decode(val, i);
891 EXPECT_EQ(val, 42);
892 EXPECT_FALSE(i == bl.end());
893 }
894
895 TEST(BufferListIterator, get_ptr_and_advance)
896 {
897 bufferptr a("one", 3);
898 bufferptr b("two", 3);
899 bufferptr c("three", 5);
900 bufferlist bl;
901 bl.append(a);
902 bl.append(b);
903 bl.append(c);
904 const char *ptr;
905 bufferlist::iterator p = bl.begin();
906 ASSERT_EQ(3u, p.get_ptr_and_advance(11u, &ptr));
907 ASSERT_EQ(bl.length() - 3u, p.get_remaining());
908 ASSERT_EQ(0, memcmp(ptr, "one", 3));
909 ASSERT_EQ(2u, p.get_ptr_and_advance(2u, &ptr));
910 ASSERT_EQ(0, memcmp(ptr, "tw", 2));
911 ASSERT_EQ(1u, p.get_ptr_and_advance(4u, &ptr));
912 ASSERT_EQ(0, memcmp(ptr, "o", 1));
913 ASSERT_EQ(5u, p.get_ptr_and_advance(5u, &ptr));
914 ASSERT_EQ(0, memcmp(ptr, "three", 5));
915 ASSERT_EQ(0u, p.get_remaining());
916 }
917
918 TEST(BufferListIterator, iterator_crc32c) {
919 bufferlist bl1;
920 bufferlist bl2;
921 bufferlist bl3;
922
923 string s1(100, 'a');
924 string s2(50, 'b');
925 string s3(7, 'c');
926 string s;
927 bl1.append(s1);
928 bl1.append(s2);
929 bl1.append(s3);
930 s = s1 + s2 + s3;
931 bl2.append(s);
932
933 bufferlist::iterator it = bl2.begin();
934 ASSERT_EQ(bl1.crc32c(0), it.crc32c(it.get_remaining(), 0));
935 ASSERT_EQ(0u, it.get_remaining());
936
937 it = bl1.begin();
938 ASSERT_EQ(bl2.crc32c(0), it.crc32c(it.get_remaining(), 0));
939
940 bl3.append(s.substr(98, 55));
941 it = bl1.begin();
942 it += 98u;
943 ASSERT_EQ(bl3.crc32c(0), it.crc32c(55, 0));
944 ASSERT_EQ(4u, it.get_remaining());
945
946 bl3.clear();
947 bl3.append(s.substr(98 + 55));
948 it = bl1.begin();
949 it += 98u + 55u;
950 ASSERT_EQ(bl3.crc32c(0), it.crc32c(10, 0));
951 ASSERT_EQ(0u, it.get_remaining());
952 }
953
954 TEST(BufferListIterator, seek) {
955 bufferlist bl;
956 bl.append("ABC", 3);
957 bufferlist::iterator i(&bl, 1);
958 EXPECT_EQ('B', *i);
959 i.seek(2);
960 EXPECT_EQ('C', *i);
961 }
962
963 TEST(BufferListIterator, operator_star) {
964 bufferlist bl;
965 {
966 bufferlist::iterator i(&bl);
967 EXPECT_THROW(*i, buffer::end_of_buffer);
968 }
969 bl.append("ABC", 3);
970 {
971 bufferlist::iterator i(&bl);
972 EXPECT_EQ('A', *i);
973 EXPECT_THROW(i += 200u, buffer::end_of_buffer);
974 EXPECT_THROW(*i, buffer::end_of_buffer);
975 }
976 }
977
978 TEST(BufferListIterator, operator_equal) {
979 bufferlist bl;
980 bl.append("ABC", 3);
981 {
982 bufferlist::iterator i(&bl);
983 bufferlist::iterator j(&bl);
984 EXPECT_EQ(i, j);
985 }
986 {
987 bufferlist::const_iterator ci = bl.begin();
988 bufferlist::iterator i = bl.begin();
989 EXPECT_EQ(i, ci);
990 EXPECT_EQ(ci, i);
991 }
992 }
993
994 TEST(BufferListIterator, operator_nequal) {
995 bufferlist bl;
996 bl.append("ABC", 3);
997 {
998 bufferlist::iterator i(&bl);
999 bufferlist::iterator j(&bl);
1000 EXPECT_NE(++i, j);
1001 }
1002 {
1003 bufferlist::const_iterator ci = bl.begin();
1004 bufferlist::const_iterator cj = bl.begin();
1005 ++ci;
1006 EXPECT_NE(ci, cj);
1007 bufferlist::iterator i = bl.begin();
1008 EXPECT_NE(i, ci);
1009 EXPECT_NE(ci, i);
1010 }
1011 {
1012 // tests begin(), end(), operator++() also
1013 string s("ABC");
1014 int i = 0;
1015 for (auto c : bl) {
1016 EXPECT_EQ(s[i++], c);
1017 }
1018 }
1019 }
1020
1021 TEST(BufferListIterator, operator_plus_plus) {
1022 bufferlist bl;
1023 {
1024 bufferlist::iterator i(&bl);
1025 EXPECT_THROW(++i, buffer::end_of_buffer);
1026 }
1027 bl.append("ABC", 3);
1028 {
1029 bufferlist::iterator i(&bl);
1030 ++i;
1031 EXPECT_EQ('B', *i);
1032 }
1033 }
1034
1035 TEST(BufferListIterator, get_current_ptr) {
1036 bufferlist bl;
1037 {
1038 bufferlist::iterator i(&bl);
1039 EXPECT_THROW(++i, buffer::end_of_buffer);
1040 }
1041 bl.append("ABC", 3);
1042 {
1043 bufferlist::iterator i(&bl, 1);
1044 const buffer::ptr ptr = i.get_current_ptr();
1045 EXPECT_EQ('B', ptr[0]);
1046 EXPECT_EQ((unsigned)1, ptr.offset());
1047 EXPECT_EQ((unsigned)2, ptr.length());
1048 }
1049 }
1050
1051 TEST(BufferListIterator, copy) {
1052 bufferlist bl;
1053 const char *expected = "ABC";
1054 bl.append(expected, 3);
1055 //
1056 // void copy(unsigned len, char *dest);
1057 //
1058 {
1059 char* copy = (char*)malloc(3);
1060 ::memset(copy, 'X', 3);
1061 bufferlist::iterator i(&bl);
1062 //
1063 // demonstrates that it seeks back to offset if p == ls->end()
1064 //
1065 EXPECT_THROW(i += 200u, buffer::end_of_buffer);
1066 i.copy(2, copy);
1067 EXPECT_EQ(0, ::memcmp(copy, expected, 2));
1068 EXPECT_EQ('X', copy[2]);
1069 i.seek(0);
1070 i.copy(3, copy);
1071 EXPECT_EQ(0, ::memcmp(copy, expected, 3));
1072 free(copy);
1073 }
1074 //
1075 // void copy(unsigned len, char *dest) via begin(size_t offset)
1076 //
1077 {
1078 bufferlist bl;
1079 EXPECT_THROW(bl.begin((unsigned)100).copy((unsigned)100, (char*)0), buffer::end_of_buffer);
1080 const char *expected = "ABC";
1081 bl.append(expected);
1082 char *dest = new char[2];
1083 bl.begin(1).copy(2, dest);
1084 EXPECT_EQ(0, ::memcmp(expected + 1, dest, 2));
1085 delete [] dest;
1086 }
1087 //
1088 // void buffer::list::iterator::copy_deep(unsigned len, ptr &dest)
1089 //
1090 {
1091 bufferptr ptr;
1092 bufferlist::iterator i(&bl);
1093 i.copy_deep(2, ptr);
1094 EXPECT_EQ((unsigned)2, ptr.length());
1095 EXPECT_EQ('A', ptr[0]);
1096 EXPECT_EQ('B', ptr[1]);
1097 }
1098 //
1099 // void buffer::list::iterator::copy_shallow(unsigned len, ptr &dest)
1100 //
1101 {
1102 bufferptr ptr;
1103 bufferlist::iterator i(&bl);
1104 i.copy_shallow(2, ptr);
1105 EXPECT_EQ((unsigned)2, ptr.length());
1106 EXPECT_EQ('A', ptr[0]);
1107 EXPECT_EQ('B', ptr[1]);
1108 }
1109 //
1110 // void buffer::list::iterator::copy(unsigned len, list &dest)
1111 //
1112 {
1113 bufferlist copy;
1114 bufferlist::iterator i(&bl);
1115 //
1116 // demonstrates that it seeks back to offset if p == ls->end()
1117 //
1118 EXPECT_THROW(i += 200u, buffer::end_of_buffer);
1119 i.copy(2, copy);
1120 EXPECT_EQ(0, ::memcmp(copy.c_str(), expected, 2));
1121 i.seek(0);
1122 i.copy(3, copy);
1123 EXPECT_EQ('A', copy[0]);
1124 EXPECT_EQ('B', copy[1]);
1125 EXPECT_EQ('A', copy[2]);
1126 EXPECT_EQ('B', copy[3]);
1127 EXPECT_EQ('C', copy[4]);
1128 EXPECT_EQ((unsigned)(2 + 3), copy.length());
1129 }
1130 //
1131 // void buffer::list::iterator::copy(unsigned len, list &dest) via begin(size_t offset)
1132 //
1133 {
1134 bufferlist bl;
1135 bufferlist dest;
1136 EXPECT_THROW(bl.begin((unsigned)100).copy((unsigned)100, dest), buffer::end_of_buffer);
1137 const char *expected = "ABC";
1138 bl.append(expected);
1139 bl.begin(1).copy(2, dest);
1140 EXPECT_EQ(0, ::memcmp(expected + 1, dest.c_str(), 2));
1141 }
1142 //
1143 // void buffer::list::iterator::copy_all(list &dest)
1144 //
1145 {
1146 bufferlist copy;
1147 bufferlist::iterator i(&bl);
1148 //
1149 // demonstrates that it seeks back to offset if p == ls->end()
1150 //
1151 EXPECT_THROW(i += 200u, buffer::end_of_buffer);
1152 i.copy_all(copy);
1153 EXPECT_EQ('A', copy[0]);
1154 EXPECT_EQ('B', copy[1]);
1155 EXPECT_EQ('C', copy[2]);
1156 EXPECT_EQ((unsigned)3, copy.length());
1157 }
1158 //
1159 // void copy(unsigned len, std::string &dest)
1160 //
1161 {
1162 std::string copy;
1163 bufferlist::iterator i(&bl);
1164 //
1165 // demonstrates that it seeks back to offset if p == ls->end()
1166 //
1167 EXPECT_THROW(i += 200u, buffer::end_of_buffer);
1168 i.copy(2, copy);
1169 EXPECT_EQ(0, ::memcmp(copy.c_str(), expected, 2));
1170 i.seek(0);
1171 i.copy(3, copy);
1172 EXPECT_EQ('A', copy[0]);
1173 EXPECT_EQ('B', copy[1]);
1174 EXPECT_EQ('A', copy[2]);
1175 EXPECT_EQ('B', copy[3]);
1176 EXPECT_EQ('C', copy[4]);
1177 EXPECT_EQ((unsigned)(2 + 3), copy.length());
1178 }
1179 //
1180 // void copy(unsigned len, std::string &dest) via begin(size_t offset)
1181 //
1182 {
1183 bufferlist bl;
1184 std::string dest;
1185 EXPECT_THROW(bl.begin((unsigned)100).copy((unsigned)100, dest), buffer::end_of_buffer);
1186 const char *expected = "ABC";
1187 bl.append(expected);
1188 bl.begin(1).copy(2, dest);
1189 EXPECT_EQ(0, ::memcmp(expected + 1, dest.c_str(), 2));
1190 }
1191 }
1192
1193 TEST(BufferListIterator, copy_in) {
1194 bufferlist bl;
1195 const char *existing = "XXX";
1196 bl.append(existing, 3);
1197 //
1198 // void buffer::list::iterator::copy_in(unsigned len, const char *src)
1199 //
1200 {
1201 bufferlist::iterator i(&bl);
1202 //
1203 // demonstrates that it seeks back to offset if p == ls->end()
1204 //
1205 EXPECT_THROW(i += 200u, buffer::end_of_buffer);
1206 const char *expected = "ABC";
1207 i.copy_in(3, expected);
1208 EXPECT_EQ(0, ::memcmp(bl.c_str(), expected, 3));
1209 EXPECT_EQ('A', bl[0]);
1210 EXPECT_EQ('B', bl[1]);
1211 EXPECT_EQ('C', bl[2]);
1212 EXPECT_EQ((unsigned)3, bl.length());
1213 }
1214 //
1215 // void copy_in(unsigned len, const char *src) via begin(size_t offset)
1216 //
1217 {
1218 bufferlist bl;
1219 bl.append("XXX");
1220 EXPECT_THROW(bl.begin((unsigned)100).copy_in((unsigned)100, (char*)0), buffer::end_of_buffer);
1221 bl.begin(1).copy_in(2, "AB");
1222 EXPECT_EQ(0, ::memcmp("XAB", bl.c_str(), 3));
1223 }
1224 //
1225 // void buffer::list::iterator::copy_in(unsigned len, const list& otherl)
1226 //
1227 {
1228 bufferlist::iterator i(&bl);
1229 //
1230 // demonstrates that it seeks back to offset if p == ls->end()
1231 //
1232 EXPECT_THROW(i += 200u, buffer::end_of_buffer);
1233 bufferlist expected;
1234 expected.append("ABC", 3);
1235 i.copy_in(3, expected);
1236 EXPECT_EQ(0, ::memcmp(bl.c_str(), expected.c_str(), 3));
1237 EXPECT_EQ('A', bl[0]);
1238 EXPECT_EQ('B', bl[1]);
1239 EXPECT_EQ('C', bl[2]);
1240 EXPECT_EQ((unsigned)3, bl.length());
1241 }
1242 //
1243 // void copy_in(unsigned len, const list& src) via begin(size_t offset)
1244 //
1245 {
1246 bufferlist bl;
1247 bl.append("XXX");
1248 bufferlist src;
1249 src.append("ABC");
1250 EXPECT_THROW(bl.begin((unsigned)100).copy_in((unsigned)100, src), buffer::end_of_buffer);
1251 bl.begin(1).copy_in(2, src);
1252 EXPECT_EQ(0, ::memcmp("XAB", bl.c_str(), 3));
1253 }
1254 }
1255
1256 // iterator& buffer::list::const_iterator::operator++()
1257 TEST(BufferListConstIterator, operator_plus_plus) {
1258 bufferlist bl;
1259 {
1260 bufferlist::const_iterator i(&bl);
1261 EXPECT_THROW(++i, buffer::end_of_buffer);
1262 }
1263 bl.append("ABC", 3);
1264 {
1265 const bufferlist const_bl(bl);
1266 bufferlist::const_iterator i(const_bl.begin());
1267 ++i;
1268 EXPECT_EQ('B', *i);
1269 }
1270
1271 }
1272
1273 TEST(BufferList, constructors) {
1274 //
1275 // list()
1276 //
1277 {
1278 bufferlist bl;
1279 ASSERT_EQ((unsigned)0, bl.length());
1280 }
1281 //
1282 // list(unsigned prealloc)
1283 //
1284 {
1285 bufferlist bl(1);
1286 ASSERT_EQ((unsigned)0, bl.length());
1287 bl.append('A');
1288 ASSERT_EQ('A', bl[0]);
1289 }
1290 //
1291 // list(const list& other)
1292 //
1293 {
1294 bufferlist bl(1);
1295 bl.append('A');
1296 ASSERT_EQ('A', bl[0]);
1297 bufferlist copy(bl);
1298 ASSERT_EQ('A', copy[0]);
1299 }
1300 //
1301 // list(list&& other)
1302 //
1303 {
1304 bufferlist bl(1);
1305 bl.append('A');
1306 bufferlist copy = std::move(bl);
1307 ASSERT_EQ(0U, bl.length());
1308 ASSERT_EQ(1U, copy.length());
1309 ASSERT_EQ('A', copy[0]);
1310 }
1311 }
1312
1313 TEST(BufferList, append_after_move) {
1314 bufferlist bl(6);
1315 bl.append("ABC", 3);
1316 EXPECT_EQ(1, bl.get_num_buffers());
1317
1318 bufferlist moved_to_bl(std::move(bl));
1319 moved_to_bl.append("123", 3);
1320 // it's expected that the list(list&&) ctor will preserve the _carriage
1321 EXPECT_EQ(1, moved_to_bl.get_num_buffers());
1322 EXPECT_EQ(0, ::memcmp("ABC123", moved_to_bl.c_str(), 6));
1323 }
1324
1325 void bench_bufferlist_alloc(int size, int num, int per)
1326 {
1327 utime_t start = ceph_clock_now();
1328 for (int i=0; i<num; ++i) {
1329 bufferlist bl;
1330 for (int j=0; j<per; ++j)
1331 bl.push_back(buffer::ptr_node::create(buffer::create(size)));
1332 }
1333 utime_t end = ceph_clock_now();
1334 cout << num << " alloc of size " << size
1335 << " in " << (end - start) << std::endl;
1336 }
1337
1338 TEST(BufferList, BenchAlloc) {
1339 bench_bufferlist_alloc(32768, 100000, 16);
1340 bench_bufferlist_alloc(25000, 100000, 16);
1341 bench_bufferlist_alloc(16384, 100000, 16);
1342 bench_bufferlist_alloc(10000, 100000, 16);
1343 bench_bufferlist_alloc(8192, 100000, 16);
1344 bench_bufferlist_alloc(6000, 100000, 16);
1345 bench_bufferlist_alloc(4096, 100000, 16);
1346 bench_bufferlist_alloc(1024, 100000, 16);
1347 bench_bufferlist_alloc(256, 100000, 16);
1348 bench_bufferlist_alloc(32, 100000, 16);
1349 bench_bufferlist_alloc(4, 100000, 16);
1350 }
1351
1352 TEST(BufferList, append_bench_with_size_hint) {
1353 std::array<char, 1048576> src = { 0, };
1354
1355 for (size_t step = 4; step <= 16384; step *= 4) {
1356 const utime_t start = ceph_clock_now();
1357
1358 constexpr size_t rounds = 4000;
1359 for (size_t r = 0; r < rounds; ++r) {
1360 ceph::bufferlist bl(std::size(src));
1361 for (auto iter = std::begin(src);
1362 iter != std::end(src);
1363 iter = std::next(iter, step)) {
1364 bl.append(&*iter, step);
1365 }
1366 }
1367 cout << rounds << " fills of buffer len " << src.size()
1368 << " with " << step << " byte appends in "
1369 << (ceph_clock_now() - start) << std::endl;
1370 }
1371 }
1372
1373 TEST(BufferList, append_bench) {
1374 std::array<char, 1048576> src = { 0, };
1375
1376 for (size_t step = 4; step <= 16384; step *= 4) {
1377 const utime_t start = ceph_clock_now();
1378
1379 constexpr size_t rounds = 4000;
1380 for (size_t r = 0; r < rounds; ++r) {
1381 ceph::bufferlist bl;
1382 for (auto iter = std::begin(src);
1383 iter != std::end(src);
1384 iter = std::next(iter, step)) {
1385 bl.append(&*iter, step);
1386 }
1387 }
1388 cout << rounds << " fills of buffer len " << src.size()
1389 << " with " << step << " byte appends in "
1390 << (ceph_clock_now() - start) << std::endl;
1391 }
1392 }
1393
1394 TEST(BufferList, operator_equal) {
1395 //
1396 // list& operator= (const list& other)
1397 //
1398 bufferlist bl;
1399 bl.append("ABC", 3);
1400 {
1401 std::string dest;
1402 bl.begin(1).copy(1, dest);
1403 ASSERT_EQ('B', dest[0]);
1404 }
1405 {
1406 bufferlist copy = bl;
1407 std::string dest;
1408 copy.begin(1).copy(1, dest);
1409 ASSERT_EQ('B', dest[0]);
1410 }
1411
1412 //
1413 // list& operator= (list&& other)
1414 //
1415 bufferlist move = std::move(bl);
1416 {
1417 std::string dest;
1418 move.begin(1).copy(1, dest);
1419 ASSERT_EQ('B', dest[0]);
1420 }
1421 EXPECT_TRUE(move.length());
1422 EXPECT_TRUE(!bl.length());
1423 }
1424
1425 TEST(BufferList, buffers) {
1426 bufferlist bl;
1427 ASSERT_EQ((unsigned)0, bl.get_num_buffers());
1428 bl.append('A');
1429 ASSERT_EQ((unsigned)1, bl.get_num_buffers());
1430 }
1431
1432 TEST(BufferList, to_str) {
1433 {
1434 bufferlist bl;
1435 bl.append("foo");
1436 ASSERT_EQ(bl.to_str(), string("foo"));
1437 }
1438 {
1439 bufferptr a("foobarbaz", 9);
1440 bufferptr b("123456789", 9);
1441 bufferptr c("ABCDEFGHI", 9);
1442 bufferlist bl;
1443 bl.append(a);
1444 bl.append(b);
1445 bl.append(c);
1446 ASSERT_EQ(bl.to_str(), string("foobarbaz123456789ABCDEFGHI"));
1447 }
1448 }
1449
1450 TEST(BufferList, swap) {
1451 bufferlist b1;
1452 b1.append('A');
1453
1454 bufferlist b2;
1455 b2.append('B');
1456
1457 b1.swap(b2);
1458
1459 std::string s1;
1460 b1.begin().copy(1, s1);
1461 ASSERT_EQ('B', s1[0]);
1462
1463 std::string s2;
1464 b2.begin().copy(1, s2);
1465 ASSERT_EQ('A', s2[0]);
1466 }
1467
1468 TEST(BufferList, length) {
1469 bufferlist bl;
1470 ASSERT_EQ((unsigned)0, bl.length());
1471 bl.append('A');
1472 ASSERT_EQ((unsigned)1, bl.length());
1473 }
1474
1475 TEST(BufferList, contents_equal) {
1476 //
1477 // A BB
1478 // AB B
1479 //
1480 bufferlist bl1;
1481 bl1.append("A");
1482 bl1.append("BB");
1483 bufferlist bl2;
1484 ASSERT_FALSE(bl1.contents_equal(bl2)); // different length
1485 bl2.append("AB");
1486 bl2.append("B");
1487 ASSERT_TRUE(bl1.contents_equal(bl2)); // same length same content
1488 //
1489 // ABC
1490 //
1491 bufferlist bl3;
1492 bl3.append("ABC");
1493 ASSERT_FALSE(bl1.contents_equal(bl3)); // same length different content
1494 }
1495
1496 TEST(BufferList, is_aligned) {
1497 const int SIMD_ALIGN = 32;
1498 {
1499 bufferlist bl;
1500 EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
1501 }
1502 {
1503 bufferlist bl;
1504 bufferptr ptr(buffer::create_aligned(2, SIMD_ALIGN));
1505 ptr.set_offset(1);
1506 ptr.set_length(1);
1507 bl.append(ptr);
1508 EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
1509 bl.rebuild_aligned(SIMD_ALIGN);
1510 EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
1511 }
1512 {
1513 bufferlist bl;
1514 bufferptr ptr(buffer::create_aligned(SIMD_ALIGN + 1, SIMD_ALIGN));
1515 ptr.set_offset(1);
1516 ptr.set_length(SIMD_ALIGN);
1517 bl.append(ptr);
1518 EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
1519 bl.rebuild_aligned(SIMD_ALIGN);
1520 EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
1521 }
1522 }
1523
1524 TEST(BufferList, is_n_align_sized) {
1525 const int SIMD_ALIGN = 32;
1526 {
1527 bufferlist bl;
1528 EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN));
1529 }
1530 {
1531 bufferlist bl;
1532 bl.append_zero(1);
1533 EXPECT_FALSE(bl.is_n_align_sized(SIMD_ALIGN));
1534 }
1535 {
1536 bufferlist bl;
1537 bl.append_zero(SIMD_ALIGN);
1538 EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN));
1539 }
1540 }
1541
1542 TEST(BufferList, is_page_aligned) {
1543 {
1544 bufferlist bl;
1545 EXPECT_TRUE(bl.is_page_aligned());
1546 }
1547 {
1548 bufferlist bl;
1549 bufferptr ptr(buffer::create_page_aligned(2));
1550 ptr.set_offset(1);
1551 ptr.set_length(1);
1552 bl.append(ptr);
1553 EXPECT_FALSE(bl.is_page_aligned());
1554 bl.rebuild_page_aligned();
1555 EXPECT_TRUE(bl.is_page_aligned());
1556 }
1557 {
1558 bufferlist bl;
1559 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE + 1));
1560 ptr.set_offset(1);
1561 ptr.set_length(CEPH_PAGE_SIZE);
1562 bl.append(ptr);
1563 EXPECT_FALSE(bl.is_page_aligned());
1564 bl.rebuild_page_aligned();
1565 EXPECT_TRUE(bl.is_page_aligned());
1566 }
1567 }
1568
1569 TEST(BufferList, is_n_page_sized) {
1570 {
1571 bufferlist bl;
1572 EXPECT_TRUE(bl.is_n_page_sized());
1573 }
1574 {
1575 bufferlist bl;
1576 bl.append_zero(1);
1577 EXPECT_FALSE(bl.is_n_page_sized());
1578 }
1579 {
1580 bufferlist bl;
1581 bl.append_zero(CEPH_PAGE_SIZE);
1582 EXPECT_TRUE(bl.is_n_page_sized());
1583 }
1584 }
1585
1586 TEST(BufferList, page_aligned_appender) {
1587 bufferlist bl;
1588 auto a = bl.get_page_aligned_appender(5);
1589 a.append("asdf", 4);
1590 a.flush();
1591 cout << bl << std::endl;
1592 ASSERT_EQ(1u, bl.get_num_buffers());
1593 a.append("asdf", 4);
1594 for (unsigned n = 0; n < 3 * CEPH_PAGE_SIZE; ++n) {
1595 a.append("x", 1);
1596 }
1597 a.flush();
1598 cout << bl << std::endl;
1599 ASSERT_EQ(1u, bl.get_num_buffers());
1600 for (unsigned n = 0; n < 3 * CEPH_PAGE_SIZE; ++n) {
1601 a.append("y", 1);
1602 }
1603 a.flush();
1604 cout << bl << std::endl;
1605 ASSERT_EQ(2u, bl.get_num_buffers());
1606 for (unsigned n = 0; n < 10 * CEPH_PAGE_SIZE; ++n) {
1607 a.append("asdfasdfasdf", 1);
1608 }
1609 a.flush();
1610 cout << bl << std::endl;
1611 }
1612
1613 TEST(BufferList, rebuild_aligned_size_and_memory) {
1614 const unsigned SIMD_ALIGN = 32;
1615 const unsigned BUFFER_SIZE = 67;
1616
1617 bufferlist bl;
1618 // These two must be concatenated into one memory + size aligned
1619 // bufferptr
1620 {
1621 bufferptr ptr(buffer::create_aligned(2, SIMD_ALIGN));
1622 ptr.set_offset(1);
1623 ptr.set_length(1);
1624 bl.append(ptr);
1625 }
1626 {
1627 bufferptr ptr(buffer::create_aligned(BUFFER_SIZE - 1, SIMD_ALIGN));
1628 bl.append(ptr);
1629 }
1630 // This one must be left alone
1631 {
1632 bufferptr ptr(buffer::create_aligned(BUFFER_SIZE, SIMD_ALIGN));
1633 bl.append(ptr);
1634 }
1635 // These two must be concatenated into one memory + size aligned
1636 // bufferptr
1637 {
1638 bufferptr ptr(buffer::create_aligned(2, SIMD_ALIGN));
1639 ptr.set_offset(1);
1640 ptr.set_length(1);
1641 bl.append(ptr);
1642 }
1643 {
1644 bufferptr ptr(buffer::create_aligned(BUFFER_SIZE - 1, SIMD_ALIGN));
1645 bl.append(ptr);
1646 }
1647 EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
1648 EXPECT_FALSE(bl.is_n_align_sized(BUFFER_SIZE));
1649 EXPECT_EQ(BUFFER_SIZE * 3, bl.length());
1650 EXPECT_FALSE(bl.front().is_aligned(SIMD_ALIGN));
1651 EXPECT_FALSE(bl.front().is_n_align_sized(BUFFER_SIZE));
1652 EXPECT_EQ(5U, bl.get_num_buffers());
1653 bl.rebuild_aligned_size_and_memory(BUFFER_SIZE, SIMD_ALIGN);
1654 EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
1655 EXPECT_TRUE(bl.is_n_align_sized(BUFFER_SIZE));
1656 EXPECT_EQ(3U, bl.get_num_buffers());
1657 }
1658
1659 TEST(BufferList, is_zero) {
1660 {
1661 bufferlist bl;
1662 EXPECT_TRUE(bl.is_zero());
1663 }
1664 {
1665 bufferlist bl;
1666 bl.append('A');
1667 EXPECT_FALSE(bl.is_zero());
1668 }
1669 {
1670 bufferlist bl;
1671 bl.append_zero(1);
1672 EXPECT_TRUE(bl.is_zero());
1673 }
1674
1675 for (size_t i = 1; i <= 256; ++i) {
1676 bufferlist bl;
1677 bl.append_zero(i);
1678 EXPECT_TRUE(bl.is_zero());
1679 bl.append('A');
1680 // ensure buffer is a single, contiguous before testing
1681 bl.rebuild();
1682 EXPECT_FALSE(bl.is_zero());
1683 }
1684
1685 }
1686
1687 TEST(BufferList, clear) {
1688 bufferlist bl;
1689 unsigned len = 17;
1690 bl.append_zero(len);
1691 bl.clear();
1692 EXPECT_EQ((unsigned)0, bl.length());
1693 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1694 }
1695
1696 TEST(BufferList, push_back) {
1697 //
1698 // void push_back(ptr& bp)
1699 //
1700 {
1701 bufferlist bl;
1702 bufferptr ptr;
1703 bl.push_back(ptr);
1704 EXPECT_EQ((unsigned)0, bl.length());
1705 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1706 }
1707 unsigned len = 17;
1708 {
1709 bufferlist bl;
1710 bl.append('A');
1711 bufferptr ptr(len);
1712 ptr.c_str()[0] = 'B';
1713 bl.push_back(ptr);
1714 EXPECT_EQ((unsigned)(1 + len), bl.length());
1715 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1716 EXPECT_EQ('B', bl.back()[0]);
1717 const bufferptr& back_bp = bl.back();
1718 EXPECT_EQ(static_cast<instrumented_bptr&>(ptr).get_raw(),
1719 static_cast<const instrumented_bptr&>(back_bp).get_raw());
1720 }
1721 //
1722 // void push_back(ptr&& bp)
1723 //
1724 {
1725 bufferlist bl;
1726 bufferptr ptr;
1727 bl.push_back(std::move(ptr));
1728 EXPECT_EQ((unsigned)0, bl.length());
1729 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1730 }
1731 {
1732 bufferlist bl;
1733 bl.append('A');
1734 bufferptr ptr(len);
1735 ptr.c_str()[0] = 'B';
1736 bl.push_back(std::move(ptr));
1737 EXPECT_EQ((unsigned)(1 + len), bl.length());
1738 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1739 EXPECT_EQ('B', bl.buffers().back()[0]);
1740 EXPECT_FALSE(static_cast<instrumented_bptr&>(ptr).get_raw());
1741 }
1742 }
1743
1744 TEST(BufferList, is_contiguous) {
1745 bufferlist bl;
1746 EXPECT_TRUE(bl.is_contiguous());
1747 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1748 bl.append('A');
1749 EXPECT_TRUE(bl.is_contiguous());
1750 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
1751 bufferptr ptr(1);
1752 bl.push_back(ptr);
1753 EXPECT_FALSE(bl.is_contiguous());
1754 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1755 }
1756
1757 TEST(BufferList, rebuild) {
1758 {
1759 bufferlist bl;
1760 bufferptr ptr(buffer::create_page_aligned(2));
1761 ptr[0] = 'X';
1762 ptr[1] = 'Y';
1763 ptr.set_offset(1);
1764 ptr.set_length(1);
1765 bl.append(ptr);
1766 EXPECT_FALSE(bl.is_page_aligned());
1767 bl.rebuild();
1768 EXPECT_EQ(1U, bl.length());
1769 EXPECT_EQ('Y', *bl.begin());
1770 }
1771 {
1772 bufferlist bl;
1773 const std::string str(CEPH_PAGE_SIZE, 'X');
1774 bl.append(str.c_str(), str.size());
1775 bl.append(str.c_str(), str.size());
1776 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1777 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
1778 bl.rebuild();
1779 EXPECT_TRUE(bl.is_page_aligned());
1780 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
1781 }
1782 {
1783 bufferlist bl;
1784 char t1[] = "X";
1785 bufferlist a2;
1786 a2.append(t1, 1);
1787 bl.rebuild();
1788 bl.append(a2);
1789 EXPECT_EQ((unsigned)1, bl.length());
1790 bufferlist::iterator p = bl.begin();
1791 char dst[1];
1792 p.copy(1, dst);
1793 EXPECT_EQ(0, memcmp(dst, "X", 1));
1794 }
1795 }
1796
1797 TEST(BufferList, rebuild_page_aligned) {
1798 {
1799 bufferlist bl;
1800 {
1801 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE + 1));
1802 ptr.set_offset(1);
1803 ptr.set_length(CEPH_PAGE_SIZE);
1804 bl.append(ptr);
1805 }
1806 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
1807 EXPECT_FALSE(bl.is_page_aligned());
1808 bl.rebuild_page_aligned();
1809 EXPECT_TRUE(bl.is_page_aligned());
1810 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
1811 }
1812 {
1813 bufferlist bl;
1814 bufferptr ptr(buffer::create_page_aligned(1));
1815 char *p = ptr.c_str();
1816 bl.append(ptr);
1817 bl.rebuild_page_aligned();
1818 EXPECT_EQ(p, bl.front().c_str());
1819 }
1820 {
1821 bufferlist bl;
1822 {
1823 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE));
1824 EXPECT_TRUE(ptr.is_page_aligned());
1825 EXPECT_TRUE(ptr.is_n_page_sized());
1826 bl.append(ptr);
1827 }
1828 {
1829 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE + 1));
1830 EXPECT_TRUE(ptr.is_page_aligned());
1831 EXPECT_FALSE(ptr.is_n_page_sized());
1832 bl.append(ptr);
1833 }
1834 {
1835 bufferptr ptr(buffer::create_page_aligned(2));
1836 ptr.set_offset(1);
1837 ptr.set_length(1);
1838 EXPECT_FALSE(ptr.is_page_aligned());
1839 EXPECT_FALSE(ptr.is_n_page_sized());
1840 bl.append(ptr);
1841 }
1842 {
1843 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE - 2));
1844 EXPECT_TRUE(ptr.is_page_aligned());
1845 EXPECT_FALSE(ptr.is_n_page_sized());
1846 bl.append(ptr);
1847 }
1848 {
1849 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE));
1850 EXPECT_TRUE(ptr.is_page_aligned());
1851 EXPECT_TRUE(ptr.is_n_page_sized());
1852 bl.append(ptr);
1853 }
1854 {
1855 bufferptr ptr(buffer::create_page_aligned(CEPH_PAGE_SIZE + 1));
1856 ptr.set_offset(1);
1857 ptr.set_length(CEPH_PAGE_SIZE);
1858 EXPECT_FALSE(ptr.is_page_aligned());
1859 EXPECT_TRUE(ptr.is_n_page_sized());
1860 bl.append(ptr);
1861 }
1862 EXPECT_EQ((unsigned)6, bl.get_num_buffers());
1863 EXPECT_TRUE((bl.length() & ~CEPH_PAGE_MASK) == 0);
1864 EXPECT_FALSE(bl.is_page_aligned());
1865 bl.rebuild_page_aligned();
1866 EXPECT_TRUE(bl.is_page_aligned());
1867 EXPECT_EQ((unsigned)4, bl.get_num_buffers());
1868 }
1869 }
1870
1871 TEST(BufferList, claim) {
1872 bufferlist from;
1873 {
1874 bufferptr ptr(2);
1875 from.append(ptr);
1876 }
1877 bufferlist to;
1878 {
1879 bufferptr ptr(4);
1880 to.append(ptr);
1881 }
1882 EXPECT_EQ((unsigned)4, to.length());
1883 EXPECT_EQ((unsigned)1, to.get_num_buffers());
1884 to.claim(from);
1885 EXPECT_EQ((unsigned)2, to.length());
1886 EXPECT_EQ((unsigned)1, to.get_num_buffers());
1887 EXPECT_EQ((unsigned)0, from.get_num_buffers());
1888 EXPECT_EQ((unsigned)0, from.length());
1889 }
1890
1891 TEST(BufferList, claim_append) {
1892 bufferlist from;
1893 {
1894 bufferptr ptr(2);
1895 from.append(ptr);
1896 }
1897 bufferlist to;
1898 {
1899 bufferptr ptr(4);
1900 to.append(ptr);
1901 }
1902 EXPECT_EQ((unsigned)4, to.length());
1903 EXPECT_EQ((unsigned)1, to.get_num_buffers());
1904 to.claim_append(from);
1905 EXPECT_EQ((unsigned)(4 + 2), to.length());
1906 EXPECT_EQ((unsigned)4, to.front().length());
1907 EXPECT_EQ((unsigned)2, to.back().length());
1908 EXPECT_EQ((unsigned)2, to.get_num_buffers());
1909 EXPECT_EQ((unsigned)0, from.get_num_buffers());
1910 EXPECT_EQ((unsigned)0, from.length());
1911 }
1912
1913 TEST(BufferList, claim_append_piecewise) {
1914 bufferlist bl, t, dst;
1915 auto a = bl.get_page_aligned_appender(4);
1916 for (uint32_t i = 0; i < (CEPH_PAGE_SIZE + CEPH_PAGE_SIZE - 1333); i++)
1917 a.append("x", 1);
1918 a.flush();
1919 const char *p = bl.c_str();
1920 t.claim_append(bl);
1921
1922 for (uint32_t i = 0; i < (CEPH_PAGE_SIZE + 1333); i++)
1923 a.append("x", 1);
1924 a.flush();
1925 t.claim_append(bl);
1926
1927 EXPECT_FALSE(t.is_aligned_size_and_memory(CEPH_PAGE_SIZE, CEPH_PAGE_SIZE));
1928 dst.claim_append_piecewise(t);
1929 EXPECT_TRUE(dst.is_aligned_size_and_memory(CEPH_PAGE_SIZE, CEPH_PAGE_SIZE));
1930 const char *p1 = dst.c_str();
1931 EXPECT_TRUE(p == p1);
1932 }
1933
1934 TEST(BufferList, begin) {
1935 bufferlist bl;
1936 bl.append("ABC");
1937 bufferlist::iterator i = bl.begin();
1938 EXPECT_EQ('A', *i);
1939 }
1940
1941 TEST(BufferList, end) {
1942 bufferlist bl;
1943 bl.append("AB");
1944 bufferlist::iterator i = bl.end();
1945 bl.append("C");
1946 EXPECT_EQ('C', bl[i.get_off()]);
1947 }
1948
1949 TEST(BufferList, append) {
1950 //
1951 // void append(char c);
1952 //
1953 {
1954 bufferlist bl;
1955 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1956 bl.append('A');
1957 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
1958 //EXPECT_TRUE(bl.is_aligned(CEPH_BUFFER_APPEND_SIZE));
1959 }
1960 //
1961 // void append(const char *data, unsigned len);
1962 //
1963 {
1964 bufferlist bl(CEPH_PAGE_SIZE);
1965 std::string str(CEPH_PAGE_SIZE * 2, 'X');
1966 bl.append(str.c_str(), str.size());
1967 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1968 EXPECT_EQ(CEPH_PAGE_SIZE, bl.front().length());
1969 EXPECT_EQ(CEPH_PAGE_SIZE, bl.back().length());
1970 }
1971 //
1972 // void append(const std::string& s);
1973 //
1974 {
1975 bufferlist bl(CEPH_PAGE_SIZE);
1976 std::string str(CEPH_PAGE_SIZE * 2, 'X');
1977 bl.append(str);
1978 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
1979 EXPECT_EQ(CEPH_PAGE_SIZE, bl.front().length());
1980 EXPECT_EQ(CEPH_PAGE_SIZE, bl.back().length());
1981 }
1982 //
1983 // void append(const ptr& bp);
1984 //
1985 {
1986 bufferlist bl;
1987 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1988 EXPECT_EQ((unsigned)0, bl.length());
1989 {
1990 bufferptr ptr;
1991 bl.append(ptr);
1992 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
1993 EXPECT_EQ((unsigned)0, bl.length());
1994 }
1995 {
1996 bufferptr ptr(3);
1997 bl.append(ptr);
1998 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
1999 EXPECT_EQ((unsigned)3, bl.length());
2000 }
2001 }
2002 //
2003 // void append(const ptr& bp, unsigned off, unsigned len);
2004 //
2005 {
2006 bufferlist bl;
2007 bl.append('A');
2008 bufferptr back(bl.back());
2009 bufferptr in(back);
2010 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2011 EXPECT_EQ((unsigned)1, bl.length());
2012 {
2013 PrCtl unset_dumpable;
2014 EXPECT_DEATH(bl.append(in, (unsigned)100, (unsigned)100), "");
2015 }
2016 EXPECT_LT((unsigned)0, in.unused_tail_length());
2017 in.append('B');
2018 bl.append(in, back.end(), 1);
2019 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2020 EXPECT_EQ((unsigned)2, bl.length());
2021 EXPECT_EQ('B', bl[1]);
2022 }
2023 {
2024 bufferlist bl;
2025 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
2026 EXPECT_EQ((unsigned)0, bl.length());
2027 bufferptr ptr(2);
2028 ptr.set_length(0);
2029 ptr.append("AB", 2);
2030 bl.append(ptr, 1, 1);
2031 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2032 EXPECT_EQ((unsigned)1, bl.length());
2033 }
2034 //
2035 // void append(const list& bl);
2036 //
2037 {
2038 bufferlist bl;
2039 bl.append('A');
2040 bufferlist other;
2041 other.append('B');
2042 bl.append(other);
2043 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
2044 EXPECT_EQ('B', bl[1]);
2045 }
2046 //
2047 // void append(std::istream& in);
2048 //
2049 {
2050 bufferlist bl;
2051 std::string expected("ABC\nDEF\n");
2052 std::istringstream is("ABC\n\nDEF");
2053 bl.append(is);
2054 EXPECT_EQ(0, ::memcmp(expected.c_str(), bl.c_str(), expected.size()));
2055 EXPECT_EQ(expected.size(), bl.length());
2056 }
2057 //
2058 // void append(ptr&& bp);
2059 //
2060 {
2061 bufferlist bl;
2062 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
2063 EXPECT_EQ((unsigned)0, bl.length());
2064 {
2065 bufferptr ptr;
2066 bl.append(std::move(ptr));
2067 EXPECT_EQ((unsigned)0, bl.get_num_buffers());
2068 EXPECT_EQ((unsigned)0, bl.length());
2069 }
2070 {
2071 bufferptr ptr(3);
2072 bl.append(std::move(ptr));
2073 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2074 EXPECT_EQ((unsigned)3, bl.length());
2075 EXPECT_FALSE(static_cast<instrumented_bptr&>(ptr).get_raw());
2076 }
2077 }
2078 }
2079
2080 TEST(BufferList, append_hole) {
2081 {
2082 bufferlist bl;
2083 auto filler = bl.append_hole(1);
2084 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2085 EXPECT_EQ((unsigned)1, bl.length());
2086
2087 bl.append("BC", 2);
2088 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2089 EXPECT_EQ((unsigned)3, bl.length());
2090
2091 const char a = 'A';
2092 filler.copy_in((unsigned)1, &a);
2093 EXPECT_EQ((unsigned)3, bl.length());
2094
2095 EXPECT_EQ(0, ::memcmp("ABC", bl.c_str(), 3));
2096 }
2097
2098 {
2099 bufferlist bl;
2100 bl.append('A');
2101 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2102 EXPECT_EQ((unsigned)1, bl.length());
2103
2104 auto filler = bl.append_hole(1);
2105 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2106 EXPECT_EQ((unsigned)2, bl.length());
2107
2108 bl.append('C');
2109 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2110 EXPECT_EQ((unsigned)3, bl.length());
2111
2112 const char b = 'B';
2113 filler.copy_in((unsigned)1, &b);
2114 EXPECT_EQ((unsigned)3, bl.length());
2115
2116 EXPECT_EQ(0, ::memcmp("ABC", bl.c_str(), 3));
2117 }
2118 }
2119
2120 TEST(BufferList, append_zero) {
2121 bufferlist bl;
2122 bl.append('A');
2123 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2124 EXPECT_EQ((unsigned)1, bl.length());
2125 bl.append_zero(1);
2126 EXPECT_EQ((unsigned)1, bl.get_num_buffers());
2127 EXPECT_EQ((unsigned)2, bl.length());
2128 EXPECT_EQ('\0', bl[1]);
2129 }
2130
2131 TEST(BufferList, operator_brackets) {
2132 bufferlist bl;
2133 EXPECT_THROW(bl[1], buffer::end_of_buffer);
2134 bl.append('A');
2135 bufferlist other;
2136 other.append('B');
2137 bl.append(other);
2138 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
2139 EXPECT_EQ('B', bl[1]);
2140 }
2141
2142 TEST(BufferList, c_str) {
2143 bufferlist bl;
2144 EXPECT_EQ((const char*)NULL, bl.c_str());
2145 bl.append('A');
2146 bufferlist other;
2147 other.append('B');
2148 bl.append(other);
2149 EXPECT_EQ((unsigned)2, bl.get_num_buffers());
2150 EXPECT_EQ(0, ::memcmp("AB", bl.c_str(), 2));
2151 }
2152
2153 TEST(BufferList, substr_of) {
2154 bufferlist bl;
2155 EXPECT_THROW(bl.substr_of(bl, 1, 1), buffer::end_of_buffer);
2156 const char *s[] = {
2157 "ABC",
2158 "DEF",
2159 "GHI",
2160 "JKL"
2161 };
2162 for (unsigned i = 0; i < 4; i++) {
2163 bufferptr ptr(s[i], strlen(s[i]));
2164 bl.push_back(ptr);
2165 }
2166 EXPECT_EQ((unsigned)4, bl.get_num_buffers());
2167
2168 bufferlist other;
2169 other.append("TO BE CLEARED");
2170 other.substr_of(bl, 4, 4);
2171 EXPECT_EQ((unsigned)2, other.get_num_buffers());
2172 EXPECT_EQ((unsigned)4, other.length());
2173 EXPECT_EQ(0, ::memcmp("EFGH", other.c_str(), 4));
2174 }
2175
2176 TEST(BufferList, splice) {
2177 bufferlist bl;
2178 EXPECT_THROW(bl.splice(1, 1), buffer::end_of_buffer);
2179 const char *s[] = {
2180 "ABC",
2181 "DEF",
2182 "GHI",
2183 "JKL"
2184 };
2185 for (unsigned i = 0; i < 4; i++) {
2186 bufferptr ptr(s[i], strlen(s[i]));
2187 bl.push_back(ptr);
2188 }
2189 EXPECT_EQ((unsigned)4, bl.get_num_buffers());
2190 bl.splice(0, 0);
2191
2192 bufferlist other;
2193 other.append('X');
2194 bl.splice(4, 4, &other);
2195 EXPECT_EQ((unsigned)3, other.get_num_buffers());
2196 EXPECT_EQ((unsigned)5, other.length());
2197 EXPECT_EQ(0, ::memcmp("XEFGH", other.c_str(), other.length()));
2198 EXPECT_EQ((unsigned)8, bl.length());
2199 {
2200 bufferlist tmp(bl);
2201 EXPECT_EQ(0, ::memcmp("ABCDIJKL", tmp.c_str(), tmp.length()));
2202 }
2203
2204 bl.splice(4, 4);
2205 EXPECT_EQ((unsigned)4, bl.length());
2206 EXPECT_EQ(0, ::memcmp("ABCD", bl.c_str(), bl.length()));
2207
2208 {
2209 bl.clear();
2210 bufferptr ptr1("0123456789", 10);
2211 bl.push_back(ptr1);
2212 bufferptr ptr2("abcdefghij", 10);
2213 bl.append(ptr2, 5, 5);
2214 other.clear();
2215 bl.splice(10, 4, &other);
2216 EXPECT_EQ((unsigned)11, bl.length());
2217 EXPECT_EQ(0, ::memcmp("fghi", other.c_str(), other.length()));
2218 }
2219 }
2220
2221 TEST(BufferList, write) {
2222 std::ostringstream stream;
2223 bufferlist bl;
2224 bl.append("ABC");
2225 bl.write(1, 2, stream);
2226 EXPECT_EQ("BC", stream.str());
2227 }
2228
2229 TEST(BufferList, encode_base64) {
2230 bufferlist bl;
2231 bl.append("ABCD");
2232 bufferlist other;
2233 bl.encode_base64(other);
2234 const char *expected = "QUJDRA==";
2235 EXPECT_EQ(0, ::memcmp(expected, other.c_str(), strlen(expected)));
2236 }
2237
2238 TEST(BufferList, decode_base64) {
2239 bufferlist bl;
2240 bl.append("QUJDRA==");
2241 bufferlist other;
2242 other.decode_base64(bl);
2243 const char *expected = "ABCD";
2244 EXPECT_EQ(0, ::memcmp(expected, other.c_str(), strlen(expected)));
2245 bufferlist malformed;
2246 malformed.append("QUJDRA");
2247 EXPECT_THROW(other.decode_base64(malformed), buffer::malformed_input);
2248 }
2249
2250 TEST(BufferList, hexdump) {
2251 bufferlist bl;
2252 std::ostringstream stream;
2253 bl.append("013245678901234\0006789012345678901234", 32);
2254 bl.hexdump(stream);
2255 EXPECT_EQ("00000000 30 31 33 32 34 35 36 37 38 39 30 31 32 33 34 00 |013245678901234.|\n"
2256 "00000010 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 |6789012345678901|\n"
2257 "00000020\n",
2258 stream.str());
2259 }
2260
2261 TEST(BufferList, read_file) {
2262 std::string error;
2263 bufferlist bl;
2264 ::unlink(FILENAME);
2265 EXPECT_EQ(-ENOENT, bl.read_file("UNLIKELY", &error));
2266 snprintf(cmd, sizeof(cmd), "echo ABC > %s ; chmod 0 %s", FILENAME, FILENAME);
2267 EXPECT_EQ(0, ::system(cmd));
2268 if (getuid() != 0) {
2269 EXPECT_EQ(-EACCES, bl.read_file(FILENAME, &error));
2270 }
2271 snprintf(cmd, sizeof(cmd), "chmod +r %s", FILENAME);
2272 EXPECT_EQ(0, ::system(cmd));
2273 EXPECT_EQ(0, bl.read_file(FILENAME, &error));
2274 ::unlink(FILENAME);
2275 EXPECT_EQ((unsigned)4, bl.length());
2276 std::string actual(bl.c_str(), bl.length());
2277 EXPECT_EQ("ABC\n", actual);
2278 }
2279
2280 TEST(BufferList, read_fd) {
2281 unsigned len = 4;
2282 ::unlink(FILENAME);
2283 snprintf(cmd, sizeof(cmd), "echo ABC > %s", FILENAME);
2284 EXPECT_EQ(0, ::system(cmd));
2285 int fd = -1;
2286 bufferlist bl;
2287 EXPECT_EQ(-EBADF, bl.read_fd(fd, len));
2288 fd = ::open(FILENAME, O_RDONLY);
2289 ASSERT_NE(-1, fd);
2290 EXPECT_EQ(len, (unsigned)bl.read_fd(fd, len));
2291 //EXPECT_EQ(CEPH_BUFFER_APPEND_SIZE - len, bl.front().unused_tail_length());
2292 EXPECT_EQ(len, bl.length());
2293 ::close(fd);
2294 ::unlink(FILENAME);
2295 }
2296
2297 TEST(BufferList, write_file) {
2298 ::unlink(FILENAME);
2299 int mode = 0600;
2300 bufferlist bl;
2301 EXPECT_EQ(-ENOENT, bl.write_file("un/like/ly", mode));
2302 bl.append("ABC");
2303 EXPECT_EQ(0, bl.write_file(FILENAME, mode));
2304 struct stat st;
2305 memset(&st, 0, sizeof(st));
2306 ASSERT_EQ(0, ::stat(FILENAME, &st));
2307 EXPECT_EQ((unsigned)(mode | S_IFREG), st.st_mode);
2308 ::unlink(FILENAME);
2309 }
2310
2311 TEST(BufferList, write_fd) {
2312 ::unlink(FILENAME);
2313 int fd = ::open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600);
2314 ASSERT_NE(-1, fd);
2315 bufferlist bl;
2316 for (unsigned i = 0; i < IOV_MAX * 2; i++) {
2317 bufferptr ptr("A", 1);
2318 bl.push_back(ptr);
2319 }
2320 EXPECT_EQ(0, bl.write_fd(fd));
2321 ::close(fd);
2322 struct stat st;
2323 memset(&st, 0, sizeof(st));
2324 ASSERT_EQ(0, ::stat(FILENAME, &st));
2325 EXPECT_EQ(IOV_MAX * 2, st.st_size);
2326 ::unlink(FILENAME);
2327 }
2328
2329 TEST(BufferList, write_fd_offset) {
2330 ::unlink(FILENAME);
2331 int fd = ::open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600);
2332 ASSERT_NE(-1, fd);
2333 bufferlist bl;
2334 for (unsigned i = 0; i < IOV_MAX * 2; i++) {
2335 bufferptr ptr("A", 1);
2336 bl.push_back(ptr);
2337 }
2338 uint64_t offset = 200;
2339 EXPECT_EQ(0, bl.write_fd(fd, offset));
2340 ::close(fd);
2341 struct stat st;
2342 memset(&st, 0, sizeof(st));
2343 ASSERT_EQ(0, ::stat(FILENAME, &st));
2344 EXPECT_EQ(IOV_MAX * 2 + offset, (unsigned)st.st_size);
2345 ::unlink(FILENAME);
2346 }
2347
2348 TEST(BufferList, crc32c) {
2349 bufferlist bl;
2350 __u32 crc = 0;
2351 bl.append("A");
2352 crc = bl.crc32c(crc);
2353 EXPECT_EQ((unsigned)0xB3109EBF, crc);
2354 crc = bl.crc32c(crc);
2355 EXPECT_EQ((unsigned)0x5FA5C0CC, crc);
2356 }
2357
2358 TEST(BufferList, crc32c_append) {
2359 bufferlist bl1;
2360 bufferlist bl2;
2361
2362 for (int j = 0; j < 200; ++j) {
2363 bufferlist bl;
2364 for (int i = 0; i < 200; ++i) {
2365 char x = rand();
2366 bl.append(x);
2367 bl1.append(x);
2368 }
2369 bl.crc32c(rand()); // mess with the cached bufferptr crc values
2370 bl2.append(bl);
2371 }
2372 ASSERT_EQ(bl1.crc32c(0), bl2.crc32c(0));
2373 }
2374
2375 TEST(BufferList, crc32c_zeros) {
2376 char buffer[4*1024];
2377 for (size_t i=0; i < sizeof(buffer); i++)
2378 {
2379 buffer[i] = i;
2380 }
2381
2382 bufferlist bla;
2383 bufferlist blb;
2384
2385 for (size_t j=0; j < 1000; j++)
2386 {
2387 bufferptr a(buffer, sizeof(buffer));
2388
2389 bla.push_back(a);
2390 uint32_t crca = bla.crc32c(111);
2391
2392 blb.push_back(a);
2393 uint32_t crcb = ceph_crc32c(111, (unsigned char*)blb.c_str(), blb.length());
2394
2395 EXPECT_EQ(crca, crcb);
2396 }
2397 }
2398
2399 TEST(BufferList, crc32c_append_perf) {
2400 int len = 256 * 1024 * 1024;
2401 bufferptr a(len);
2402 bufferptr b(len);
2403 bufferptr c(len);
2404 bufferptr d(len);
2405 std::cout << "populating large buffers (a, b=c=d)" << std::endl;
2406 char *pa = a.c_str();
2407 char *pb = b.c_str();
2408 char *pc = c.c_str();
2409 char *pd = c.c_str();
2410 for (int i=0; i<len; i++) {
2411 pa[i] = (i & 0xff) ^ 73;
2412 pb[i] = (i & 0xff) ^ 123;
2413 pc[i] = (i & 0xff) ^ 123;
2414 pd[i] = (i & 0xff) ^ 123;
2415 }
2416
2417 // track usage of cached crcs
2418 buffer::track_cached_crc(true);
2419
2420 [[maybe_unused]] int base_cached = buffer::get_cached_crc();
2421 [[maybe_unused]] int base_cached_adjusted = buffer::get_cached_crc_adjusted();
2422
2423 bufferlist bla;
2424 bla.push_back(a);
2425 bufferlist blb;
2426 blb.push_back(b);
2427 {
2428 utime_t start = ceph_clock_now();
2429 uint32_t r = bla.crc32c(0);
2430 utime_t end = ceph_clock_now();
2431 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2432 std::cout << "a.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2433 ASSERT_EQ(r, 1138817026u);
2434 }
2435 ceph_assert(buffer::get_cached_crc() == 0 + base_cached);
2436 {
2437 utime_t start = ceph_clock_now();
2438 uint32_t r = bla.crc32c(0);
2439 utime_t end = ceph_clock_now();
2440 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2441 std::cout << "a.crc32c(0) (again) = " << r << " at " << rate << " MB/sec" << std::endl;
2442 ASSERT_EQ(r, 1138817026u);
2443 }
2444 ceph_assert(buffer::get_cached_crc() == 1 + base_cached);
2445
2446 {
2447 utime_t start = ceph_clock_now();
2448 uint32_t r = bla.crc32c(5);
2449 utime_t end = ceph_clock_now();
2450 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2451 std::cout << "a.crc32c(5) = " << r << " at " << rate << " MB/sec" << std::endl;
2452 ASSERT_EQ(r, 3239494520u);
2453 }
2454 ceph_assert(buffer::get_cached_crc() == 1 + base_cached);
2455 ceph_assert(buffer::get_cached_crc_adjusted() == 1 + base_cached_adjusted);
2456 {
2457 utime_t start = ceph_clock_now();
2458 uint32_t r = bla.crc32c(5);
2459 utime_t end = ceph_clock_now();
2460 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2461 std::cout << "a.crc32c(5) (again) = " << r << " at " << rate << " MB/sec" << std::endl;
2462 ASSERT_EQ(r, 3239494520u);
2463 }
2464 ceph_assert(buffer::get_cached_crc() == 1 + base_cached);
2465 ceph_assert(buffer::get_cached_crc_adjusted() == 2 + base_cached_adjusted);
2466 {
2467 utime_t start = ceph_clock_now();
2468 uint32_t r = blb.crc32c(0);
2469 utime_t end = ceph_clock_now();
2470 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2471 std::cout << "b.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2472 ASSERT_EQ(r, 2481791210u);
2473 }
2474 ceph_assert(buffer::get_cached_crc() == 1 + base_cached);
2475 {
2476 utime_t start = ceph_clock_now();
2477 uint32_t r = blb.crc32c(0);
2478 utime_t end = ceph_clock_now();
2479 float rate = (float)len / (float)(1024*1024) / (float)(end - start);
2480 std::cout << "b.crc32c(0) (again)= " << r << " at " << rate << " MB/sec" << std::endl;
2481 ASSERT_EQ(r, 2481791210u);
2482 }
2483 ceph_assert(buffer::get_cached_crc() == 2 + base_cached);
2484
2485 bufferlist ab;
2486 ab.push_back(a);
2487 ab.push_back(b);
2488 {
2489 utime_t start = ceph_clock_now();
2490 uint32_t r = ab.crc32c(0);
2491 utime_t end = ceph_clock_now();
2492 float rate = (float)ab.length() / (float)(1024*1024) / (float)(end - start);
2493 std::cout << "ab.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2494 ASSERT_EQ(r, 2988268779u);
2495 }
2496 ceph_assert(buffer::get_cached_crc() == 3 + base_cached);
2497 ceph_assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted);
2498 bufferlist ac;
2499 ac.push_back(a);
2500 ac.push_back(c);
2501 {
2502 utime_t start = ceph_clock_now();
2503 uint32_t r = ac.crc32c(0);
2504 utime_t end = ceph_clock_now();
2505 float rate = (float)ac.length() / (float)(1024*1024) / (float)(end - start);
2506 std::cout << "ac.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2507 ASSERT_EQ(r, 2988268779u);
2508 }
2509 ceph_assert(buffer::get_cached_crc() == 4 + base_cached);
2510 ceph_assert(buffer::get_cached_crc_adjusted() == 3 + base_cached_adjusted);
2511
2512 bufferlist ba;
2513 ba.push_back(b);
2514 ba.push_back(a);
2515 {
2516 utime_t start = ceph_clock_now();
2517 uint32_t r = ba.crc32c(0);
2518 utime_t end = ceph_clock_now();
2519 float rate = (float)ba.length() / (float)(1024*1024) / (float)(end - start);
2520 std::cout << "ba.crc32c(0) = " << r << " at " << rate << " MB/sec" << std::endl;
2521 ASSERT_EQ(r, 169240695u);
2522 }
2523 ceph_assert(buffer::get_cached_crc() == 5 + base_cached);
2524 ceph_assert(buffer::get_cached_crc_adjusted() == 4 + base_cached_adjusted);
2525 {
2526 utime_t start = ceph_clock_now();
2527 uint32_t r = ba.crc32c(5);
2528 utime_t end = ceph_clock_now();
2529 float rate = (float)ba.length() / (float)(1024*1024) / (float)(end - start);
2530 std::cout << "ba.crc32c(5) = " << r << " at " << rate << " MB/sec" << std::endl;
2531 ASSERT_EQ(r, 1265464778u);
2532 }
2533 ceph_assert(buffer::get_cached_crc() == 5 + base_cached);
2534 ceph_assert(buffer::get_cached_crc_adjusted() == 6 + base_cached_adjusted);
2535
2536 cout << "crc cache hits (same start) = " << buffer::get_cached_crc() << std::endl;
2537 cout << "crc cache hits (adjusted) = " << buffer::get_cached_crc_adjusted() << std::endl;
2538 }
2539
2540 TEST(BufferList, compare) {
2541 bufferlist a;
2542 a.append("A");
2543 bufferlist ab;
2544 ab.append("AB");
2545 bufferlist ac;
2546 ac.append("AC");
2547 //
2548 // bool operator>(bufferlist& l, bufferlist& r)
2549 //
2550 ASSERT_FALSE(a > ab);
2551 ASSERT_TRUE(ab > a);
2552 ASSERT_TRUE(ac > ab);
2553 ASSERT_FALSE(ab > ac);
2554 ASSERT_FALSE(ab > ab);
2555 //
2556 // bool operator>=(bufferlist& l, bufferlist& r)
2557 //
2558 ASSERT_FALSE(a >= ab);
2559 ASSERT_TRUE(ab >= a);
2560 ASSERT_TRUE(ac >= ab);
2561 ASSERT_FALSE(ab >= ac);
2562 ASSERT_TRUE(ab >= ab);
2563 //
2564 // bool operator<(bufferlist& l, bufferlist& r)
2565 //
2566 ASSERT_TRUE(a < ab);
2567 ASSERT_FALSE(ab < a);
2568 ASSERT_FALSE(ac < ab);
2569 ASSERT_TRUE(ab < ac);
2570 ASSERT_FALSE(ab < ab);
2571 //
2572 // bool operator<=(bufferlist& l, bufferlist& r)
2573 //
2574 ASSERT_TRUE(a <= ab);
2575 ASSERT_FALSE(ab <= a);
2576 ASSERT_FALSE(ac <= ab);
2577 ASSERT_TRUE(ab <= ac);
2578 ASSERT_TRUE(ab <= ab);
2579 //
2580 // bool operator==(bufferlist &l, bufferlist &r)
2581 //
2582 ASSERT_FALSE(a == ab);
2583 ASSERT_FALSE(ac == ab);
2584 ASSERT_TRUE(ab == ab);
2585 }
2586
2587 TEST(BufferList, ostream) {
2588 std::ostringstream stream;
2589 bufferlist bl;
2590 const char *s[] = {
2591 "ABC",
2592 "DEF"
2593 };
2594 for (unsigned i = 0; i < 2; i++) {
2595 bufferptr ptr(s[i], strlen(s[i]));
2596 bl.push_back(ptr);
2597 }
2598 stream << bl;
2599 std::cerr << stream.str() << std::endl;
2600 EXPECT_GT(stream.str().size(), stream.str().find("list(len=6,"));
2601 EXPECT_GT(stream.str().size(), stream.str().find("len 3 nref 1),\n"));
2602 EXPECT_GT(stream.str().size(), stream.str().find("len 3 nref 1)\n"));
2603 }
2604
2605 TEST(BufferList, zero) {
2606 //
2607 // void zero()
2608 //
2609 {
2610 bufferlist bl;
2611 bl.append('A');
2612 EXPECT_EQ('A', bl[0]);
2613 bl.zero();
2614 EXPECT_EQ('\0', bl[0]);
2615 }
2616 //
2617 // void zero(unsigned o, unsigned l)
2618 //
2619 const char *s[] = {
2620 "ABC",
2621 "DEF",
2622 "GHI",
2623 "KLM"
2624 };
2625 {
2626 bufferlist bl;
2627 bufferptr ptr(s[0], strlen(s[0]));
2628 bl.push_back(ptr);
2629 bl.zero((unsigned)0, (unsigned)1);
2630 EXPECT_EQ(0, ::memcmp("\0BC", bl.c_str(), 3));
2631 }
2632 {
2633 bufferlist bl;
2634 for (unsigned i = 0; i < 4; i++) {
2635 bufferptr ptr(s[i], strlen(s[i]));
2636 bl.push_back(ptr);
2637 }
2638 {
2639 PrCtl unset_dumpable;
2640 EXPECT_DEATH(bl.zero((unsigned)0, (unsigned)2000), "");
2641 }
2642 bl.zero((unsigned)2, (unsigned)5);
2643 EXPECT_EQ(0, ::memcmp("AB\0\0\0\0\0HIKLM", bl.c_str(), 9));
2644 }
2645 {
2646 bufferlist bl;
2647 for (unsigned i = 0; i < 4; i++) {
2648 bufferptr ptr(s[i], strlen(s[i]));
2649 bl.push_back(ptr);
2650 }
2651 bl.zero((unsigned)3, (unsigned)3);
2652 EXPECT_EQ(0, ::memcmp("ABC\0\0\0GHIKLM", bl.c_str(), 9));
2653 }
2654 {
2655 bufferlist bl;
2656 bufferptr ptr1(4);
2657 bufferptr ptr2(4);
2658 memset(ptr1.c_str(), 'a', 4);
2659 memset(ptr2.c_str(), 'b', 4);
2660 bl.append(ptr1);
2661 bl.append(ptr2);
2662 bl.zero((unsigned)2, (unsigned)4);
2663 EXPECT_EQ(0, ::memcmp("aa\0\0\0\0bb", bl.c_str(), 8));
2664 }
2665 }
2666
2667 TEST(BufferList, EmptyAppend) {
2668 bufferlist bl;
2669 bufferptr ptr;
2670 bl.push_back(ptr);
2671 ASSERT_EQ(bl.begin().end(), 1);
2672 }
2673
2674 TEST(BufferList, InternalCarriage) {
2675 ceph::bufferlist bl;
2676 EXPECT_EQ(bl.get_num_buffers(), 0u);
2677
2678 encode(int64_t(42), bl);
2679 EXPECT_EQ(bl.get_num_buffers(), 1u);
2680
2681 {
2682 ceph::bufferlist bl_with_foo;
2683 bl_with_foo.append("foo", 3);
2684 EXPECT_EQ(bl_with_foo.length(), 3u);
2685 EXPECT_EQ(bl_with_foo.get_num_buffers(), 1u);
2686
2687 bl.append(bl_with_foo);
2688 EXPECT_EQ(bl.get_num_buffers(), 2u);
2689 }
2690
2691 encode(int64_t(24), bl);
2692 EXPECT_EQ(bl.get_num_buffers(), 3u);
2693 }
2694
2695 TEST(BufferList, ContiguousAppender) {
2696 ceph::bufferlist bl;
2697 EXPECT_EQ(bl.get_num_buffers(), 0u);
2698
2699 // we expect a flush in ~contiguous_appender
2700 {
2701 auto ap = bl.get_contiguous_appender(100);
2702
2703 denc(int64_t(42), ap);
2704 EXPECT_EQ(bl.get_num_buffers(), 1u);
2705
2706 // append bufferlist with single ptr inside. This should
2707 // commit changes to bl::_len and the underlying bp::len.
2708 {
2709 ceph::bufferlist bl_with_foo;
2710 bl_with_foo.append("foo", 3);
2711 EXPECT_EQ(bl_with_foo.length(), 3u);
2712 EXPECT_EQ(bl_with_foo.get_num_buffers(), 1u);
2713
2714 ap.append(bl_with_foo);
2715 // 3 as the ap::append(const bl&) splits the bp with free
2716 // space.
2717 EXPECT_EQ(bl.get_num_buffers(), 3u);
2718 }
2719
2720 denc(int64_t(24), ap);
2721 EXPECT_EQ(bl.get_num_buffers(), 3u);
2722 EXPECT_EQ(bl.length(), sizeof(int64_t) + 3u);
2723 }
2724 EXPECT_EQ(bl.length(), 2u * sizeof(int64_t) + 3u);
2725 }
2726
2727 TEST(BufferList, TestPtrAppend) {
2728 bufferlist bl;
2729 char correct[MAX_TEST];
2730 int curpos = 0;
2731 int length = random() % 5 > 0 ? random() % 1000 : 0;
2732 while (curpos + length < MAX_TEST) {
2733 if (!length) {
2734 bufferptr ptr;
2735 bl.push_back(ptr);
2736 } else {
2737 char *current = correct + curpos;
2738 for (int i = 0; i < length; ++i) {
2739 char next = random() % 255;
2740 correct[curpos++] = next;
2741 }
2742 bufferptr ptr(current, length);
2743 bl.append(ptr);
2744 }
2745 length = random() % 5 > 0 ? random() % 1000 : 0;
2746 }
2747 ASSERT_EQ(memcmp(bl.c_str(), correct, curpos), 0);
2748 }
2749
2750 TEST(BufferList, TestDirectAppend) {
2751 bufferlist bl;
2752 char correct[MAX_TEST];
2753 int curpos = 0;
2754 int length = random() % 5 > 0 ? random() % 1000 : 0;
2755 while (curpos + length < MAX_TEST) {
2756 char *current = correct + curpos;
2757 for (int i = 0; i < length; ++i) {
2758 char next = random() % 255;
2759 correct[curpos++] = next;
2760 }
2761 bl.append(current, length);
2762 length = random() % 5 > 0 ? random() % 1000 : 0;
2763 }
2764 ASSERT_EQ(memcmp(bl.c_str(), correct, curpos), 0);
2765 }
2766
2767 TEST(BufferList, TestCopyAll) {
2768 const static size_t BIG_SZ = 10737414;
2769 std::shared_ptr <unsigned char> big(
2770 (unsigned char*)malloc(BIG_SZ), free);
2771 unsigned char c = 0;
2772 for (size_t i = 0; i < BIG_SZ; ++i) {
2773 big.get()[i] = c++;
2774 }
2775 bufferlist bl;
2776 bl.append((const char*)big.get(), BIG_SZ);
2777 bufferlist::iterator i = bl.begin();
2778 bufferlist bl2;
2779 i.copy_all(bl2);
2780 ASSERT_EQ(bl2.length(), BIG_SZ);
2781 std::shared_ptr <unsigned char> big2(
2782 (unsigned char*)malloc(BIG_SZ), free);
2783 bl2.begin().copy(BIG_SZ, (char*)big2.get());
2784 ASSERT_EQ(memcmp(big.get(), big2.get(), BIG_SZ), 0);
2785 }
2786
2787 TEST(BufferList, InvalidateCrc) {
2788 const static size_t buffer_size = 262144;
2789 std::shared_ptr <unsigned char> big(
2790 (unsigned char*)malloc(buffer_size), free);
2791 unsigned char c = 0;
2792 char* ptr = (char*) big.get();
2793 char* inptr;
2794 for (size_t i = 0; i < buffer_size; ++i) {
2795 ptr[i] = c++;
2796 }
2797 bufferlist bl;
2798
2799 // test for crashes (shouldn't crash)
2800 bl.invalidate_crc();
2801
2802 // put data into bufferlist
2803 bl.append((const char*)big.get(), buffer_size);
2804
2805 // get its crc
2806 __u32 crc = bl.crc32c(0);
2807
2808 // modify data in bl without its knowledge
2809 inptr = (char*) bl.c_str();
2810 c = 0;
2811 for (size_t i = 0; i < buffer_size; ++i) {
2812 inptr[i] = c--;
2813 }
2814
2815 // make sure data in bl are now different than in big
2816 EXPECT_NE(memcmp((void*) ptr, (void*) inptr, buffer_size), 0);
2817
2818 // crc should remain the same
2819 __u32 new_crc = bl.crc32c(0);
2820 EXPECT_EQ(crc, new_crc);
2821
2822 // force crc invalidate, check if it is updated
2823 bl.invalidate_crc();
2824 EXPECT_NE(crc, bl.crc32c(0));
2825 }
2826
2827 TEST(BufferList, TestIsProvidedBuffer) {
2828 char buff[100];
2829 bufferlist bl;
2830 bl.push_back(buffer::create_static(100, buff));
2831 ASSERT_TRUE(bl.is_provided_buffer(buff));
2832 bl.append_zero(100);
2833 ASSERT_FALSE(bl.is_provided_buffer(buff));
2834 }
2835
2836 TEST(BufferList, DISABLED_DanglingLastP) {
2837 bufferlist bl;
2838 {
2839 // previously we're using the unsharable buffer type to distinguish
2840 // the last_p-specific problem from the generic crosstalk issues we
2841 // had since the very beginning:
2842 // https://gist.github.com/rzarzynski/aed18372e88aed392101adac3bd87bbc
2843 // this is no longer possible as `buffer::create_unsharable()` has
2844 // been dropped.
2845 bufferptr bp(buffer::create(10));
2846 bp.copy_in(0, 3, "XXX");
2847 bl.push_back(std::move(bp));
2848 EXPECT_EQ(0, ::memcmp("XXX", bl.c_str(), 3));
2849
2850 // let `copy_in` to set `last_p` member of bufferlist
2851 bl.begin().copy_in(2, "AB");
2852 EXPECT_EQ(0, ::memcmp("ABX", bl.c_str(), 3));
2853 }
2854
2855 bufferlist empty;
2856 // before the fix this would have left `last_p` unchanged leading to
2857 // the dangerous dangling state – keep in mind that the initial,
2858 // unsharable bptr will be freed.
2859 bl = const_cast<const bufferlist&>(empty);
2860 bl.append("123");
2861
2862 // we must continue from where the previous copy_in had finished.
2863 // Otherwise `bl::copy_in` will call `seek()` and refresh `last_p`.
2864 bl.begin(2).copy_in(1, "C");
2865 EXPECT_EQ(0, ::memcmp("12C", bl.c_str(), 3));
2866 }
2867
2868 TEST(BufferHash, all) {
2869 {
2870 bufferlist bl;
2871 bl.append("A");
2872 bufferhash hash;
2873 EXPECT_EQ((unsigned)0, hash.digest());
2874 hash.update(bl);
2875 EXPECT_EQ((unsigned)0xB3109EBF, hash.digest());
2876 hash.update(bl);
2877 EXPECT_EQ((unsigned)0x5FA5C0CC, hash.digest());
2878 }
2879 {
2880 bufferlist bl;
2881 bl.append("A");
2882 bufferhash hash;
2883 EXPECT_EQ((unsigned)0, hash.digest());
2884 bufferhash& returned_hash = hash << bl;
2885 EXPECT_EQ(&returned_hash, &hash);
2886 EXPECT_EQ((unsigned)0xB3109EBF, hash.digest());
2887 }
2888 }
2889
2890 /*
2891 * Local Variables:
2892 * compile-command: "cd .. ; make unittest_bufferlist &&
2893 * ulimit -s unlimited ; valgrind \
2894 * --max-stackframe=20000000 --tool=memcheck \
2895 * ./unittest_bufferlist # --gtest_filter=BufferList.constructors"
2896 * End:
2897 */
2898