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