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