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