Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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 #include "include/crc32c.h"
40 #include "common/sctp_crc32.h"
41
42 #define MAX_TEST 1000000
43 #define FILENAME "bufferlist"
44
45 static char cmd[128];
46
47 TEST(Buffer, constructors) {
48   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
240 void 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
252 TEST(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
261 TEST(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
270 class TestRawPipe : public ::testing::Test {
271 protected:
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
288 TEST_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
296 TEST_F(TestRawPipe, c_str_no_fd) {
297   EXPECT_THROW(bufferptr ptr(buffer::create_zero_copy(len, -1, NULL)),
298                buffer::error_code);
299 }
300
301 TEST_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
307 TEST_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
315 TEST_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
323 TEST_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
330 TEST_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
337 TEST_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
346 TEST_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
355 TEST_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
363 TEST_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
371 TEST_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
379 TEST_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
392 TEST_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 //
423 TEST(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
508 TEST(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
532 TEST(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
580 TEST(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
588 TEST(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
616 TEST(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
627 TEST(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
638 TEST(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
645 TEST(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
652 TEST(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
663 TEST(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
674 TEST(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
735 TEST(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
752 TEST(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
764 TEST(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
781 TEST(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
800 TEST(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
820 TEST(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
838 TEST(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
862 TEST(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
883 TEST(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
898 TEST(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 //
938 TEST(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
1001 TEST(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
1012 TEST(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
1024 TEST(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
1031 TEST(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
1038 TEST(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
1051 TEST(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
1080 TEST(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
1103 TEST(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
1139 TEST(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
1148 TEST(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
1163 TEST(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
1179 TEST(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
1206 TEST(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
1220 TEST(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
1236 TEST(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
1340 TEST(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++()
1382 TEST(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
1398 TEST(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
1438 void 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
1451 TEST(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
1465 TEST(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
1496 TEST(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
1503 TEST(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
1521 TEST(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
1570 TEST(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
1588 TEST(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
1595 TEST(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
1616 TEST(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
1644 TEST(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
1662 TEST(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
1689 TEST(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
1706 TEST(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
1733 TEST(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
1779 TEST(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   }
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
1805 }
1806
1807 TEST(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
1816 TEST(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
1876 TEST(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
1936 TEST(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
1949 TEST(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
1989 TEST(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
2063 TEST(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
2083 TEST(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
2105 TEST(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
2127 TEST(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
2148 TEST(BufferList, begin) {
2149   bufferlist bl;
2150   bl.append("ABC");
2151   bufferlist::iterator i = bl.begin();
2152   EXPECT_EQ('A', *i);
2153 }
2154
2155 TEST(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
2163 TEST(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
2203 TEST(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
2228 TEST(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
2359 TEST(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
2370 TEST(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
2381 TEST(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
2392 TEST(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
2415 TEST(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
2460 TEST(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
2468 TEST(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
2477 TEST(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
2489 TEST(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
2500 TEST(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
2519 TEST(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
2535 TEST(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
2549 TEST(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
2566 TEST(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
2584 TEST(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
2594 TEST(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
2611 TEST(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
2635 TEST(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);
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
2776 TEST(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
2823 TEST(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
2841 TEST(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
2903 TEST(BufferList, EmptyAppend) {
2904   bufferlist bl;
2905   bufferptr ptr;
2906   bl.push_back(ptr);
2907   ASSERT_EQ(bl.begin().end(), 1);
2908 }
2909
2910 TEST(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
2933 TEST(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
2950 TEST(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
2992 TEST(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
3012 TEST(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
3052 TEST(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
3061 TEST(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