abseil-cpp/absl/strings/cord_test.cc
Go to the documentation of this file.
1 // Copyright 2020 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/strings/cord.h"
16 
17 #include <algorithm>
18 #include <climits>
19 #include <cstdio>
20 #include <iterator>
21 #include <map>
22 #include <numeric>
23 #include <random>
24 #include <sstream>
25 #include <type_traits>
26 #include <utility>
27 #include <vector>
28 
29 #include "gmock/gmock.h"
30 #include "gtest/gtest.h"
31 #include "absl/base/casts.h"
32 #include "absl/base/config.h"
33 #include "absl/base/internal/endian.h"
34 #include "absl/base/internal/raw_logging.h"
35 #include "absl/base/macros.h"
36 #include "absl/container/fixed_array.h"
37 #include "absl/hash/hash.h"
38 #include "absl/random/random.h"
39 #include "absl/strings/cord_test_helpers.h"
40 #include "absl/strings/cordz_test_helpers.h"
41 #include "absl/strings/match.h"
42 #include "absl/strings/str_cat.h"
43 #include "absl/strings/str_format.h"
44 #include "absl/strings/string_view.h"
45 
46 // convenience local constants
47 static constexpr auto FLAT = absl::cord_internal::FLAT;
49 
50 typedef std::mt19937_64 RandomEngine;
51 
62 
65 
66 static int GetUniformRandomUpTo(RandomEngine* rng, int upper_bound) {
67  if (upper_bound > 0) {
68  std::uniform_int_distribution<int> uniform(0, upper_bound - 1);
69  return uniform(*rng);
70  } else {
71  return 0;
72  }
73 }
74 
75 static size_t GetUniformRandomUpTo(RandomEngine* rng, size_t upper_bound) {
76  if (upper_bound > 0) {
77  std::uniform_int_distribution<size_t> uniform(0, upper_bound - 1);
78  return uniform(*rng);
79  } else {
80  return 0;
81  }
82 }
83 
84 static int32_t GenerateSkewedRandom(RandomEngine* rng, int max_log) {
85  const uint32_t base = (*rng)() % (max_log + 1);
86  const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u;
87  return (*rng)() & mask;
88 }
89 
91  int length;
92  std::bernoulli_distribution one_in_1k(0.001);
93  std::bernoulli_distribution one_in_10k(0.0001);
94  // With low probability, make a large fragment
95  if (one_in_10k(*rng)) {
96  length = GetUniformRandomUpTo(rng, 1048576);
97  } else if (one_in_1k(*rng)) {
98  length = GetUniformRandomUpTo(rng, 10000);
99  } else {
100  length = GenerateSkewedRandom(rng, 10);
101  }
102  return RandomLowercaseString(rng, length);
103 }
104 
106  std::string result(length, '\0');
107  std::uniform_int_distribution<int> chars('a', 'z');
108  std::generate(result.begin(), result.end(),
109  [&]() { return static_cast<char>(chars(*rng)); });
110  return result;
111 }
112 
113 static void DoNothing(absl::string_view /* data */, void* /* arg */) {}
114 
116  std::string* s = reinterpret_cast<std::string*>(arg);
117  EXPECT_EQ(data, *s);
118  delete s;
119 }
120 
121 // Add "s" to *dst via `MakeCordFromExternal`
123  std::string* str = new std::string(s.data(), s.size());
126  }));
127 }
128 
129 static void DumpGrowth() {
130  absl::Cord str;
131  for (int i = 0; i < 1000; i++) {
132  char c = 'a' + i % 26;
133  str.Append(absl::string_view(&c, 1));
134  }
135 }
136 
137 // Make a Cord with some number of fragments. Return the size (in bytes)
138 // of the smallest fragment.
139 static size_t AppendWithFragments(const std::string& s, RandomEngine* rng,
140  absl::Cord* cord) {
141  size_t j = 0;
142  const size_t max_size = s.size() / 5; // Make approx. 10 fragments
143  size_t min_size = max_size; // size of smallest fragment
144  while (j < s.size()) {
145  size_t N = 1 + GetUniformRandomUpTo(rng, max_size);
146  if (N > (s.size() - j)) {
147  N = s.size() - j;
148  }
149  if (N < min_size) {
150  min_size = N;
151  }
152 
153  std::bernoulli_distribution coin_flip(0.5);
154  if (coin_flip(*rng)) {
155  // Grow by adding an external-memory.
156  AddExternalMemory(absl::string_view(s.data() + j, N), cord);
157  } else {
158  cord->Append(absl::string_view(s.data() + j, N));
159  }
160  j += N;
161  }
162  return min_size;
163 }
164 
165 // Add an external memory that contains the specified std::string to cord
167  char* data = new char[str.size()];
168  memcpy(data, str.data(), str.size());
170  absl::string_view(data, str.size()),
171  [](absl::string_view s) { delete[] s.data(); }));
172 }
173 
174 // Make a Cord out of many different types of nodes.
176  absl::Cord cord;
177  cord.Append("the");
178  AddExternalMemory(" quick brown", &cord);
179  AddExternalMemory(" fox jumped", &cord);
180 
181  absl::Cord full(" over");
182  AddExternalMemory(" the lazy", &full);
183  AddNewStringBlock(" dog slept the whole day away", &full);
184  absl::Cord substring = full.Subcord(0, 18);
185 
186  // Make substring long enough to defeat the copying fast path in Append.
187  substring.Append(std::string(1000, '.'));
188  cord.Append(substring);
189  cord = cord.Subcord(0, cord.size() - 998); // Remove most of extra junk
190 
191  return cord;
192 }
193 
194 namespace absl {
196 
198  public:
199  static void ForEachChunk(
201  c.ForEachChunk(callback);
202  }
203 
204  static bool IsTree(const Cord& c) { return c.contents_.is_tree(); }
205  static CordRep* Tree(const Cord& c) { return c.contents_.tree(); }
206 
208  return c.contents_.cordz_info();
209  }
210 
211  static Cord MakeSubstring(Cord src, size_t offset, size_t length) {
212  ABSL_RAW_CHECK(src.contents_.is_tree(), "Can not be inlined");
213  ABSL_RAW_CHECK(src.ExpectedChecksum() == absl::nullopt,
214  "Can not be hardened");
215  Cord cord;
216  auto* tree = cord_internal::SkipCrcNode(src.contents_.tree());
217  auto* rep = CordRepSubstring::Create(CordRep::Ref(tree), offset, length);
218  cord.contents_.EmplaceTree(rep, CordzUpdateTracker::kSubCord);
219  return cord;
220  }
221 };
222 
224 } // namespace absl
225 
226 // The CordTest fixture runs all tests with and without Cord Btree enabled,
227 // and with our without expected CRCs being set on the subject Cords.
228 class CordTest : public testing::TestWithParam<int> {
229  public:
230  // Returns true if test is running with btree enabled.
231  bool UseCrc() const { return GetParam() == 2 || GetParam() == 3; }
233  if (UseCrc()) {
234  c.SetExpectedChecksum(1);
235  }
236  }
238  MaybeHarden(c);
239  return c;
240  }
241 
242  // Returns human readable string representation of the test parameter.
244  switch (param.param) {
245  case 0:
246  return "Btree";
247  case 1:
248  return "BtreeHardened";
249  default:
250  assert(false);
251  return "???";
252  }
253  }
254 };
255 
258 
259 TEST(CordRepFlat, AllFlatCapacities) {
260  // Explicitly and redundantly assert built-in min/max limits
261  static_assert(absl::cord_internal::kFlatOverhead < 32, "");
262  static_assert(absl::cord_internal::kMinFlatSize == 32, "");
263  static_assert(absl::cord_internal::kMaxLargeFlatSize == 256 << 10, "");
266 
267  // Verify all tags to map perfectly back and forth, and
268  // that sizes are monotonically increasing.
269  size_t last_size = 0;
270  for (int tag = FLAT; tag <= MAX_FLAT_TAG; ++tag) {
272  ASSERT_GT(size, last_size);
274  last_size = size;
275  }
276 
277  // All flat size from 32 - 512 are 8 byte granularity
278  for (size_t size = 32; size <= 512; size += 8) {
282  }
283 
284  // All flat sizes from 512 - 8192 are 64 byte granularity
285  for (size_t size = 512; size <= 8192; size += 64) {
289  }
290 
291  // All flat sizes from 8KB to 256KB are 4KB granularity
292  for (size_t size = 8192; size <= 256 * 1024; size += 4 * 1024) {
296  }
297 }
298 
299 TEST(CordRepFlat, MaxFlatSize) {
302  CordRep::Unref(flat);
303 
304  flat = CordRepFlat::New(kMaxFlatLength * 4);
306  CordRep::Unref(flat);
307 }
308 
309 TEST(CordRepFlat, MaxLargeFlatSize) {
310  const size_t size = 256 * 1024 - kFlatOverhead;
311  CordRepFlat* flat = CordRepFlat::New(CordRepFlat::Large(), size);
312  EXPECT_GE(flat->Capacity(), size);
313  CordRep::Unref(flat);
314 }
315 
316 TEST(CordRepFlat, AllFlatSizes) {
317  const size_t kMaxSize = 256 * 1024;
318  for (size_t size = 32; size <= kMaxSize; size *=2) {
319  const size_t length = size - kFlatOverhead - 1;
320  CordRepFlat* flat = CordRepFlat::New(CordRepFlat::Large(), length);
321  EXPECT_GE(flat->Capacity(), length);
322  memset(flat->Data(), 0xCD, flat->Capacity());
323  CordRep::Unref(flat);
324  }
325 }
326 
327 TEST_P(CordTest, AllFlatSizes) {
329 
330  for (size_t s = 0; s < CordTestAccess::MaxFlatLength(); s++) {
331  // Make a string of length s.
332  std::string src;
333  while (src.size() < s) {
334  src.push_back('a' + (src.size() % 26));
335  }
336 
337  absl::Cord dst(src);
338  MaybeHarden(dst);
339  EXPECT_EQ(std::string(dst), src) << s;
340  }
341 }
342 
343 // We create a Cord at least 128GB in size using the fact that Cords can
344 // internally reference-count; thus the Cord is enormous without actually
345 // consuming very much memory.
346 TEST_P(CordTest, GigabyteCordFromExternal) {
347  const size_t one_gig = 1024U * 1024U * 1024U;
348  size_t max_size = 2 * one_gig;
349  if (sizeof(max_size) > 4) max_size = 128 * one_gig;
350 
351  size_t length = 128 * 1024;
352  char* data = new char[length];
355  [](absl::string_view sv) { delete[] sv.data(); });
356 
357  // This loop may seem odd due to its combination of exponential doubling of
358  // size and incremental size increases. We do it incrementally to be sure the
359  // Cord will need rebalancing and will exercise code that, in the past, has
360  // caused crashes in production. We grow exponentially so that the code will
361  // execute in a reasonable amount of time.
362  absl::Cord c;
363  c.Append(from);
364  while (c.size() < max_size) {
365  c.Append(c);
366  c.Append(from);
367  c.Append(from);
368  c.Append(from);
369  c.Append(from);
370  MaybeHarden(c);
371  }
372 
373  for (int i = 0; i < 1024; ++i) {
374  c.Append(from);
375  }
376  ABSL_RAW_LOG(INFO, "Made a Cord with %zu bytes!", c.size());
377  // Note: on a 32-bit build, this comes out to 2,818,048,000 bytes.
378  // Note: on a 64-bit build, this comes out to 171,932,385,280 bytes.
379 }
380 
382  char* buffer = new char[size];
383  memset(buffer, 'x', size);
384  absl::Cord cord;
387  [](absl::string_view s) { delete[] s.data(); }));
388  return cord;
389 }
390 
391 // Extern to fool clang that this is not constant. Needed to suppress
392 // a warning of unsafe code we want to test.
393 extern bool my_unique_true_boolean;
395 
396 TEST_P(CordTest, Assignment) {
397  absl::Cord x(absl::string_view("hi there"));
398  absl::Cord y(x);
399  MaybeHarden(y);
400  ASSERT_EQ(x.ExpectedChecksum(), absl::nullopt);
401  ASSERT_EQ(std::string(x), "hi there");
402  ASSERT_EQ(std::string(y), "hi there");
403  ASSERT_TRUE(x == y);
404  ASSERT_TRUE(x <= y);
405  ASSERT_TRUE(y <= x);
406 
407  x = absl::string_view("foo");
408  ASSERT_EQ(std::string(x), "foo");
409  ASSERT_EQ(std::string(y), "hi there");
410  ASSERT_TRUE(x < y);
411  ASSERT_TRUE(y > x);
412  ASSERT_TRUE(x != y);
413  ASSERT_TRUE(x <= y);
414  ASSERT_TRUE(y >= x);
415 
416  x = "foo";
417  ASSERT_EQ(x, "foo");
418 
419  // Test that going from inline rep to tree we don't leak memory.
420  std::vector<std::pair<absl::string_view, absl::string_view>>
421  test_string_pairs = {{"hi there", "foo"},
422  {"loooooong coooooord", "short cord"},
423  {"short cord", "loooooong coooooord"},
424  {"loooooong coooooord1", "loooooong coooooord2"}};
425  for (std::pair<absl::string_view, absl::string_view> test_strings :
426  test_string_pairs) {
427  absl::Cord tmp(test_strings.first);
429  ASSERT_EQ(std::string(z), test_strings.first);
430  tmp = test_strings.second;
431  z = std::move(tmp);
432  ASSERT_EQ(std::string(z), test_strings.second);
433  }
434  {
435  // Test that self-move assignment doesn't crash/leak.
436  // Do not write such code!
437  absl::Cord my_small_cord("foo");
438  absl::Cord my_big_cord("loooooong coooooord");
439  // Bypass clang's warning on self move-assignment.
440  absl::Cord* my_small_alias =
441  my_unique_true_boolean ? &my_small_cord : &my_big_cord;
442  absl::Cord* my_big_alias =
443  !my_unique_true_boolean ? &my_small_cord : &my_big_cord;
444 
445  *my_small_alias = std::move(my_small_cord);
446  *my_big_alias = std::move(my_big_cord);
447  // my_small_cord and my_big_cord are in an unspecified but valid
448  // state, and will be correctly destroyed here.
449  }
450 }
451 
452 TEST_P(CordTest, StartsEndsWith) {
453  absl::Cord x(absl::string_view("abcde"));
454  MaybeHarden(x);
455  absl::Cord empty("");
456 
457  ASSERT_TRUE(x.StartsWith(absl::Cord("abcde")));
458  ASSERT_TRUE(x.StartsWith(absl::Cord("abc")));
459  ASSERT_TRUE(x.StartsWith(absl::Cord("")));
460  ASSERT_TRUE(empty.StartsWith(absl::Cord("")));
461  ASSERT_TRUE(x.EndsWith(absl::Cord("abcde")));
462  ASSERT_TRUE(x.EndsWith(absl::Cord("cde")));
463  ASSERT_TRUE(x.EndsWith(absl::Cord("")));
464  ASSERT_TRUE(empty.EndsWith(absl::Cord("")));
465 
466  ASSERT_TRUE(!x.StartsWith(absl::Cord("xyz")));
467  ASSERT_TRUE(!empty.StartsWith(absl::Cord("xyz")));
468  ASSERT_TRUE(!x.EndsWith(absl::Cord("xyz")));
469  ASSERT_TRUE(!empty.EndsWith(absl::Cord("xyz")));
470 
471  ASSERT_TRUE(x.StartsWith("abcde"));
472  ASSERT_TRUE(x.StartsWith("abc"));
473  ASSERT_TRUE(x.StartsWith(""));
474  ASSERT_TRUE(empty.StartsWith(""));
475  ASSERT_TRUE(x.EndsWith("abcde"));
476  ASSERT_TRUE(x.EndsWith("cde"));
477  ASSERT_TRUE(x.EndsWith(""));
478  ASSERT_TRUE(empty.EndsWith(""));
479 
480  ASSERT_TRUE(!x.StartsWith("xyz"));
481  ASSERT_TRUE(!empty.StartsWith("xyz"));
482  ASSERT_TRUE(!x.EndsWith("xyz"));
483  ASSERT_TRUE(!empty.EndsWith("xyz"));
484 }
485 
486 TEST_P(CordTest, Subcord) {
487  RandomEngine rng(GTEST_FLAG_GET(random_seed));
488  const std::string s = RandomLowercaseString(&rng, 1024);
489 
490  absl::Cord a;
491  AppendWithFragments(s, &rng, &a);
492  MaybeHarden(a);
493  ASSERT_EQ(s, std::string(a));
494 
495  // Check subcords of a, from a variety of interesting points.
496  std::set<size_t> positions;
497  for (int i = 0; i <= 32; ++i) {
498  positions.insert(i);
499  positions.insert(i * 32 - 1);
500  positions.insert(i * 32);
501  positions.insert(i * 32 + 1);
502  positions.insert(a.size() - i);
503  }
504  positions.insert(237);
505  positions.insert(732);
506  for (size_t pos : positions) {
507  if (pos > a.size()) continue;
508  for (size_t end_pos : positions) {
509  if (end_pos < pos || end_pos > a.size()) continue;
510  absl::Cord sa = a.Subcord(pos, end_pos - pos);
511  ASSERT_EQ(absl::string_view(s).substr(pos, end_pos - pos),
512  std::string(sa))
513  << a;
514  if (pos != 0 || end_pos != a.size()) {
515  ASSERT_EQ(sa.ExpectedChecksum(), absl::nullopt);
516  }
517  }
518  }
519 
520  // Do the same thing for an inline cord.
521  const std::string sh = "short";
522  absl::Cord c(sh);
523  for (size_t pos = 0; pos <= sh.size(); ++pos) {
524  for (size_t n = 0; n <= sh.size() - pos; ++n) {
525  absl::Cord sc = c.Subcord(pos, n);
526  ASSERT_EQ(sh.substr(pos, n), std::string(sc)) << c;
527  }
528  }
529 
530  // Check subcords of subcords.
531  absl::Cord sa = a.Subcord(0, a.size());
532  std::string ss = s.substr(0, s.size());
533  while (sa.size() > 1) {
534  sa = sa.Subcord(1, sa.size() - 2);
535  ss = ss.substr(1, ss.size() - 2);
536  ASSERT_EQ(ss, std::string(sa)) << a;
537  if (HasFailure()) break; // halt cascade
538  }
539 
540  // It is OK to ask for too much.
541  sa = a.Subcord(0, a.size() + 1);
542  EXPECT_EQ(s, std::string(sa));
543 
544  // It is OK to ask for something beyond the end.
545  sa = a.Subcord(a.size() + 1, 0);
546  EXPECT_TRUE(sa.empty());
547  sa = a.Subcord(a.size() + 1, 1);
548  EXPECT_TRUE(sa.empty());
549 }
550 
552  absl::string_view a("Dexter");
553  absl::string_view b("Mandark");
554  absl::Cord x(a);
555  absl::Cord y(b);
556  MaybeHarden(x);
557  swap(x, y);
558  if (UseCrc()) {
559  ASSERT_EQ(x.ExpectedChecksum(), absl::nullopt);
560  ASSERT_EQ(y.ExpectedChecksum(), 1);
561  }
562  ASSERT_EQ(x, absl::Cord(b));
563  ASSERT_EQ(y, absl::Cord(a));
564  x.swap(y);
565  if (UseCrc()) {
566  ASSERT_EQ(x.ExpectedChecksum(), 1);
567  ASSERT_EQ(y.ExpectedChecksum(), absl::nullopt);
568  }
569  ASSERT_EQ(x, absl::Cord(a));
570  ASSERT_EQ(y, absl::Cord(b));
571 }
572 
573 static void VerifyCopyToString(const absl::Cord& cord) {
574  std::string initially_empty;
575  absl::CopyCordToString(cord, &initially_empty);
576  EXPECT_EQ(initially_empty, cord);
577 
578  constexpr size_t kInitialLength = 1024;
579  std::string has_initial_contents(kInitialLength, 'x');
580  const char* address_before_copy = has_initial_contents.data();
581  absl::CopyCordToString(cord, &has_initial_contents);
582  EXPECT_EQ(has_initial_contents, cord);
583 
584  if (cord.size() <= kInitialLength) {
585  EXPECT_EQ(has_initial_contents.data(), address_before_copy)
586  << "CopyCordToString allocated new string storage; "
587  "has_initial_contents = \""
588  << has_initial_contents << "\"";
589  }
590 }
591 
592 TEST_P(CordTest, CopyToString) {
593  VerifyCopyToString(absl::Cord()); // empty cords cannot carry CRCs
594  VerifyCopyToString(MaybeHardened(absl::Cord("small cord")));
595  VerifyCopyToString(MaybeHardened(
596  absl::MakeFragmentedCord({"fragmented ", "cord ", "to ", "test ",
597  "copying ", "to ", "a ", "string."})));
598 }
599 
600 TEST_P(CordTest, AppendEmptyBuffer) {
601  absl::Cord cord;
602  cord.Append(absl::CordBuffer());
604 }
605 
606 TEST_P(CordTest, AppendEmptyBufferToFlat) {
607  absl::Cord cord(std::string(2000, 'x'));
608  cord.Append(absl::CordBuffer());
610 }
611 
612 TEST_P(CordTest, AppendEmptyBufferToTree) {
613  absl::Cord cord(std::string(2000, 'x'));
614  cord.Append(std::string(2000, 'y'));
615  cord.Append(absl::CordBuffer());
617 }
618 
619 TEST_P(CordTest, AppendSmallBuffer) {
620  absl::Cord cord;
622  ASSERT_THAT(buffer.capacity(), ::testing::Le(15));
623  memcpy(buffer.data(), "Abc", 3);
624  buffer.SetLength(3);
625  cord.Append(std::move(buffer));
626  EXPECT_EQ(buffer.length(), 0); // NOLINT
627  EXPECT_GT(buffer.capacity(), 0); // NOLINT
628 
630  memcpy(buffer.data(), "defgh", 5);
631  buffer.SetLength(5);
632  cord.Append(std::move(buffer));
633  EXPECT_EQ(buffer.length(), 0); // NOLINT
634  EXPECT_GT(buffer.capacity(), 0); // NOLINT
635 
636  EXPECT_THAT(cord.Chunks(), ::testing::ElementsAre("Abcdefgh"));
637 }
638 
639 TEST_P(CordTest, AppendAndPrependBufferArePrecise) {
640  // Create a cord large enough to force 40KB flats.
642  absl::Cord cord1(test_data);
643  absl::Cord cord2(test_data);
644  const size_t size1 = cord1.EstimatedMemoryUsage();
645  const size_t size2 = cord2.EstimatedMemoryUsage();
646 
648  memcpy(buffer.data(), "Abc", 3);
649  buffer.SetLength(3);
650  cord1.Append(std::move(buffer));
651 
653  memcpy(buffer.data(), "Abc", 3);
654  buffer.SetLength(3);
655  cord2.Prepend(std::move(buffer));
656 
657 #ifndef NDEBUG
658  // Allow 32 bytes new CordRepFlat, and 128 bytes for 'glue nodes'
659  constexpr size_t kMaxDelta = 128 + 32;
660 #else
661  // Allow 256 bytes extra for 'allocation debug overhead'
662  constexpr size_t kMaxDelta = 128 + 32 + 256;
663 #endif
664 
665  EXPECT_LE(cord1.EstimatedMemoryUsage() - size1, kMaxDelta);
666  EXPECT_LE(cord2.EstimatedMemoryUsage() - size2, kMaxDelta);
667 
668  EXPECT_EQ(cord1, absl::StrCat(test_data, "Abc"));
669  EXPECT_EQ(cord2, absl::StrCat("Abc", test_data));
670 }
671 
672 TEST_P(CordTest, PrependSmallBuffer) {
673  absl::Cord cord;
675  ASSERT_THAT(buffer.capacity(), ::testing::Le(15));
676  memcpy(buffer.data(), "Abc", 3);
677  buffer.SetLength(3);
678  cord.Prepend(std::move(buffer));
679  EXPECT_EQ(buffer.length(), 0); // NOLINT
680  EXPECT_GT(buffer.capacity(), 0); // NOLINT
681 
683  memcpy(buffer.data(), "defgh", 5);
684  buffer.SetLength(5);
685  cord.Prepend(std::move(buffer));
686  EXPECT_EQ(buffer.length(), 0); // NOLINT
687  EXPECT_GT(buffer.capacity(), 0); // NOLINT
688 
689  EXPECT_THAT(cord.Chunks(), ::testing::ElementsAre("defghAbc"));
690 }
691 
692 TEST_P(CordTest, AppendLargeBuffer) {
693  absl::Cord cord;
694 
695  std::string s1(700, '1');
697  memcpy(buffer.data(), s1.data(), s1.size());
698  buffer.SetLength(s1.size());
699  cord.Append(std::move(buffer));
700  EXPECT_EQ(buffer.length(), 0); // NOLINT
701  EXPECT_GT(buffer.capacity(), 0); // NOLINT
702 
703  std::string s2(1000, '2');
705  memcpy(buffer.data(), s2.data(), s2.size());
706  buffer.SetLength(s2.size());
707  cord.Append(std::move(buffer));
708  EXPECT_EQ(buffer.length(), 0); // NOLINT
709  EXPECT_GT(buffer.capacity(), 0); // NOLINT
710 
711  EXPECT_THAT(cord.Chunks(), ::testing::ElementsAre(s1, s2));
712 }
713 
714 TEST_P(CordTest, PrependLargeBuffer) {
715  absl::Cord cord;
716 
717  std::string s1(700, '1');
719  memcpy(buffer.data(), s1.data(), s1.size());
720  buffer.SetLength(s1.size());
721  cord.Prepend(std::move(buffer));
722  EXPECT_EQ(buffer.length(), 0); // NOLINT
723  EXPECT_GT(buffer.capacity(), 0); // NOLINT
724 
725  std::string s2(1000, '2');
727  memcpy(buffer.data(), s2.data(), s2.size());
728  buffer.SetLength(s2.size());
729  cord.Prepend(std::move(buffer));
730  EXPECT_EQ(buffer.length(), 0); // NOLINT
731  EXPECT_GT(buffer.capacity(), 0); // NOLINT
732 
733  EXPECT_THAT(cord.Chunks(), ::testing::ElementsAre(s2, s1));
734 }
735 
736 TEST_P(CordTest, GetAppendBufferOnEmptyCord) {
737  absl::Cord cord;
739  EXPECT_GE(buffer.capacity(), 1000);
740  EXPECT_EQ(buffer.length(), 0);
741 }
742 
743 TEST_P(CordTest, GetAppendBufferOnInlinedCord) {
744  static constexpr int kInlinedSize = sizeof(absl::CordBuffer) - 1;
745  for (int size : {6, kInlinedSize - 3, kInlinedSize - 2, 1000}) {
746  absl::Cord cord("Abc");
748  EXPECT_GE(buffer.capacity(), 3 + size);
749  EXPECT_EQ(buffer.length(), 3);
750  EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), "Abc");
751  EXPECT_TRUE(cord.empty());
752  }
753 }
754 
755 TEST_P(CordTest, GetAppendBufferOnInlinedCordWithCapacityCloseToMax) {
756  // Cover the use case where we have a non empty inlined cord with some size
757  // 'n', and ask for something like 'uint64_max - k', assuming internal logic
758  // could overflow on 'uint64_max - k + size', and return a valid, but
759  // inefficiently smaller buffer if it would provide is the max allowed size.
760  for (size_t dist_from_max = 0; dist_from_max <= 4; ++dist_from_max) {
761  absl::Cord cord("Abc");
762  size_t size = std::numeric_limits<size_t>::max() - dist_from_max;
765  EXPECT_EQ(buffer.length(), 3);
766  EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), "Abc");
767  EXPECT_TRUE(cord.empty());
768  }
769 }
770 
771 TEST_P(CordTest, GetAppendBufferOnFlat) {
772  // Create a cord with a single flat and extra capacity
773  absl::Cord cord;
775  buffer.SetLength(3);
776  memcpy(buffer.data(), "Abc", 3);
777  cord.Append(std::move(buffer));
778 
779  buffer = cord.GetAppendBuffer(6);
780  EXPECT_GE(buffer.capacity(), 500);
781  EXPECT_EQ(buffer.length(), 3);
782  EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), "Abc");
783  EXPECT_TRUE(cord.empty());
784 }
785 
786 TEST_P(CordTest, GetAppendBufferOnFlatWithoutMinCapacity) {
787  // Create a cord with a single flat and extra capacity
788  absl::Cord cord;
790  buffer.SetLength(30);
791  memset(buffer.data(), 'x', 30);
792  cord.Append(std::move(buffer));
793 
794  buffer = cord.GetAppendBuffer(1000, 900);
795  EXPECT_GE(buffer.capacity(), 1000);
796  EXPECT_EQ(buffer.length(), 0);
797  EXPECT_EQ(cord, std::string(30, 'x'));
798 }
799 
800 TEST_P(CordTest, GetAppendBufferOnTree) {
801  RandomEngine rng;
802  for (int num_flats : {2, 3, 100}) {
803  // Create a cord with `num_flats` flats and extra capacity
804  absl::Cord cord;
806  std::string last;
807  for (int i = 0; i < num_flats - 1; ++i) {
808  prefix += last;
809  last = RandomLowercaseString(&rng, 10);
811  buffer.SetLength(10);
812  memcpy(buffer.data(), last.data(), 10);
813  cord.Append(std::move(buffer));
814  }
816  EXPECT_GE(buffer.capacity(), 500);
817  EXPECT_EQ(buffer.length(), 10);
818  EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), last);
819  EXPECT_EQ(cord, prefix);
820  }
821 }
822 
823 TEST_P(CordTest, GetAppendBufferOnTreeWithoutMinCapacity) {
824  absl::Cord cord;
825  for (int i = 0; i < 2; ++i) {
827  buffer.SetLength(3);
828  memcpy(buffer.data(), i ? "def" : "Abc", 3);
829  cord.Append(std::move(buffer));
830  }
831  absl::CordBuffer buffer = cord.GetAppendBuffer(1000, 900);
832  EXPECT_GE(buffer.capacity(), 1000);
833  EXPECT_EQ(buffer.length(), 0);
834  EXPECT_EQ(cord, "Abcdef");
835 }
836 
837 TEST_P(CordTest, GetAppendBufferOnSubstring) {
838  // Create a large cord with a single flat and some extra capacity
839  absl::Cord cord;
841  buffer.SetLength(450);
842  memset(buffer.data(), 'x', 450);
843  cord.Append(std::move(buffer));
844  cord.RemovePrefix(1);
845 
846  // Deny on substring
847  buffer = cord.GetAppendBuffer(6);
848  EXPECT_EQ(buffer.length(), 0);
849  EXPECT_EQ(cord, std::string(449, 'x'));
850 }
851 
852 TEST_P(CordTest, GetAppendBufferOnSharedCord) {
853  // Create a shared cord with a single flat and extra capacity
854  absl::Cord cord;
856  buffer.SetLength(3);
857  memcpy(buffer.data(), "Abc", 3);
858  cord.Append(std::move(buffer));
859  absl::Cord shared_cord = cord;
860 
861  // Deny on flat
862  buffer = cord.GetAppendBuffer(6);
863  EXPECT_EQ(buffer.length(), 0);
864  EXPECT_EQ(cord, "Abc");
865 
867  buffer.SetLength(3);
868  memcpy(buffer.data(), "def", 3);
869  cord.Append(std::move(buffer));
870  shared_cord = cord;
871 
872  // Deny on tree
873  buffer = cord.GetAppendBuffer(6);
874  EXPECT_EQ(buffer.length(), 0);
875  EXPECT_EQ(cord, "Abcdef");
876 }
877 
878 TEST_P(CordTest, TryFlatEmpty) {
879  absl::Cord c;
880  EXPECT_EQ(c.TryFlat(), "");
881 }
882 
883 TEST_P(CordTest, TryFlatFlat) {
884  absl::Cord c("hello");
885  MaybeHarden(c);
886  EXPECT_EQ(c.TryFlat(), "hello");
887 }
888 
889 TEST_P(CordTest, TryFlatSubstrInlined) {
890  absl::Cord c("hello");
891  c.RemovePrefix(1);
892  MaybeHarden(c);
893  EXPECT_EQ(c.TryFlat(), "ello");
894 }
895 
896 TEST_P(CordTest, TryFlatSubstrFlat) {
897  absl::Cord c("longer than 15 bytes");
898  absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
899  MaybeHarden(sub);
900  EXPECT_EQ(sub.TryFlat(), "onger than 15 bytes");
901 }
902 
903 TEST_P(CordTest, TryFlatConcat) {
904  absl::Cord c = absl::MakeFragmentedCord({"hel", "lo"});
905  MaybeHarden(c);
906  EXPECT_EQ(c.TryFlat(), absl::nullopt);
907 }
908 
909 TEST_P(CordTest, TryFlatExternal) {
911  MaybeHarden(c);
912  EXPECT_EQ(c.TryFlat(), "hell");
913 }
914 
915 TEST_P(CordTest, TryFlatSubstrExternal) {
917  absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
918  MaybeHarden(sub);
919  EXPECT_EQ(sub.TryFlat(), "ell");
920 }
921 
922 TEST_P(CordTest, TryFlatCommonlyAssumedInvariants) {
923  // The behavior tested below is not part of the API contract of Cord, but it's
924  // something we intend to be true in our current implementation. This test
925  // exists to detect and prevent accidental breakage of the implementation.
926  absl::string_view fragments[] = {"A fragmented test",
927  " cord",
928  " to test subcords",
929  " of ",
930  "a",
931  " cord for",
932  " each chunk "
933  "returned by the ",
934  "iterator"};
936  MaybeHarden(c);
937  int fragment = 0;
938  int offset = 0;
939  absl::Cord::CharIterator itc = c.char_begin();
940  for (absl::string_view sv : c.Chunks()) {
941  absl::string_view expected = fragments[fragment];
942  absl::Cord subcord1 = c.Subcord(offset, sv.length());
943  absl::Cord subcord2 = absl::Cord::AdvanceAndRead(&itc, sv.size());
944  EXPECT_EQ(subcord1.TryFlat(), expected);
945  EXPECT_EQ(subcord2.TryFlat(), expected);
946  ++fragment;
947  offset += sv.length();
948  }
949 }
950 
951 static bool IsFlat(const absl::Cord& c) {
952  return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end();
953 }
954 
955 static void VerifyFlatten(absl::Cord c) {
956  std::string old_contents(c);
957  absl::string_view old_flat;
958  bool already_flat_and_non_empty = IsFlat(c) && !c.empty();
959  if (already_flat_and_non_empty) {
960  old_flat = *c.chunk_begin();
961  }
962  absl::string_view new_flat = c.Flatten();
963 
964  // Verify that the contents of the flattened Cord are correct.
965  EXPECT_EQ(new_flat, old_contents);
966  EXPECT_EQ(std::string(c), old_contents);
967 
968  // If the Cord contained data and was already flat, verify that the data
969  // wasn't copied.
970  if (already_flat_and_non_empty) {
971  EXPECT_EQ(old_flat.data(), new_flat.data())
972  << "Allocated new memory even though the Cord was already flat.";
973  }
974 
975  // Verify that the flattened Cord is in fact flat.
976  EXPECT_TRUE(IsFlat(c));
977 }
978 
979 TEST_P(CordTest, Flatten) {
981  VerifyFlatten(MaybeHardened(absl::Cord("small cord")));
983  MaybeHardened(absl::Cord("larger than small buffer optimization")));
984  VerifyFlatten(MaybeHardened(
985  absl::MakeFragmentedCord({"small ", "fragmented ", "cord"})));
986 
987  // Test with a cord that is longer than the largest flat buffer
988  RandomEngine rng(GTEST_FLAG_GET(random_seed));
989  VerifyFlatten(MaybeHardened(absl::Cord(RandomLowercaseString(&rng, 8192))));
990 }
991 
992 // Test data
993 namespace {
994 class TestData {
995  private:
996  std::vector<std::string> data_;
997 
998  // Return a std::string of the specified length.
999  static std::string MakeString(int length) {
1001  char buf[30];
1002  snprintf(buf, sizeof(buf), "(%d)", length);
1003  while (result.size() < length) {
1004  result += buf;
1005  }
1006  result.resize(length);
1007  return result;
1008  }
1009 
1010  public:
1011  TestData() {
1012  // short strings increasing in length by one
1013  for (int i = 0; i < 30; i++) {
1014  data_.push_back(MakeString(i));
1015  }
1016 
1017  // strings around half kMaxFlatLength
1018  static const int kMaxFlatLength = 4096 - 9;
1019  static const int kHalf = kMaxFlatLength / 2;
1020 
1021  for (int i = -10; i <= +10; i++) {
1022  data_.push_back(MakeString(kHalf + i));
1023  }
1024 
1025  for (int i = -10; i <= +10; i++) {
1026  data_.push_back(MakeString(kMaxFlatLength + i));
1027  }
1028  }
1029 
1030  size_t size() const { return data_.size(); }
1031  const std::string& data(size_t i) const { return data_[i]; }
1032 };
1033 } // namespace
1034 
1035 TEST_P(CordTest, MultipleLengths) {
1036  TestData d;
1037  for (size_t i = 0; i < d.size(); i++) {
1038  std::string a = d.data(i);
1039 
1040  { // Construct from Cord
1041  absl::Cord tmp(a);
1042  absl::Cord x(tmp);
1043  MaybeHarden(x);
1044  EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
1045  }
1046 
1047  { // Construct from absl::string_view
1048  absl::Cord x(a);
1049  MaybeHarden(x);
1050  EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
1051  }
1052 
1053  { // Append cord to self
1054  absl::Cord self(a);
1055  MaybeHarden(self);
1056  self.Append(self);
1057  EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
1058  }
1059 
1060  { // Prepend cord to self
1061  absl::Cord self(a);
1062  MaybeHarden(self);
1063  self.Prepend(self);
1064  EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
1065  }
1066 
1067  // Try to append/prepend others
1068  for (size_t j = 0; j < d.size(); j++) {
1069  std::string b = d.data(j);
1070 
1071  { // CopyFrom Cord
1072  absl::Cord x(a);
1073  absl::Cord y(b);
1074  MaybeHarden(x);
1075  x = y;
1076  EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
1077  }
1078 
1079  { // CopyFrom absl::string_view
1080  absl::Cord x(a);
1081  MaybeHarden(x);
1082  x = b;
1083  EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
1084  }
1085 
1086  { // Cord::Append(Cord)
1087  absl::Cord x(a);
1088  absl::Cord y(b);
1089  MaybeHarden(x);
1090  x.Append(y);
1091  EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
1092  }
1093 
1094  { // Cord::Append(absl::string_view)
1095  absl::Cord x(a);
1096  MaybeHarden(x);
1097  x.Append(b);
1098  EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
1099  }
1100 
1101  { // Cord::Prepend(Cord)
1102  absl::Cord x(a);
1103  absl::Cord y(b);
1104  MaybeHarden(x);
1105  x.Prepend(y);
1106  EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
1107  }
1108 
1109  { // Cord::Prepend(absl::string_view)
1110  absl::Cord x(a);
1111  MaybeHarden(x);
1112  x.Prepend(b);
1113  EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
1114  }
1115  }
1116  }
1117 }
1118 
1119 namespace {
1120 
1121 TEST_P(CordTest, RemoveSuffixWithExternalOrSubstring) {
1123  "foo bar baz", [](absl::string_view s) { DoNothing(s, nullptr); });
1124  EXPECT_EQ("foo bar baz", std::string(cord));
1125 
1126  MaybeHarden(cord);
1127 
1128  // This RemoveSuffix() will wrap the EXTERNAL node in a SUBSTRING node.
1129  cord.RemoveSuffix(4);
1130  EXPECT_EQ("foo bar", std::string(cord));
1131 
1132  MaybeHarden(cord);
1133 
1134  // This RemoveSuffix() will adjust the SUBSTRING node in-place.
1135  cord.RemoveSuffix(4);
1136  EXPECT_EQ("foo", std::string(cord));
1137 }
1138 
1139 TEST_P(CordTest, RemoveSuffixMakesZeroLengthNode) {
1140  absl::Cord c;
1141  c.Append(absl::Cord(std::string(100, 'x')));
1142  absl::Cord other_ref = c; // Prevent inplace appends
1143  MaybeHarden(c);
1144  c.Append(absl::Cord(std::string(200, 'y')));
1145  c.RemoveSuffix(200);
1146  EXPECT_EQ(std::string(100, 'x'), std::string(c));
1147 }
1148 
1149 } // namespace
1150 
1151 // CordSpliceTest contributed by hendrie.
1152 namespace {
1153 
1154 // Create a cord with an external memory block filled with 'z'
1155 absl::Cord CordWithZedBlock(size_t size) {
1156  char* data = new char[size];
1157  if (size > 0) {
1158  memset(data, 'z', size);
1159  }
1162  [](absl::string_view s) { delete[] s.data(); });
1163  return cord;
1164 }
1165 
1166 // Establish that ZedBlock does what we think it does.
1167 TEST_P(CordTest, CordSpliceTestZedBlock) {
1168  absl::Cord blob = CordWithZedBlock(10);
1169  MaybeHarden(blob);
1170  EXPECT_EQ(10, blob.size());
1171  std::string s;
1172  absl::CopyCordToString(blob, &s);
1173  EXPECT_EQ("zzzzzzzzzz", s);
1174 }
1175 
1176 TEST_P(CordTest, CordSpliceTestZedBlock0) {
1177  absl::Cord blob = CordWithZedBlock(0);
1178  MaybeHarden(blob);
1179  EXPECT_EQ(0, blob.size());
1180  std::string s;
1181  absl::CopyCordToString(blob, &s);
1182  EXPECT_EQ("", s);
1183 }
1184 
1185 TEST_P(CordTest, CordSpliceTestZedBlockSuffix1) {
1186  absl::Cord blob = CordWithZedBlock(10);
1187  MaybeHarden(blob);
1188  EXPECT_EQ(10, blob.size());
1189  absl::Cord suffix(blob);
1190  suffix.RemovePrefix(9);
1191  EXPECT_EQ(1, suffix.size());
1192  std::string s;
1194  EXPECT_EQ("z", s);
1195 }
1196 
1197 // Remove all of a prefix block
1198 TEST_P(CordTest, CordSpliceTestZedBlockSuffix0) {
1199  absl::Cord blob = CordWithZedBlock(10);
1200  MaybeHarden(blob);
1201  EXPECT_EQ(10, blob.size());
1202  absl::Cord suffix(blob);
1203  suffix.RemovePrefix(10);
1204  EXPECT_EQ(0, suffix.size());
1205  std::string s;
1207  EXPECT_EQ("", s);
1208 }
1209 
1210 absl::Cord BigCord(size_t len, char v) {
1211  std::string s(len, v);
1212  return absl::Cord(s);
1213 }
1214 
1215 // Splice block into cord.
1216 absl::Cord SpliceCord(const absl::Cord& blob, int64_t offset,
1217  const absl::Cord& block) {
1218  ABSL_RAW_CHECK(offset >= 0, "");
1219  ABSL_RAW_CHECK(offset + block.size() <= blob.size(), "");
1220  absl::Cord result(blob);
1221  result.RemoveSuffix(blob.size() - offset);
1222  result.Append(block);
1223  absl::Cord suffix(blob);
1224  suffix.RemovePrefix(offset + block.size());
1225  result.Append(suffix);
1226  ABSL_RAW_CHECK(blob.size() == result.size(), "");
1227  return result;
1228 }
1229 
1230 // Taking an empty suffix of a block breaks appending.
1231 TEST_P(CordTest, CordSpliceTestRemoveEntireBlock1) {
1232  absl::Cord zero = CordWithZedBlock(10);
1233  MaybeHarden(zero);
1234  absl::Cord suffix(zero);
1235  suffix.RemovePrefix(10);
1237  result.Append(suffix);
1238 }
1239 
1240 TEST_P(CordTest, CordSpliceTestRemoveEntireBlock2) {
1241  absl::Cord zero = CordWithZedBlock(10);
1242  MaybeHarden(zero);
1243  absl::Cord prefix(zero);
1244  prefix.RemoveSuffix(10);
1245  absl::Cord suffix(zero);
1246  suffix.RemovePrefix(10);
1248  result.Append(suffix);
1249 }
1250 
1251 TEST_P(CordTest, CordSpliceTestRemoveEntireBlock3) {
1252  absl::Cord blob = CordWithZedBlock(10);
1253  absl::Cord block = BigCord(10, 'b');
1254  MaybeHarden(blob);
1255  MaybeHarden(block);
1256  blob = SpliceCord(blob, 0, block);
1257 }
1258 
1259 struct CordCompareTestCase {
1260  template <typename LHS, typename RHS>
1261  CordCompareTestCase(const LHS& lhs, const RHS& rhs, bool use_crc)
1262  : lhs_cord(lhs), rhs_cord(rhs) {
1263  if (use_crc) {
1264  lhs_cord.SetExpectedChecksum(1);
1265  }
1266  }
1267 
1268  absl::Cord lhs_cord;
1269  absl::Cord rhs_cord;
1270 };
1271 
1272 const auto sign = [](int x) { return x == 0 ? 0 : (x > 0 ? 1 : -1); };
1273 
1274 void VerifyComparison(const CordCompareTestCase& test_case) {
1275  std::string lhs_string(test_case.lhs_cord);
1276  std::string rhs_string(test_case.rhs_cord);
1277  int expected = sign(lhs_string.compare(rhs_string));
1278  EXPECT_EQ(expected, test_case.lhs_cord.Compare(test_case.rhs_cord))
1279  << "LHS=" << lhs_string << "; RHS=" << rhs_string;
1280  EXPECT_EQ(expected, test_case.lhs_cord.Compare(rhs_string))
1281  << "LHS=" << lhs_string << "; RHS=" << rhs_string;
1282  EXPECT_EQ(-expected, test_case.rhs_cord.Compare(test_case.lhs_cord))
1283  << "LHS=" << rhs_string << "; RHS=" << lhs_string;
1284  EXPECT_EQ(-expected, test_case.rhs_cord.Compare(lhs_string))
1285  << "LHS=" << rhs_string << "; RHS=" << lhs_string;
1286 }
1287 
1289  absl::Cord subcord("aaaaaBBBBBcccccDDDDD");
1290  subcord = subcord.Subcord(3, 10);
1291 
1292  absl::Cord tmp("aaaaaaaaaaaaaaaa");
1293  tmp.Append("BBBBBBBBBBBBBBBB");
1294  absl::Cord concat = absl::Cord("cccccccccccccccc");
1295  concat.Append("DDDDDDDDDDDDDDDD");
1296  concat.Prepend(tmp);
1297 
1298  absl::Cord concat2("aaaaaaaaaaaaa");
1299  concat2.Append("aaaBBBBBBBBBBBBBBBBccccc");
1300  concat2.Append("cccccccccccDDDDDDDDDDDDDD");
1301  concat2.Append("DD");
1302 
1303  const bool use_crc = UseCrc();
1304 
1305  std::vector<CordCompareTestCase> test_cases = {{
1306  // Inline cords
1307  {"abcdef", "abcdef", use_crc},
1308  {"abcdef", "abcdee", use_crc},
1309  {"abcdef", "abcdeg", use_crc},
1310  {"bbcdef", "abcdef", use_crc},
1311  {"bbcdef", "abcdeg", use_crc},
1312  {"abcdefa", "abcdef", use_crc},
1313  {"abcdef", "abcdefa", use_crc},
1314 
1315  // Small flat cords
1316  {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDD", use_crc},
1317  {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBxccccDDDDD", use_crc},
1318  {"aaaaaBBBBBcxcccDDDDD", "aaaaaBBBBBcccccDDDDD", use_crc},
1319  {"aaaaaBBBBBxccccDDDDD", "aaaaaBBBBBcccccDDDDX", use_crc},
1320  {"aaaaaBBBBBcccccDDDDDa", "aaaaaBBBBBcccccDDDDD", use_crc},
1321  {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDDa", use_crc},
1322 
1323  // Subcords
1324  {subcord, subcord, use_crc},
1325  {subcord, "aaBBBBBccc", use_crc},
1326  {subcord, "aaBBBBBccd", use_crc},
1327  {subcord, "aaBBBBBccb", use_crc},
1328  {subcord, "aaBBBBBxcb", use_crc},
1329  {subcord, "aaBBBBBccca", use_crc},
1330  {subcord, "aaBBBBBcc", use_crc},
1331 
1332  // Concats
1333  {concat, concat, use_crc},
1334  {concat,
1335  "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDD",
1336  use_crc},
1337  {concat,
1338  "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBcccccccccccccccxDDDDDDDDDDDDDDDD",
1339  use_crc},
1340  {concat,
1341  "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBacccccccccccccccDDDDDDDDDDDDDDDD",
1342  use_crc},
1343  {concat,
1344  "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDD",
1345  use_crc},
1346  {concat,
1347  "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDDe",
1348  use_crc},
1349 
1350  {concat, concat2, use_crc},
1351  }};
1352 
1353  for (const auto& tc : test_cases) {
1354  VerifyComparison(tc);
1355  }
1356 }
1357 
1358 TEST_P(CordTest, CompareAfterAssign) {
1359  absl::Cord a("aaaaaa1111111");
1360  absl::Cord b("aaaaaa2222222");
1361  MaybeHarden(a);
1362  a = "cccccc";
1363  b = "cccccc";
1364  EXPECT_EQ(a, b);
1365  EXPECT_FALSE(a < b);
1366 
1367  a = "aaaa";
1368  b = "bbbbb";
1369  a = "";
1370  b = "";
1371  EXPECT_EQ(a, b);
1372  EXPECT_FALSE(a < b);
1373 }
1374 
1375 // Test CompareTo() and ComparePrefix() against string and substring
1376 // comparison methods from basic_string.
1377 static void TestCompare(const absl::Cord& c, const absl::Cord& d,
1378  RandomEngine* rng) {
1379  typedef std::basic_string<uint8_t> ustring;
1380  ustring cs(reinterpret_cast<const uint8_t*>(std::string(c).data()), c.size());
1381  ustring ds(reinterpret_cast<const uint8_t*>(std::string(d).data()), d.size());
1382  // ustring comparison is ideal because we expect Cord comparisons to be
1383  // based on unsigned byte comparisons regardless of whether char is signed.
1384  int expected = sign(cs.compare(ds));
1385  EXPECT_EQ(expected, sign(c.Compare(d))) << c << ", " << d;
1386 }
1387 
1388 TEST_P(CordTest, CompareComparisonIsUnsigned) {
1389  RandomEngine rng(GTEST_FLAG_GET(random_seed));
1390  std::uniform_int_distribution<uint32_t> uniform_uint8(0, 255);
1391  char x = static_cast<char>(uniform_uint8(rng));
1392  TestCompare(
1394  absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x ^ 0x80)), &rng);
1395 }
1396 
1397 TEST_P(CordTest, CompareRandomComparisons) {
1398  const int kIters = 5000;
1399  RandomEngine rng(GTEST_FLAG_GET(random_seed));
1400 
1401  int n = GetUniformRandomUpTo(&rng, 5000);
1403  absl::Cord("ant"),
1404  absl::Cord("elephant"),
1405  absl::Cord("giraffe"),
1407  GetUniformRandomUpTo(&rng, 100))),
1408  absl::Cord(""),
1409  absl::Cord("x"),
1410  absl::Cord("A"),
1411  absl::Cord("B"),
1412  absl::Cord("C")};
1413  for (int i = 0; i < kIters; i++) {
1414  absl::Cord c, d;
1415  for (int j = 0; j < (i % 7) + 1; j++) {
1416  c.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
1417  d.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
1418  }
1419  std::bernoulli_distribution coin_flip(0.5);
1420  MaybeHarden(c);
1421  MaybeHarden(d);
1422  TestCompare(coin_flip(rng) ? c : absl::Cord(std::string(c)),
1423  coin_flip(rng) ? d : absl::Cord(std::string(d)), &rng);
1424  }
1425 }
1426 
1427 template <typename T1, typename T2>
1428 void CompareOperators() {
1429  const T1 a("a");
1430  const T2 b("b");
1431 
1432  EXPECT_TRUE(a == a);
1433  // For pointer type (i.e. `const char*`), operator== compares the address
1434  // instead of the string, so `a == const char*("a")` isn't necessarily true.
1437  EXPECT_FALSE(a == b);
1438 
1439  EXPECT_TRUE(a != b);
1440  EXPECT_FALSE(a != a);
1441 
1442  EXPECT_TRUE(a < b);
1443  EXPECT_FALSE(b < a);
1444 
1445  EXPECT_TRUE(b > a);
1446  EXPECT_FALSE(a > b);
1447 
1448  EXPECT_TRUE(a >= a);
1449  EXPECT_TRUE(b >= a);
1450  EXPECT_FALSE(a >= b);
1451 
1452  EXPECT_TRUE(a <= a);
1453  EXPECT_TRUE(a <= b);
1454  EXPECT_FALSE(b <= a);
1455 }
1456 
1457 TEST_P(CordTest, ComparisonOperators_Cord_Cord) {
1458  CompareOperators<absl::Cord, absl::Cord>();
1459 }
1460 
1461 TEST_P(CordTest, ComparisonOperators_Cord_StringPiece) {
1462  CompareOperators<absl::Cord, absl::string_view>();
1463 }
1464 
1465 TEST_P(CordTest, ComparisonOperators_StringPiece_Cord) {
1466  CompareOperators<absl::string_view, absl::Cord>();
1467 }
1468 
1469 TEST_P(CordTest, ComparisonOperators_Cord_string) {
1470  CompareOperators<absl::Cord, std::string>();
1471 }
1472 
1473 TEST_P(CordTest, ComparisonOperators_string_Cord) {
1474  CompareOperators<std::string, absl::Cord>();
1475 }
1476 
1477 TEST_P(CordTest, ComparisonOperators_stdstring_Cord) {
1478  CompareOperators<std::string, absl::Cord>();
1479 }
1480 
1481 TEST_P(CordTest, ComparisonOperators_Cord_stdstring) {
1482  CompareOperators<absl::Cord, std::string>();
1483 }
1484 
1485 TEST_P(CordTest, ComparisonOperators_charstar_Cord) {
1486  CompareOperators<const char*, absl::Cord>();
1487 }
1488 
1489 TEST_P(CordTest, ComparisonOperators_Cord_charstar) {
1490  CompareOperators<absl::Cord, const char*>();
1491 }
1492 
1493 TEST_P(CordTest, ConstructFromExternalReleaserInvoked) {
1494  // Empty external memory means the releaser should be called immediately.
1495  {
1496  bool invoked = false;
1497  auto releaser = [&invoked](absl::string_view) { invoked = true; };
1498  {
1499  auto c = absl::MakeCordFromExternal("", releaser);
1500  EXPECT_TRUE(invoked);
1501  }
1502  }
1503 
1504  // If the size of the data is small enough, a future constructor
1505  // implementation may copy the bytes and immediately invoke the releaser
1506  // instead of creating an external node. We make a large dummy std::string to
1507  // make this test independent of such an optimization.
1508  std::string large_dummy(2048, 'c');
1509  {
1510  bool invoked = false;
1511  auto releaser = [&invoked](absl::string_view) { invoked = true; };
1512  {
1513  auto c = absl::MakeCordFromExternal(large_dummy, releaser);
1514  EXPECT_FALSE(invoked);
1515  }
1516  EXPECT_TRUE(invoked);
1517  }
1518 
1519  {
1520  bool invoked = false;
1521  auto releaser = [&invoked](absl::string_view) { invoked = true; };
1522  {
1523  absl::Cord copy;
1524  {
1525  auto c = absl::MakeCordFromExternal(large_dummy, releaser);
1526  copy = c;
1527  EXPECT_FALSE(invoked);
1528  }
1529  EXPECT_FALSE(invoked);
1530  }
1531  EXPECT_TRUE(invoked);
1532  }
1533 }
1534 
1535 TEST_P(CordTest, ConstructFromExternalCompareContents) {
1536  RandomEngine rng(GTEST_FLAG_GET(random_seed));
1537 
1538  for (int length = 1; length <= 2048; length *= 2) {
1540  auto* external = new std::string(data);
1541  auto cord =
1542  absl::MakeCordFromExternal(*external, [external](absl::string_view sv) {
1543  EXPECT_EQ(external->data(), sv.data());
1544  EXPECT_EQ(external->size(), sv.size());
1545  delete external;
1546  });
1547  MaybeHarden(cord);
1548  EXPECT_EQ(data, cord);
1549  }
1550 }
1551 
1552 TEST_P(CordTest, ConstructFromExternalLargeReleaser) {
1553  RandomEngine rng(GTEST_FLAG_GET(random_seed));
1554  constexpr size_t kLength = 256;
1555  std::string data = RandomLowercaseString(&rng, kLength);
1556  std::array<char, kLength> data_array;
1557  for (size_t i = 0; i < kLength; ++i) data_array[i] = data[i];
1558  bool invoked = false;
1559  auto releaser = [data_array, &invoked](absl::string_view data) {
1560  EXPECT_EQ(data, absl::string_view(data_array.data(), data_array.size()));
1561  invoked = true;
1562  };
1563  (void)MaybeHardened(absl::MakeCordFromExternal(data, releaser));
1564  EXPECT_TRUE(invoked);
1565 }
1566 
1567 TEST_P(CordTest, ConstructFromExternalFunctionPointerReleaser) {
1568  static absl::string_view data("hello world");
1569  static bool invoked;
1570  auto* releaser =
1571  static_cast<void (*)(absl::string_view)>([](absl::string_view sv) {
1572  EXPECT_EQ(data, sv);
1573  invoked = true;
1574  });
1575  invoked = false;
1576  (void)MaybeHardened(absl::MakeCordFromExternal(data, releaser));
1577  EXPECT_TRUE(invoked);
1578 
1579  invoked = false;
1580  (void)MaybeHardened(absl::MakeCordFromExternal(data, *releaser));
1581  EXPECT_TRUE(invoked);
1582 }
1583 
1584 TEST_P(CordTest, ConstructFromExternalMoveOnlyReleaser) {
1585  struct Releaser {
1586  explicit Releaser(bool* invoked) : invoked(invoked) {}
1587  Releaser(Releaser&& other) noexcept : invoked(other.invoked) {}
1588  void operator()(absl::string_view) const { *invoked = true; }
1589 
1590  bool* invoked;
1591  };
1592 
1593  bool invoked = false;
1594  (void)MaybeHardened(absl::MakeCordFromExternal("dummy", Releaser(&invoked)));
1595  EXPECT_TRUE(invoked);
1596 }
1597 
1598 TEST_P(CordTest, ConstructFromExternalNoArgLambda) {
1599  bool invoked = false;
1600  (void)MaybeHardened(
1601  absl::MakeCordFromExternal("dummy", [&invoked]() { invoked = true; }));
1602  EXPECT_TRUE(invoked);
1603 }
1604 
1605 TEST_P(CordTest, ConstructFromExternalStringViewArgLambda) {
1606  bool invoked = false;
1607  (void)MaybeHardened(absl::MakeCordFromExternal(
1608  "dummy", [&invoked](absl::string_view) { invoked = true; }));
1609  EXPECT_TRUE(invoked);
1610 }
1611 
1612 TEST_P(CordTest, ConstructFromExternalNonTrivialReleaserDestructor) {
1613  struct Releaser {
1614  explicit Releaser(bool* destroyed) : destroyed(destroyed) {}
1615  ~Releaser() { *destroyed = true; }
1616  void operator()(absl::string_view) const {}
1617 
1618  bool* destroyed;
1619  };
1620 
1621  bool destroyed = false;
1622  Releaser releaser(&destroyed);
1623  (void)MaybeHardened(absl::MakeCordFromExternal("dummy", releaser));
1624  EXPECT_TRUE(destroyed);
1625 }
1626 
1627 TEST_P(CordTest, ConstructFromExternalReferenceQualifierOverloads) {
1628  enum InvokedAs { kMissing, kLValue, kRValue };
1629  enum CopiedAs { kNone, kMove, kCopy };
1630  struct Tracker {
1631  CopiedAs copied_as = kNone;
1632  InvokedAs invoked_as = kMissing;
1633 
1634  void Record(InvokedAs rhs) {
1635  ASSERT_EQ(invoked_as, kMissing);
1636  invoked_as = rhs;
1637  }
1638 
1639  void Record(CopiedAs rhs) {
1640  if (copied_as == kNone || rhs == kCopy) copied_as = rhs;
1641  }
1642  } tracker;
1643 
1644  class Releaser {
1645  public:
1646  explicit Releaser(Tracker* tracker) : tr_(tracker) { *tracker = Tracker(); }
1647  Releaser(Releaser&& rhs) : tr_(rhs.tr_) { tr_->Record(kMove); }
1648  Releaser(const Releaser& rhs) : tr_(rhs.tr_) { tr_->Record(kCopy); }
1649 
1650  void operator()(absl::string_view) & { tr_->Record(kLValue); }
1651  void operator()(absl::string_view) && { tr_->Record(kRValue); }
1652 
1653  private:
1654  Tracker* tr_;
1655  };
1656 
1657  const Releaser releaser1(&tracker);
1658  (void)MaybeHardened(absl::MakeCordFromExternal("", releaser1));
1659  EXPECT_EQ(tracker.copied_as, kCopy);
1660  EXPECT_EQ(tracker.invoked_as, kRValue);
1661 
1662  const Releaser releaser2(&tracker);
1663  (void)MaybeHardened(absl::MakeCordFromExternal("", releaser2));
1664  EXPECT_EQ(tracker.copied_as, kCopy);
1665  EXPECT_EQ(tracker.invoked_as, kRValue);
1666 
1667  Releaser releaser3(&tracker);
1668  (void)MaybeHardened(absl::MakeCordFromExternal("", std::move(releaser3)));
1669  EXPECT_EQ(tracker.copied_as, kMove);
1670  EXPECT_EQ(tracker.invoked_as, kRValue);
1671 
1672  Releaser releaser4(&tracker);
1673  (void)MaybeHardened(absl::MakeCordFromExternal("dummy", releaser4));
1674  EXPECT_EQ(tracker.copied_as, kCopy);
1675  EXPECT_EQ(tracker.invoked_as, kRValue);
1676 
1677  const Releaser releaser5(&tracker);
1678  (void)MaybeHardened(absl::MakeCordFromExternal("dummy", releaser5));
1679  EXPECT_EQ(tracker.copied_as, kCopy);
1680  EXPECT_EQ(tracker.invoked_as, kRValue);
1681 
1682  Releaser releaser6(&tracker);
1683  (void)MaybeHardened(absl::MakeCordFromExternal("foo", std::move(releaser6)));
1684  EXPECT_EQ(tracker.copied_as, kMove);
1685  EXPECT_EQ(tracker.invoked_as, kRValue);
1686 }
1687 
1688 TEST_P(CordTest, ExternalMemoryBasicUsage) {
1689  static const char* strings[] = {"", "hello", "there"};
1690  for (const char* str : strings) {
1691  absl::Cord dst("(prefix)");
1692  MaybeHarden(dst);
1694  MaybeHarden(dst);
1695  dst.Append("(suffix)");
1696  EXPECT_EQ((std::string("(prefix)") + str + std::string("(suffix)")),
1697  std::string(dst));
1698  }
1699 }
1700 
1701 TEST_P(CordTest, ExternalMemoryRemovePrefixSuffix) {
1702  // Exhaustively try all sub-strings.
1703  absl::Cord cord = MakeComposite();
1704  std::string s = std::string(cord);
1705  for (int offset = 0; offset <= s.size(); offset++) {
1706  for (int length = 0; length <= s.size() - offset; length++) {
1707  absl::Cord result(cord);
1708  MaybeHarden(result);
1709  result.RemovePrefix(offset);
1710  MaybeHarden(result);
1711  result.RemoveSuffix(result.size() - length);
1713  << offset << " " << length;
1714  }
1715  }
1716 }
1717 
1718 TEST_P(CordTest, ExternalMemoryGet) {
1719  absl::Cord cord("hello");
1720  AddExternalMemory(" world!", &cord);
1721  MaybeHarden(cord);
1722  AddExternalMemory(" how are ", &cord);
1723  cord.Append(" you?");
1724  MaybeHarden(cord);
1725  std::string s = std::string(cord);
1726  for (int i = 0; i < s.size(); i++) {
1727  EXPECT_EQ(s[i], cord[i]);
1728  }
1729 }
1730 
1731 // CordMemoryUsage tests verify the correctness of the EstimatedMemoryUsage()
1732 // We use whiteboxed expectations based on our knowledge of the layout and size
1733 // of empty and inlined cords, and flat nodes.
1734 
1736 
1737 // Creates a cord of `n` `c` values, making sure no string stealing occurs.
1738 absl::Cord MakeCord(size_t n, char c) {
1739  const std::string s(n, c);
1740  return absl::Cord(s);
1741 }
1742 
1743 TEST(CordTest, CordMemoryUsageEmpty) {
1744  absl::Cord cord;
1745  EXPECT_EQ(sizeof(absl::Cord), cord.EstimatedMemoryUsage());
1746  EXPECT_EQ(sizeof(absl::Cord), cord.EstimatedMemoryUsage(kFairShare));
1747 }
1748 
1749 TEST(CordTest, CordMemoryUsageInlined) {
1750  absl::Cord a("hello");
1751  EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
1752  EXPECT_EQ(a.EstimatedMemoryUsage(kFairShare), sizeof(absl::Cord));
1753 }
1754 
1755 TEST(CordTest, CordMemoryUsageExternalMemory) {
1756  absl::Cord cord;
1757  AddExternalMemory(std::string(1000, 'x'), &cord);
1758  const size_t expected =
1759  sizeof(absl::Cord) + 1000 + sizeof(CordRepExternal) + sizeof(intptr_t);
1760  EXPECT_EQ(cord.EstimatedMemoryUsage(), expected);
1761  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare), expected);
1762 }
1763 
1764 TEST(CordTest, CordMemoryUsageFlat) {
1765  absl::Cord cord = MakeCord(1000, 'a');
1766  const size_t flat_size =
1768  EXPECT_EQ(cord.EstimatedMemoryUsage(), sizeof(absl::Cord) + flat_size);
1769  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
1770  sizeof(absl::Cord) + flat_size);
1771 }
1772 
1773 TEST(CordTest, CordMemoryUsageSubStringSharedFlat) {
1774  absl::Cord flat = MakeCord(2000, 'a');
1775  const size_t flat_size =
1777  absl::Cord cord = flat.Subcord(500, 1000);
1779  sizeof(absl::Cord) + sizeof(CordRepSubstring) + flat_size);
1780  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
1781  sizeof(absl::Cord) + sizeof(CordRepSubstring) + flat_size / 2);
1782 }
1783 
1784 TEST(CordTest, CordMemoryUsageFlatShared) {
1785  absl::Cord shared = MakeCord(1000, 'a');
1786  absl::Cord cord(shared);
1787  const size_t flat_size =
1789  EXPECT_EQ(cord.EstimatedMemoryUsage(), sizeof(absl::Cord) + flat_size);
1790  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
1791  sizeof(absl::Cord) + flat_size / 2);
1792 }
1793 
1794 TEST(CordTest, CordMemoryUsageFlatHardenedAndShared) {
1795  absl::Cord shared = MakeCord(1000, 'a');
1796  absl::Cord cord(shared);
1797  const size_t flat_size =
1799  cord.SetExpectedChecksum(1);
1801  sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size);
1802  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
1803  sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size / 2);
1804 
1805  absl::Cord cord2(cord);
1806  EXPECT_EQ(cord2.EstimatedMemoryUsage(),
1807  sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size);
1808  EXPECT_EQ(cord2.EstimatedMemoryUsage(kFairShare),
1809  sizeof(absl::Cord) + (sizeof(CordRepCrc) + flat_size / 2) / 2);
1810 }
1811 
1812 TEST(CordTest, CordMemoryUsageBTree) {
1813  absl::Cord cord1;
1814  size_t flats1_size = 0;
1815  absl::Cord flats1[4] = {MakeCord(1000, 'a'), MakeCord(1100, 'a'),
1816  MakeCord(1200, 'a'), MakeCord(1300, 'a')};
1817  for (absl::Cord flat : flats1) {
1818  flats1_size += absl::CordTestPeer::Tree(flat)->flat()->AllocatedSize();
1819  cord1.Append(std::move(flat));
1820  }
1821 
1822  // Make sure the created cord is a BTREE tree. Under some builds such as
1823  // windows DLL, we may have ODR like effects on the flag, meaning the DLL
1824  // code will run with the picked up default.
1825  if (!absl::CordTestPeer::Tree(cord1)->IsBtree()) {
1826  ABSL_RAW_LOG(WARNING, "Cord library code not respecting btree flag");
1827  return;
1828  }
1829 
1830  size_t rep1_size = sizeof(CordRepBtree) + flats1_size;
1831  size_t rep1_shared_size = sizeof(CordRepBtree) + flats1_size / 2;
1832 
1833  EXPECT_EQ(cord1.EstimatedMemoryUsage(), sizeof(absl::Cord) + rep1_size);
1834  EXPECT_EQ(cord1.EstimatedMemoryUsage(kFairShare),
1835  sizeof(absl::Cord) + rep1_shared_size);
1836 
1837  absl::Cord cord2;
1838  size_t flats2_size = 0;
1839  absl::Cord flats2[4] = {MakeCord(600, 'a'), MakeCord(700, 'a'),
1840  MakeCord(800, 'a'), MakeCord(900, 'a')};
1841  for (absl::Cord& flat : flats2) {
1842  flats2_size += absl::CordTestPeer::Tree(flat)->flat()->AllocatedSize();
1843  cord2.Append(std::move(flat));
1844  }
1845  size_t rep2_size = sizeof(CordRepBtree) + flats2_size;
1846 
1847  EXPECT_EQ(cord2.EstimatedMemoryUsage(), sizeof(absl::Cord) + rep2_size);
1848  EXPECT_EQ(cord2.EstimatedMemoryUsage(kFairShare),
1849  sizeof(absl::Cord) + rep2_size);
1850 
1851  absl::Cord cord(cord1);
1852  cord.Append(std::move(cord2));
1853 
1855  sizeof(absl::Cord) + sizeof(CordRepBtree) + rep1_size + rep2_size);
1856  EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
1857  sizeof(absl::Cord) + sizeof(CordRepBtree) + rep1_shared_size / 2 +
1858  rep2_size);
1859 }
1860 
1861 // Regtest for a change that had to be rolled back because it expanded out
1862 // of the InlineRep too soon, which was observable through MemoryUsage().
1863 TEST_P(CordTest, CordMemoryUsageInlineRep) {
1864  constexpr size_t kMaxInline = 15; // Cord::InlineRep::N
1865  const std::string small_string(kMaxInline, 'x');
1866  absl::Cord c1(small_string);
1867 
1868  absl::Cord c2;
1869  c2.Append(small_string);
1870  EXPECT_EQ(c1, c2);
1871  EXPECT_EQ(c1.EstimatedMemoryUsage(), c2.EstimatedMemoryUsage());
1872 }
1873 
1874 } // namespace
1875 
1876 // Regtest for 7510292 (fix a bug introduced by 7465150)
1877 TEST_P(CordTest, Concat_Append) {
1878  // Create a rep of type CONCAT
1879  absl::Cord s1("foobarbarbarbarbar");
1880  MaybeHarden(s1);
1881  s1.Append("abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg");
1882  size_t size = s1.size();
1883 
1884  // Create a copy of s1 and append to it.
1885  absl::Cord s2 = s1;
1886  MaybeHarden(s2);
1887  s2.Append("x");
1888 
1889  // 7465150 modifies s1 when it shouldn't.
1890  EXPECT_EQ(s1.size(), size);
1891  EXPECT_EQ(s2.size(), size + 1);
1892 }
1893 
1894 TEST_P(CordTest, DiabolicalGrowth) {
1895  // This test exercises a diabolical Append(<one char>) on a cord, making the
1896  // cord shared before each Append call resulting in a terribly fragmented
1897  // resulting cord.
1898  // TODO(b/183983616): Apply some minimum compaction when copying a shared
1899  // source cord into a mutable copy for updates in CordRepRing.
1900  RandomEngine rng(GTEST_FLAG_GET(random_seed));
1901  const std::string expected = RandomLowercaseString(&rng, 5000);
1902  absl::Cord cord;
1903  for (char c : expected) {
1904  absl::Cord shared(cord);
1905  cord.Append(absl::string_view(&c, 1));
1906  MaybeHarden(cord);
1907  }
1909  absl::CopyCordToString(cord, &value);
1910  EXPECT_EQ(value, expected);
1911  ABSL_RAW_LOG(INFO, "Diabolical size allocated = %zu",
1912  cord.EstimatedMemoryUsage());
1913 }
1914 
1915 // The following tests check support for >4GB cords in 64-bit binaries, and
1916 // 2GB-4GB cords in 32-bit binaries. This function returns the large cord size
1917 // that's appropriate for the binary.
1918 
1919 // Construct a huge cord with the specified valid prefix.
1921  absl::Cord cord;
1922  if (sizeof(size_t) > 4) {
1923  // In 64-bit binaries, test 64-bit Cord support.
1924  const size_t size =
1925  static_cast<size_t>(std::numeric_limits<uint32_t>::max()) + 314;
1927  absl::string_view(prefix.data(), size),
1928  [](absl::string_view s) { DoNothing(s, nullptr); }));
1929  } else {
1930  // Cords are limited to 32-bit lengths in 32-bit binaries. The following
1931  // tests check for use of "signed int" to represent Cord length/offset.
1932  // However absl::string_view does not allow lengths >= (1u<<31), so we need
1933  // to append in two parts;
1934  const size_t s1 = (1u << 31) - 1;
1935  // For shorter cord, `Append` copies the data rather than allocating a new
1936  // node. The threshold is currently set to 511, so `s2` needs to be bigger
1937  // to not trigger the copy.
1938  const size_t s2 = 600;
1940  absl::string_view(prefix.data(), s1),
1941  [](absl::string_view s) { DoNothing(s, nullptr); }));
1943  absl::string_view("", s2),
1944  [](absl::string_view s) { DoNothing(s, nullptr); }));
1945  }
1946  return cord;
1947 }
1948 
1949 TEST_P(CordTest, HugeCord) {
1950  absl::Cord cord = MakeHuge("huge cord");
1951  MaybeHarden(cord);
1952 
1953  const size_t acceptable_delta =
1954  100 + (UseCrc() ? sizeof(absl::cord_internal::CordRepCrc) : 0);
1955  EXPECT_LE(cord.size(), cord.EstimatedMemoryUsage());
1956  EXPECT_GE(cord.size() + acceptable_delta, cord.EstimatedMemoryUsage());
1957 }
1958 
1959 // Tests that Append() works ok when handed a self reference
1960 TEST_P(CordTest, AppendSelf) {
1961  // We run the test until data is ~16K
1962  // This guarantees it covers small, medium and large data.
1963  std::string control_data = "Abc";
1964  absl::Cord data(control_data);
1965  while (control_data.length() < 0x4000) {
1966  MaybeHarden(data);
1967  data.Append(data);
1968  control_data.append(control_data);
1969  ASSERT_EQ(control_data, data);
1970  }
1971 }
1972 
1973 TEST_P(CordTest, MakeFragmentedCordFromInitializerList) {
1974  absl::Cord fragmented =
1975  absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
1976 
1977  MaybeHarden(fragmented);
1978 
1979  EXPECT_EQ("A fragmented Cord", fragmented);
1980 
1981  auto chunk_it = fragmented.chunk_begin();
1982 
1983  ASSERT_TRUE(chunk_it != fragmented.chunk_end());
1984  EXPECT_EQ("A ", *chunk_it);
1985 
1986  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
1987  EXPECT_EQ("fragmented ", *chunk_it);
1988 
1989  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
1990  EXPECT_EQ("Cord", *chunk_it);
1991 
1992  ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
1993 }
1994 
1995 TEST_P(CordTest, MakeFragmentedCordFromVector) {
1996  std::vector<absl::string_view> chunks = {"A ", "fragmented ", "Cord"};
1997  absl::Cord fragmented = absl::MakeFragmentedCord(chunks);
1998 
1999  MaybeHarden(fragmented);
2000 
2001  EXPECT_EQ("A fragmented Cord", fragmented);
2002 
2003  auto chunk_it = fragmented.chunk_begin();
2004 
2005  ASSERT_TRUE(chunk_it != fragmented.chunk_end());
2006  EXPECT_EQ("A ", *chunk_it);
2007 
2008  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
2009  EXPECT_EQ("fragmented ", *chunk_it);
2010 
2011  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
2012  EXPECT_EQ("Cord", *chunk_it);
2013 
2014  ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
2015 }
2016 
2017 TEST_P(CordTest, CordChunkIteratorTraits) {
2019  "");
2021 
2022  // Move semantics to satisfy swappable via std::swap
2024  "");
2026 
2027  static_assert(
2028  std::is_same<
2029  std::iterator_traits<absl::Cord::ChunkIterator>::iterator_category,
2030  std::input_iterator_tag>::value,
2031  "");
2032  static_assert(
2035  "");
2036  static_assert(
2037  std::is_same<
2038  std::iterator_traits<absl::Cord::ChunkIterator>::difference_type,
2039  ptrdiff_t>::value,
2040  "");
2041  static_assert(
2042  std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::pointer,
2043  const absl::string_view*>::value,
2044  "");
2045  static_assert(
2046  std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::reference,
2048  "");
2049 }
2050 
2051 static void VerifyChunkIterator(const absl::Cord& cord,
2052  size_t expected_chunks) {
2053  EXPECT_EQ(cord.chunk_begin() == cord.chunk_end(), cord.empty()) << cord;
2054  EXPECT_EQ(cord.chunk_begin() != cord.chunk_end(), !cord.empty());
2055 
2057  EXPECT_EQ(range.begin() == range.end(), cord.empty());
2058  EXPECT_EQ(range.begin() != range.end(), !cord.empty());
2059 
2060  std::string content(cord);
2061  size_t pos = 0;
2062  auto pre_iter = cord.chunk_begin(), post_iter = cord.chunk_begin();
2063  size_t n_chunks = 0;
2064  while (pre_iter != cord.chunk_end() && post_iter != cord.chunk_end()) {
2065  EXPECT_FALSE(pre_iter == cord.chunk_end()); // NOLINT: explicitly test ==
2066  EXPECT_FALSE(post_iter == cord.chunk_end()); // NOLINT
2067 
2068  EXPECT_EQ(pre_iter, post_iter);
2069  EXPECT_EQ(*pre_iter, *post_iter);
2070 
2071  EXPECT_EQ(pre_iter->data(), (*pre_iter).data());
2072  EXPECT_EQ(pre_iter->size(), (*pre_iter).size());
2073 
2074  absl::string_view chunk = *pre_iter;
2075  EXPECT_FALSE(chunk.empty());
2076  EXPECT_LE(pos + chunk.size(), content.size());
2077  EXPECT_EQ(absl::string_view(content.c_str() + pos, chunk.size()), chunk);
2078 
2079  int n_equal_iterators = 0;
2080  for (absl::Cord::ChunkIterator it = range.begin(); it != range.end();
2081  ++it) {
2082  n_equal_iterators += static_cast<int>(it == pre_iter);
2083  }
2084  EXPECT_EQ(n_equal_iterators, 1);
2085 
2086  ++pre_iter;
2087  EXPECT_EQ(*post_iter++, chunk);
2088 
2089  pos += chunk.size();
2090  ++n_chunks;
2091  }
2092  EXPECT_EQ(expected_chunks, n_chunks);
2093  EXPECT_EQ(pos, content.size());
2094  EXPECT_TRUE(pre_iter == cord.chunk_end()); // NOLINT: explicitly test ==
2095  EXPECT_TRUE(post_iter == cord.chunk_end()); // NOLINT
2096 }
2097 
2098 TEST_P(CordTest, CordChunkIteratorOperations) {
2099  absl::Cord empty_cord;
2100  VerifyChunkIterator(empty_cord, 0);
2101 
2102  absl::Cord small_buffer_cord("small cord");
2103  MaybeHarden(small_buffer_cord);
2104  VerifyChunkIterator(small_buffer_cord, 1);
2105 
2106  absl::Cord flat_node_cord("larger than small buffer optimization");
2107  MaybeHarden(flat_node_cord);
2108  VerifyChunkIterator(flat_node_cord, 1);
2109 
2111  {"a ", "small ", "fragmented ", "cord ", "for ",
2112  "testing ", "chunk ", "iterations."})),
2113  8);
2114 
2115  absl::Cord reused_nodes_cord(std::string(40, 'c'));
2116  reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'b')));
2117  MaybeHarden(reused_nodes_cord);
2118  reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'a')));
2119  size_t expected_chunks = 3;
2120  for (int i = 0; i < 8; ++i) {
2121  reused_nodes_cord.Prepend(reused_nodes_cord);
2122  MaybeHarden(reused_nodes_cord);
2123  expected_chunks *= 2;
2124  VerifyChunkIterator(reused_nodes_cord, expected_chunks);
2125  }
2126 
2127  RandomEngine rng(GTEST_FLAG_GET(random_seed));
2128  absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
2129  absl::Cord subcords;
2130  for (int i = 0; i < 128; ++i) subcords.Prepend(flat_cord.Subcord(i, 128));
2131  VerifyChunkIterator(subcords, 128);
2132 }
2133 
2134 
2135 TEST_P(CordTest, AdvanceAndReadOnDataEdge) {
2136  RandomEngine rng(GTEST_FLAG_GET(random_seed));
2137  const std::string data = RandomLowercaseString(&rng, 2000);
2138  for (bool as_flat : {true, false}) {
2139  SCOPED_TRACE(as_flat ? "Flat" : "External");
2140 
2141  absl::Cord cord =
2142  as_flat ? absl::Cord(data)
2144  auto it = cord.Chars().begin();
2145 #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
2146  EXPECT_DEATH_IF_SUPPORTED(cord.AdvanceAndRead(&it, 2001), ".*");
2147 #endif
2148 
2149  it = cord.Chars().begin();
2150  absl::Cord frag = cord.AdvanceAndRead(&it, 2000);
2151  EXPECT_EQ(frag, data);
2152  EXPECT_TRUE(it == cord.Chars().end());
2153 
2154  it = cord.Chars().begin();
2155  frag = cord.AdvanceAndRead(&it, 200);
2156  EXPECT_EQ(frag, data.substr(0, 200));
2157  EXPECT_FALSE(it == cord.Chars().end());
2158 
2159  frag = cord.AdvanceAndRead(&it, 1500);
2160  EXPECT_EQ(frag, data.substr(200, 1500));
2161  EXPECT_FALSE(it == cord.Chars().end());
2162 
2163  frag = cord.AdvanceAndRead(&it, 300);
2164  EXPECT_EQ(frag, data.substr(1700, 300));
2165  EXPECT_TRUE(it == cord.Chars().end());
2166  }
2167 }
2168 
2169 TEST_P(CordTest, AdvanceAndReadOnSubstringDataEdge) {
2170  RandomEngine rng(GTEST_FLAG_GET(random_seed));
2171  const std::string data = RandomLowercaseString(&rng, 2500);
2172  for (bool as_flat : {true, false}) {
2173  SCOPED_TRACE(as_flat ? "Flat" : "External");
2174 
2175  absl::Cord cord =
2176  as_flat ? absl::Cord(data)
2178  cord = cord.Subcord(200, 2000);
2179  const std::string substr = data.substr(200, 2000);
2180 
2181  auto it = cord.Chars().begin();
2182 #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
2183  EXPECT_DEATH_IF_SUPPORTED(cord.AdvanceAndRead(&it, 2001), ".*");
2184 #endif
2185 
2186  it = cord.Chars().begin();
2187  absl::Cord frag = cord.AdvanceAndRead(&it, 2000);
2188  EXPECT_EQ(frag, substr);
2189  EXPECT_TRUE(it == cord.Chars().end());
2190 
2191  it = cord.Chars().begin();
2192  frag = cord.AdvanceAndRead(&it, 200);
2193  EXPECT_EQ(frag, substr.substr(0, 200));
2194  EXPECT_FALSE(it == cord.Chars().end());
2195 
2196  frag = cord.AdvanceAndRead(&it, 1500);
2197  EXPECT_EQ(frag, substr.substr(200, 1500));
2198  EXPECT_FALSE(it == cord.Chars().end());
2199 
2200  frag = cord.AdvanceAndRead(&it, 300);
2201  EXPECT_EQ(frag, substr.substr(1700, 300));
2202  EXPECT_TRUE(it == cord.Chars().end());
2203  }
2204 }
2205 
2206 TEST_P(CordTest, CharIteratorTraits) {
2208  "");
2210 
2211  // Move semantics to satisfy swappable via std::swap
2213  "");
2215 
2216  static_assert(
2217  std::is_same<
2218  std::iterator_traits<absl::Cord::CharIterator>::iterator_category,
2219  std::input_iterator_tag>::value,
2220  "");
2221  static_assert(
2223  char>::value,
2224  "");
2225  static_assert(
2226  std::is_same<
2227  std::iterator_traits<absl::Cord::CharIterator>::difference_type,
2228  ptrdiff_t>::value,
2229  "");
2230  static_assert(
2231  std::is_same<std::iterator_traits<absl::Cord::CharIterator>::pointer,
2232  const char*>::value,
2233  "");
2234  static_assert(
2235  std::is_same<std::iterator_traits<absl::Cord::CharIterator>::reference,
2236  const char&>::value,
2237  "");
2238 }
2239 
2240 static void VerifyCharIterator(const absl::Cord& cord) {
2241  EXPECT_EQ(cord.char_begin() == cord.char_end(), cord.empty());
2242  EXPECT_EQ(cord.char_begin() != cord.char_end(), !cord.empty());
2243 
2245  EXPECT_EQ(range.begin() == range.end(), cord.empty());
2246  EXPECT_EQ(range.begin() != range.end(), !cord.empty());
2247 
2248  size_t i = 0;
2249  absl::Cord::CharIterator pre_iter = cord.char_begin();
2250  absl::Cord::CharIterator post_iter = cord.char_begin();
2251  std::string content(cord);
2252  while (pre_iter != cord.char_end() && post_iter != cord.char_end()) {
2253  EXPECT_FALSE(pre_iter == cord.char_end()); // NOLINT: explicitly test ==
2254  EXPECT_FALSE(post_iter == cord.char_end()); // NOLINT
2255 
2256  EXPECT_LT(i, cord.size());
2257  EXPECT_EQ(content[i], *pre_iter);
2258 
2259  EXPECT_EQ(pre_iter, post_iter);
2260  EXPECT_EQ(*pre_iter, *post_iter);
2261  EXPECT_EQ(&*pre_iter, &*post_iter);
2262 
2263  EXPECT_EQ(&*pre_iter, pre_iter.operator->());
2264 
2265  const char* character_address = &*pre_iter;
2266  absl::Cord::CharIterator copy = pre_iter;
2267  ++copy;
2268  EXPECT_EQ(character_address, &*pre_iter);
2269 
2270  int n_equal_iterators = 0;
2271  for (absl::Cord::CharIterator it = range.begin(); it != range.end(); ++it) {
2272  n_equal_iterators += static_cast<int>(it == pre_iter);
2273  }
2274  EXPECT_EQ(n_equal_iterators, 1);
2275 
2276  absl::Cord::CharIterator advance_iter = range.begin();
2277  absl::Cord::Advance(&advance_iter, i);
2278  EXPECT_EQ(pre_iter, advance_iter);
2279 
2280  advance_iter = range.begin();
2281  EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, i), cord.Subcord(0, i));
2282  EXPECT_EQ(pre_iter, advance_iter);
2283 
2284  advance_iter = pre_iter;
2285  absl::Cord::Advance(&advance_iter, cord.size() - i);
2286  EXPECT_EQ(range.end(), advance_iter);
2287 
2288  advance_iter = pre_iter;
2289  EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, cord.size() - i),
2290  cord.Subcord(i, cord.size() - i));
2291  EXPECT_EQ(range.end(), advance_iter);
2292 
2293  ++i;
2294  ++pre_iter;
2295  post_iter++;
2296  }
2297  EXPECT_EQ(i, cord.size());
2298  EXPECT_TRUE(pre_iter == cord.char_end()); // NOLINT: explicitly test ==
2299  EXPECT_TRUE(post_iter == cord.char_end()); // NOLINT
2300 
2301  absl::Cord::CharIterator zero_advanced_end = cord.char_end();
2302  absl::Cord::Advance(&zero_advanced_end, 0);
2303  EXPECT_EQ(zero_advanced_end, cord.char_end());
2304 
2306  for (absl::string_view chunk : cord.Chunks()) {
2307  while (!chunk.empty()) {
2309  chunk.remove_prefix(1);
2310  ++it;
2311  }
2312  }
2313 }
2314 
2315 TEST_P(CordTest, CharIteratorOperations) {
2316  absl::Cord empty_cord;
2317  VerifyCharIterator(empty_cord);
2318 
2319  absl::Cord small_buffer_cord("small cord");
2320  MaybeHarden(small_buffer_cord);
2321  VerifyCharIterator(small_buffer_cord);
2322 
2323  absl::Cord flat_node_cord("larger than small buffer optimization");
2324  MaybeHarden(flat_node_cord);
2325  VerifyCharIterator(flat_node_cord);
2326 
2327  VerifyCharIterator(MaybeHardened(
2328  absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ",
2329  "testing ", "character ", "iteration."})));
2330 
2331  absl::Cord reused_nodes_cord("ghi");
2332  reused_nodes_cord.Prepend(absl::Cord("def"));
2333  reused_nodes_cord.Prepend(absl::Cord("abc"));
2334  for (int i = 0; i < 4; ++i) {
2335  reused_nodes_cord.Prepend(reused_nodes_cord);
2336  MaybeHarden(reused_nodes_cord);
2337  VerifyCharIterator(reused_nodes_cord);
2338  }
2339 
2340  RandomEngine rng(GTEST_FLAG_GET(random_seed));
2341  absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
2342  absl::Cord subcords;
2343  for (int i = 0; i < 4; ++i) {
2344  subcords.Prepend(flat_cord.Subcord(16 * i, 128));
2345  MaybeHarden(subcords);
2346  }
2347  VerifyCharIterator(subcords);
2348 }
2349 
2350 TEST_P(CordTest, CharIteratorAdvanceAndRead) {
2351  // Create a Cord holding 6 flats of 2500 bytes each, and then iterate over it
2352  // reading 150, 1500, 2500 and 3000 bytes. This will result in all possible
2353  // partial, full and straddled read combinations including reads below
2354  // kMaxBytesToCopy. b/197776822 surfaced a bug for a specific partial, small
2355  // read 'at end' on Cord which caused a failure on attempting to read past the
2356  // end in CordRepBtreeReader which was not covered by any existing test.
2357  constexpr int kBlocks = 6;
2358  constexpr size_t kBlockSize = 2500;
2359  constexpr size_t kChunkSize1 = 1500;
2360  constexpr size_t kChunkSize2 = 2500;
2361  constexpr size_t kChunkSize3 = 3000;
2362  constexpr size_t kChunkSize4 = 150;
2363  RandomEngine rng;
2364  std::string data = RandomLowercaseString(&rng, kBlocks * kBlockSize);
2365  absl::Cord cord;
2366  for (int i = 0; i < kBlocks; ++i) {
2367  const std::string block = data.substr(i * kBlockSize, kBlockSize);
2368  cord.Append(absl::Cord(block));
2369  }
2370 
2371  MaybeHarden(cord);
2372 
2373  for (size_t chunk_size :
2374  {kChunkSize1, kChunkSize2, kChunkSize3, kChunkSize4}) {
2376  size_t offset = 0;
2377  while (offset < data.length()) {
2378  const size_t n = std::min<size_t>(data.length() - offset, chunk_size);
2379  absl::Cord chunk = cord.AdvanceAndRead(&it, n);
2380  ASSERT_EQ(chunk.size(), n);
2381  ASSERT_EQ(chunk.Compare(data.substr(offset, n)), 0);
2382  offset += n;
2383  }
2384  }
2385 }
2386 
2387 TEST_P(CordTest, StreamingOutput) {
2388  absl::Cord c =
2389  absl::MakeFragmentedCord({"A ", "small ", "fragmented ", "Cord", "."});
2390  MaybeHarden(c);
2391  std::stringstream output;
2392  output << c;
2393  EXPECT_EQ("A small fragmented Cord.", output.str());
2394 }
2395 
2396 TEST_P(CordTest, ForEachChunk) {
2397  for (int num_elements : {1, 10, 200}) {
2399  std::vector<std::string> cord_chunks;
2400  for (int i = 0; i < num_elements; ++i) {
2401  cord_chunks.push_back(absl::StrCat("[", i, "]"));
2402  }
2403  absl::Cord c = absl::MakeFragmentedCord(cord_chunks);
2404  MaybeHarden(c);
2405 
2406  std::vector<std::string> iterated_chunks;
2408  [&iterated_chunks](absl::string_view sv) {
2409  iterated_chunks.emplace_back(sv);
2410  });
2411  EXPECT_EQ(iterated_chunks, cord_chunks);
2412  }
2413 }
2414 
2415 TEST_P(CordTest, SmallBufferAssignFromOwnData) {
2416  constexpr size_t kMaxInline = 15;
2417  std::string contents = "small buff cord";
2419  for (size_t pos = 0; pos < contents.size(); ++pos) {
2420  for (size_t count = contents.size() - pos; count > 0; --count) {
2422  MaybeHarden(c);
2423  absl::string_view flat = c.Flatten();
2424  c = flat.substr(pos, count);
2426  << "pos = " << pos << "; count = " << count;
2427  }
2428  }
2429 }
2430 
2432  absl::Cord c;
2433  absl::Format(&c, "There were %04d little %s.", 3, "pigs");
2434  EXPECT_EQ(c, "There were 0003 little pigs.");
2435  MaybeHarden(c);
2436  absl::Format(&c, "And %-3llx bad wolf!", 1);
2437  MaybeHarden(c);
2438  EXPECT_EQ(c, "There were 0003 little pigs.And 1 bad wolf!");
2439 }
2440 
2441 TEST_P(CordTest, Hardening) {
2442  absl::Cord cord("hello");
2443  MaybeHarden(cord);
2444 
2445  // These statement should abort the program in all builds modes.
2448 
2449  bool test_hardening = false;
2450  ABSL_HARDENING_ASSERT([&]() {
2451  // This only runs when ABSL_HARDENING_ASSERT is active.
2452  test_hardening = true;
2453  return true;
2454  }());
2455  if (!test_hardening) return;
2456 
2457  EXPECT_DEATH_IF_SUPPORTED(cord[5], "");
2458  EXPECT_DEATH_IF_SUPPORTED(*cord.chunk_end(), "");
2459  EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), "");
2460  EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), "");
2461 }
2462 
2463 // This test mimics a specific (and rare) application repeatedly splitting a
2464 // cord, inserting (overwriting) a string value, and composing a new cord from
2465 // the three pieces. This is hostile towards a Btree implementation: A split of
2466 // a node at any level is likely to have the right-most edge of the left split,
2467 // and the left-most edge of the right split shared. For example, splitting a
2468 // leaf node with 6 edges will result likely in a 1-6, 2-5, 3-4, etc. split,
2469 // sharing the 'split node'. When recomposing such nodes, we 'injected' an edge
2470 // in that node. As this happens with some probability on each level of the
2471 // tree, this will quickly grow the tree until it reaches maximum height.
2472 TEST_P(CordTest, BtreeHostileSplitInsertJoin) {
2473  absl::BitGen bitgen;
2474 
2475  // Start with about 1GB of data
2476  std::string data(1 << 10, 'x');
2478  absl::Cord cord;
2479  for (int i = 0; i < 1000000; ++i) {
2480  cord.Append(buffer);
2481  }
2482 
2483  for (int j = 0; j < 1000; ++j) {
2484  MaybeHarden(cord);
2485  size_t offset = absl::Uniform(bitgen, 0u, cord.size());
2486  size_t length = absl::Uniform(bitgen, 100u, data.size());
2487  if (cord.size() == offset) {
2488  cord.Append(absl::string_view(data.data(), length));
2489  } else {
2491  if (offset + length < cord.size()) {
2492  suffix = cord;
2493  suffix.RemovePrefix(offset + length);
2494  }
2495  if (cord.size() > offset) {
2496  cord.RemoveSuffix(cord.size() - offset);
2497  }
2498  cord.Append(absl::string_view(data.data(), length));
2499  if (!suffix.empty()) {
2500  cord.Append(suffix);
2501  }
2502  }
2503  }
2504 }
2505 
2507  public:
2508  bool Set(absl::Cord* cord, absl::string_view expected) {
2509  cord_ = cord;
2510  expected_ = expected;
2511  return true;
2512  }
2513 
2516  }
2517  private:
2520 };
2521 
2522 // Deliberately prevents the destructor for an absl::Cord from running. The cord
2523 // is accessible via the cord member during the lifetime of the CordLeaker.
2524 // After the CordLeaker is destroyed, pointers to the cord will remain valid
2525 // until the CordLeaker's memory is deallocated.
2526 struct CordLeaker {
2527  union {
2529  };
2530 
2531  template <typename Str>
2532  constexpr explicit CordLeaker(const Str& str) : cord(str) {}
2533 
2535  // Don't do anything, including running cord's destructor. (cord's
2536  // destructor won't run automatically because cord is hidden inside a
2537  // union.)
2538  }
2539 };
2540 
2541 template <typename Str>
2543  const auto expected = Str::value;
2544  // Defined before `cord` to be destroyed after it.
2545  static AfterExitCordTester exit_tester; // NOLINT
2546  ABSL_CONST_INIT static CordLeaker cord_leaker(Str{}); // NOLINT
2547  // cord_leaker is static, so this reference will remain valid through the end
2548  // of program execution.
2549  static absl::Cord& cord = cord_leaker.cord;
2550  static bool init_exit_tester = exit_tester.Set(&cord, expected);
2551  (void)init_exit_tester;
2552 
2553  EXPECT_EQ(cord, expected);
2554  // Copy the object and test the copy, and the original.
2555  {
2556  absl::Cord copy = cord;
2557  EXPECT_EQ(copy, expected);
2558  }
2559  // The original still works
2560  EXPECT_EQ(cord, expected);
2561 
2562  // Try making adding more structure to the tree.
2563  {
2564  absl::Cord copy = cord;
2565  std::string expected_copy(expected);
2566  for (int i = 0; i < 10; ++i) {
2567  copy.Append(cord);
2568  absl::StrAppend(&expected_copy, expected);
2569  EXPECT_EQ(copy, expected_copy);
2570  }
2571  }
2572 
2573  // Make sure we are using the right branch during constant evaluation.
2574  EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16);
2575 
2576  for (int i = 0; i < 10; ++i) {
2577  // Make a few more Cords from the same global rep.
2578  // This tests what happens when the refcount for it gets below 1.
2579  EXPECT_EQ(expected, absl::Cord(Str{}));
2580  }
2581 }
2582 
2583 constexpr int SimpleStrlen(const char* p) {
2584  return *p ? 1 + SimpleStrlen(p + 1) : 0;
2585 }
2586 
2587 struct ShortView {
2588  constexpr absl::string_view operator()() const {
2589  return absl::string_view("SSO string", SimpleStrlen("SSO string"));
2590  }
2591 };
2592 
2593 struct LongView {
2594  constexpr absl::string_view operator()() const {
2595  return absl::string_view("String that does not fit SSO.",
2596  SimpleStrlen("String that does not fit SSO."));
2597  }
2598 };
2599 
2600 
2601 TEST_P(CordTest, ConstinitConstructor) {
2606 }
2607 
2608 namespace {
2609 
2610 // Test helper that generates a populated cord for future manipulation.
2611 //
2612 // By test convention, all generated cords begin with the characters "abcde" at
2613 // the start of the first chunk.
2614 class PopulatedCordFactory {
2615  public:
2616  constexpr PopulatedCordFactory(absl::string_view name,
2617  absl::Cord (*generator)())
2618  : name_(name), generator_(generator) {}
2619 
2620  absl::string_view Name() const { return name_; }
2621  absl::Cord Generate() const { return generator_(); }
2622 
2623  private:
2625  absl::Cord (*generator_)();
2626 };
2627 
2628 // clang-format off
2629 // This array is constant-initialized in conformant compilers.
2630 PopulatedCordFactory cord_factories[] = {
2631  {"sso", [] { return absl::Cord("abcde"); }},
2632  {"flat", [] {
2633  // Too large to live in SSO space, but small enough to be a simple FLAT.
2634  absl::Cord flat(absl::StrCat("abcde", std::string(1000, 'x')));
2635  flat.Flatten();
2636  return flat;
2637  }},
2638  {"external", [] {
2639  // A cheat: we are using a string literal as the external storage, so a
2640  // no-op releaser is correct here.
2641  return absl::MakeCordFromExternal("abcde External!", []{});
2642  }},
2643  {"external substring", [] {
2644  // A cheat: we are using a string literal as the external storage, so a
2645  // no-op releaser is correct here.
2646  absl::Cord ext = absl::MakeCordFromExternal("-abcde External!", []{});
2647  return absl::CordTestPeer::MakeSubstring(ext, 1, ext.size() - 1);
2648  }},
2649  {"substring", [] {
2650  absl::Cord flat(absl::StrCat("-abcde", std::string(1000, 'x')));
2651  flat.Flatten();
2652  return flat.Subcord(1, 998);
2653  }},
2654  {"fragmented", [] {
2655  std::string fragment = absl::StrCat("abcde", std::string(195, 'x'));
2656  std::vector<std::string> fragments(200, fragment);
2657  absl::Cord cord = absl::MakeFragmentedCord(fragments);
2658  assert(cord.size() == 40000);
2659  return cord;
2660  }},
2661 };
2662 // clang-format on
2663 
2664 // Test helper that can mutate a cord, and possibly undo the mutation, for
2665 // testing.
2666 class CordMutator {
2667  public:
2668  constexpr CordMutator(absl::string_view name, void (*mutate)(absl::Cord&),
2669  void (*undo)(absl::Cord&) = nullptr)
2670  : name_(name), mutate_(mutate), undo_(undo) {}
2671 
2672  absl::string_view Name() const { return name_; }
2673  void Mutate(absl::Cord& cord) const { mutate_(cord); }
2674  bool CanUndo() const { return undo_ != nullptr; }
2675  void Undo(absl::Cord& cord) const { undo_(cord); }
2676 
2677  private:
2679  void (*mutate_)(absl::Cord&);
2680  void (*undo_)(absl::Cord&);
2681 };
2682 
2683 // clang-format off
2684 // This array is constant-initialized in conformant compilers.
2685 CordMutator cord_mutators[] ={
2686  {"clear", [](absl::Cord& c) { c.Clear(); }},
2687  {"overwrite", [](absl::Cord& c) { c = "overwritten"; }},
2688  {
2689  "append string",
2690  [](absl::Cord& c) { c.Append("0123456789"); },
2691  [](absl::Cord& c) { c.RemoveSuffix(10); }
2692  },
2693  {
2694  "append cord",
2695  [](absl::Cord& c) {
2696  c.Append(absl::MakeFragmentedCord({"12345", "67890"}));
2697  },
2698  [](absl::Cord& c) { c.RemoveSuffix(10); }
2699  },
2700  {
2701  "append checksummed cord",
2702  [](absl::Cord& c) {
2703  absl::Cord to_append = absl::MakeFragmentedCord({"12345", "67890"});
2704  to_append.SetExpectedChecksum(999);
2705  c.Append(to_append);
2706  },
2707  [](absl::Cord& c) { c.RemoveSuffix(10); }
2708  },
2709  {
2710  "append self",
2711  [](absl::Cord& c) { c.Append(c); },
2712  [](absl::Cord& c) { c.RemoveSuffix(c.size() / 2); }
2713  },
2714  {
2715  "prepend string",
2716  [](absl::Cord& c) { c.Prepend("9876543210"); },
2717  [](absl::Cord& c) { c.RemovePrefix(10); }
2718  },
2719  {
2720  "prepend cord",
2721  [](absl::Cord& c) {
2722  c.Prepend(absl::MakeFragmentedCord({"98765", "43210"}));
2723  },
2724  [](absl::Cord& c) { c.RemovePrefix(10); }
2725  },
2726  {
2727  "prepend checksummed cord",
2728  [](absl::Cord& c) {
2729  absl::Cord to_prepend = absl::MakeFragmentedCord({"98765", "43210"});
2730  to_prepend.SetExpectedChecksum(999);
2731  c.Prepend(to_prepend);
2732  },
2733  [](absl::Cord& c) { c.RemovePrefix(10); }
2734  },
2735  {
2736  "prepend self",
2737  [](absl::Cord& c) { c.Prepend(c); },
2738  [](absl::Cord& c) { c.RemovePrefix(c.size() / 2); }
2739  },
2740  {"remove prefix", [](absl::Cord& c) { c.RemovePrefix(2); }},
2741  {"remove suffix", [](absl::Cord& c) { c.RemoveSuffix(2); }},
2742  {"subcord", [](absl::Cord& c) { c = c.Subcord(1, c.size() - 2); }},
2743  {
2744  "swap inline",
2745  [](absl::Cord& c) {
2746  absl::Cord other("swap");
2747  c.swap(other);
2748  }
2749  },
2750  {
2751  "swap tree",
2752  [](absl::Cord& c) {
2753  absl::Cord other(std::string(10000, 'x'));
2754  c.swap(other);
2755  }
2756  },
2757 };
2758 // clang-format on
2759 } // namespace
2760 
2761 TEST_P(CordTest, ExpectedChecksum) {
2762  for (const PopulatedCordFactory& factory : cord_factories) {
2763  SCOPED_TRACE(factory.Name());
2764  for (bool shared : {false, true}) {
2765  SCOPED_TRACE(shared);
2766 
2767  absl::Cord shared_cord_source = factory.Generate();
2768  auto make_instance = [=] {
2769  return shared ? shared_cord_source : factory.Generate();
2770  };
2771 
2772  const absl::Cord base_value = factory.Generate();
2773  const std::string base_value_as_string(factory.Generate().Flatten());
2774 
2775  absl::Cord c1 = make_instance();
2776  EXPECT_FALSE(c1.ExpectedChecksum().has_value());
2777 
2778  // Setting an expected checksum works, and retains the cord's bytes
2779  c1.SetExpectedChecksum(12345);
2780  EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
2781  EXPECT_EQ(c1, base_value);
2782 
2783  // CRC persists through copies, assignments, and moves:
2784  absl::Cord c1_copy_construct = c1;
2785  EXPECT_EQ(c1_copy_construct.ExpectedChecksum().value_or(0), 12345);
2786 
2787  absl::Cord c1_copy_assign;
2788  c1_copy_assign = c1;
2789  EXPECT_EQ(c1_copy_assign.ExpectedChecksum().value_or(0), 12345);
2790 
2791  absl::Cord c1_move(std::move(c1_copy_assign));
2792  EXPECT_EQ(c1_move.ExpectedChecksum().value_or(0), 12345);
2793 
2794  EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
2795 
2796  // A CRC Cord compares equal to its non-CRC value.
2797  EXPECT_EQ(c1, make_instance());
2798 
2799  for (const CordMutator& mutator : cord_mutators) {
2800  SCOPED_TRACE(mutator.Name());
2801 
2802  // Test that mutating a cord removes its stored checksum
2803  absl::Cord c2 = make_instance();
2804  c2.SetExpectedChecksum(24680);
2805 
2806  mutator.Mutate(c2);
2807  EXPECT_EQ(c2.ExpectedChecksum(), absl::nullopt);
2808 
2809  if (mutator.CanUndo()) {
2810  // Undoing an operation should not restore the checksum
2811  mutator.Undo(c2);
2812  EXPECT_EQ(c2, base_value);
2813  EXPECT_EQ(c2.ExpectedChecksum(), absl::nullopt);
2814  }
2815  }
2816 
2817  absl::Cord c3 = make_instance();
2818  c3.SetExpectedChecksum(999);
2819  const absl::Cord& cc3 = c3;
2820 
2821  // Test that all cord reading operations function in the face of an
2822  // expected checksum.
2823 
2824  // Test data precondition
2825  ASSERT_TRUE(cc3.StartsWith("abcde"));
2826 
2827  EXPECT_EQ(cc3.size(), base_value_as_string.size());
2828  EXPECT_FALSE(cc3.empty());
2829  EXPECT_EQ(cc3.Compare(base_value), 0);
2830  EXPECT_EQ(cc3.Compare(base_value_as_string), 0);
2831  EXPECT_EQ(cc3.Compare("wxyz"), -1);
2832  EXPECT_EQ(cc3.Compare(absl::Cord("wxyz")), -1);
2833  EXPECT_EQ(cc3.Compare("aaaa"), 1);
2834  EXPECT_EQ(cc3.Compare(absl::Cord("aaaa")), 1);
2835  EXPECT_EQ(absl::Cord("wxyz").Compare(cc3), 1);
2836  EXPECT_EQ(absl::Cord("aaaa").Compare(cc3), -1);
2837  EXPECT_TRUE(cc3.StartsWith("abcd"));
2838  EXPECT_EQ(std::string(cc3), base_value_as_string);
2839 
2840  std::string dest;
2842  EXPECT_EQ(dest, base_value_as_string);
2843 
2844  bool first_pass = true;
2845  for (absl::string_view chunk : cc3.Chunks()) {
2846  if (first_pass) {
2847  EXPECT_TRUE(absl::StartsWith(chunk, "abcde"));
2848  }
2849  first_pass = false;
2850  }
2851  first_pass = true;
2852  for (char ch : cc3.Chars()) {
2853  if (first_pass) {
2854  EXPECT_EQ(ch, 'a');
2855  }
2856  first_pass = false;
2857  }
2858  EXPECT_TRUE(absl::StartsWith(*cc3.chunk_begin(), "abcde"));
2859  EXPECT_EQ(*cc3.char_begin(), 'a');
2860 
2861  auto char_it = cc3.char_begin();
2862  absl::Cord::Advance(&char_it, 2);
2863  EXPECT_EQ(absl::Cord::AdvanceAndRead(&char_it, 2), "cd");
2864  EXPECT_EQ(*char_it, 'e');
2865  char_it = cc3.char_begin();
2866  absl::Cord::Advance(&char_it, 2);
2868 
2869  EXPECT_EQ(cc3[0], 'a');
2870  EXPECT_EQ(cc3[4], 'e');
2871  EXPECT_EQ(absl::HashOf(cc3), absl::HashOf(base_value));
2872  EXPECT_EQ(absl::HashOf(cc3), absl::HashOf(base_value_as_string));
2873  }
2874  }
2875 }
testing::TestParamInfo::param
ParamType param
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h:60
absl::cord_internal::kMaxLargeFlatSize
static constexpr size_t kMaxLargeFlatSize
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:47
xds_interop_client.str
str
Definition: xds_interop_client.py:487
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
ABSL_RAW_CHECK
#define ABSL_RAW_CHECK(condition, message)
Definition: abseil-cpp/absl/base/internal/raw_logging.h:59
check_grpcio_tools.content
content
Definition: check_grpcio_tools.py:26
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
absl::cord_internal::kMinFlatSize
static constexpr size_t kMinFlatSize
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:43
absl::Cord
Definition: abseil-cpp/absl/strings/cord.h:150
VerifyFlatten
static void VerifyFlatten(absl::Cord c)
Definition: abseil-cpp/absl/strings/cord_test.cc:955
dst
static const char dst[]
Definition: test-fs-copyfile.c:37
absl::cord_internal::CordRepCrc
Definition: cord_rep_crc.h:35
absl::Cord::size
size_t size() const
Definition: abseil-cpp/absl/strings/cord.h:1288
absl::swap_internal::Swap
void Swap(T &lhs, T &rhs) noexcept(IsNothrowSwappable< T >::value)
Definition: abseil-cpp/absl/meta/type_traits.h:772
absl::cord_internal::AllocatedSizeToTag
uint8_t AllocatedSizeToTag(size_t size)
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:92
regen-readme.it
it
Definition: regen-readme.py:15
absl::str_format_internal::LengthMod::j
@ j
AddExternalMemory
static void AddExternalMemory(absl::string_view s, absl::Cord *dst)
Definition: abseil-cpp/absl/strings/cord_test.cc:122
pos
int pos
Definition: libuv/docs/code/tty-gravity/main.c:11
absl::StrAppend
void StrAppend(std::string *dest, const AlphaNum &a)
Definition: abseil-cpp/absl/strings/str_cat.cc:193
test_evm.cs
cs
Definition: test_evm.py:8
ABSL_CONST_INIT
#define ABSL_CONST_INIT
Definition: abseil-cpp/absl/base/attributes.h:716
absl::HashOf
size_t HashOf(const Types &... values)
Definition: abseil-cpp/absl/hash/hash.h:264
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
memset
return memset(p, 0, total)
absl::cord_internal::CordzUpdateTracker
Definition: abseil-cpp/absl/strings/internal/cordz_update_tracker.h:37
absl::Cord::ChunkRemaining
static absl::string_view ChunkRemaining(const CharIterator &it)
Definition: abseil-cpp/absl/strings/cord.h:1552
EXPECT_THAT
#define EXPECT_THAT(value, matcher)
INSTANTIATE_TEST_SUITE_P
INSTANTIATE_TEST_SUITE_P(WithParam, CordTest, testing::Values(0, 1), CordTest::ToString)
capstone.range
range
Definition: third_party/bloaty/third_party/capstone/bindings/python/capstone/__init__.py:6
CordLeaker::~CordLeaker
~CordLeaker()
Definition: abseil-cpp/absl/strings/cord_test.cc:2534
y
const double y
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3611
ext
void * ext
Definition: x509v3.h:87
copy
static int copy(grpc_slice_buffer *input, grpc_slice_buffer *output)
Definition: message_compress.cc:145
CordTest::MaybeHardened
absl::Cord MaybeHardened(absl::Cord c)
Definition: abseil-cpp/absl/strings/cord_test.cc:237
absl::Cord::Compare
int Compare(absl::string_view rhs) const
Definition: abseil-cpp/absl/strings/cord.cc:974
absl::StartsWith
bool StartsWith(absl::string_view text, absl::string_view prefix) noexcept
Definition: third_party/abseil-cpp/absl/strings/match.h:58
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::cord_internal::RoundUpForTag
size_t RoundUpForTag(size_t size)
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:84
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
EXPECT_GT
#define EXPECT_GT(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2036
absl::cord_internal::CordRepFlat::Capacity
size_t Capacity() const
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:166
absl::Cord::GetAppendBuffer
CordBuffer GetAppendBuffer(size_t capacity, size_t min_capacity=16)
Definition: abseil-cpp/absl/strings/cord.h:1361
ShortView::operator()
constexpr absl::string_view operator()() const
Definition: abseil-cpp/absl/strings/cord_test.cc:2588
absl::MakeCordFromExternal
Cord MakeCordFromExternal(absl::string_view, Releaser &&)
Definition: abseil-cpp/absl/strings/cord.h:1087
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
absl::Cord::Advance
static void Advance(CharIterator *it, size_t n_bytes)
Definition: abseil-cpp/absl/strings/cord.h:1547
absl::Cord::ChunkRange
Definition: abseil-cpp/absl/strings/cord.h:507
FLAT
static constexpr auto FLAT
Definition: abseil-cpp/absl/strings/cord_test.cc:47
New
T * New(Args &&... args)
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:195
absl::cord_internal::kMaxFlatLength
static constexpr size_t kMaxFlatLength
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:45
absl::Cord::char_begin
CharIterator char_begin() const
Definition: abseil-cpp/absl/strings/cord.h:1556
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
absl::Cord::StartsWith
bool StartsWith(const Cord &rhs) const
Definition: abseil-cpp/absl/strings/cord.h:1378
testing::TestParamInfo
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h:56
setup.name
name
Definition: setup.py:542
AfterExitCordTester::cord_
absl::Cord * cord_
Definition: abseil-cpp/absl/strings/cord_test.cc:2518
absl::cord_internal::CordRepConcat
Definition: bloaty/third_party/abseil-cpp/absl/strings/internal/cord_internal.h:211
absl::FormatConversionChar::s
@ s
num_elements
static size_t num_elements(const uint8_t *in, size_t in_len)
Definition: evp_asn1.c:283
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
CordTest::ToString
static std::string ToString(testing::TestParamInfo< int > param)
Definition: abseil-cpp/absl/strings/cord_test.cc:243
EXPECT_LE
#define EXPECT_LE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2030
absl::Cord::CharRange
Definition: abseil-cpp/absl/strings/cord.h:648
my_unique_true_boolean
bool my_unique_true_boolean
Definition: abseil-cpp/absl/strings/cord_test.cc:394
xds_manager.p
p
Definition: xds_manager.py:60
VerifyChunkIterator
static void VerifyChunkIterator(const absl::Cord &cord, size_t expected_chunks)
Definition: abseil-cpp/absl/strings/cord_test.cc:2051
name_
const std::string name_
Definition: priority.cc:233
absl::flags_internal::HelpMode::kNone
@ kNone
absl::Cord::TryFlat
absl::optional< absl::string_view > TryFlat() const
Definition: abseil-cpp/absl/strings/cord.h:1308
absl::cord_internal::TagToAllocatedSize
constexpr size_t TagToAllocatedSize(uint8_t tag)
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:64
ABSL_ARRAYSIZE
#define ABSL_ARRAYSIZE(array)
Definition: abseil-cpp/absl/base/macros.h:44
z
Uncopyable z
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3612
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
absl::cord_internal::CordRep
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:209
GetUniformRandomUpTo
static int GetUniformRandomUpTo(RandomEngine *rng, int upper_bound)
Definition: abseil-cpp/absl/strings/cord_test.cc:66
IsFlat
static bool IsFlat(const absl::Cord &c)
Definition: abseil-cpp/absl/strings/cord_test.cc:951
ABSL_HARDENING_ASSERT
#define ABSL_HARDENING_ASSERT(expr)
Definition: abseil-cpp/absl/base/macros.h:134
CordTest::MaybeHarden
void MaybeHarden(absl::Cord &c)
Definition: abseil-cpp/absl/strings/cord_test.cc:232
absl::Cord::RemoveSuffix
void RemoveSuffix(size_t n)
Definition: abseil-cpp/absl/strings/cord.cc:687
absl::Cord::empty
bool empty() const
Definition: abseil-cpp/absl/strings/cord.h:1293
testing::TestWithParam
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1883
absl::CordTestPeer::MakeSubstring
static Cord MakeSubstring(Cord src, size_t offset, size_t length)
Definition: abseil-cpp/absl/strings/cord_test.cc:211
absl::CordMemoryAccounting::kFairShare
@ kFairShare
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
testing::ElementsAre
internal::ElementsAreMatcher< ::testing::tuple<> > ElementsAre()
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:13040
block
Block * block
Definition: protobuf/src/google/protobuf/descriptor.cc:1041
AppendWithFragments
static size_t AppendWithFragments(const std::string &s, RandomEngine *rng, absl::Cord *cord)
Definition: abseil-cpp/absl/strings/cord_test.cc:139
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
re2::T1
@ T1
Definition: bloaty/third_party/re2/util/rune.cc:31
from
size_t from
Definition: abseil-cpp/absl/container/internal/layout_test.cc:1384
VerifyCopyToString
static void VerifyCopyToString(const absl::Cord &cord)
Definition: abseil-cpp/absl/strings/cord_test.cc:573
CordLeaker
Definition: abseil-cpp/absl/strings/cord_test.cc:2526
LongView::operator()
constexpr absl::string_view operator()() const
Definition: abseil-cpp/absl/strings/cord_test.cc:2594
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
c
void c(T a)
Definition: miscompile_with_no_unique_address_test.cc:40
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
SCOPED_TRACE
#define SCOPED_TRACE(message)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2264
absl::Cord::Chunks
ChunkRange Chunks() const
Definition: abseil-cpp/absl/strings/cord.h:1509
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
absl::cord_internal::CordRepExternal
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:306
absl::Cord::ExpectedChecksum
absl::optional< uint32_t > ExpectedChecksum() const
Definition: abseil-cpp/absl/strings/cord.cc:853
absl::cord_internal::kMaxInline
@ kMaxInline
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:418
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
absl::string_view::size
constexpr size_type size() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:277
swap
#define swap(a, b)
Definition: qsort.h:111
tag
static void * tag(intptr_t t)
Definition: bad_client.cc:318
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
absl::CordTestPeer::GetCordzInfo
static cord_internal::CordzInfo * GetCordzInfo(const Cord &c)
Definition: abseil-cpp/absl/strings/cord_test.cc:207
python_utils.jobset.INFO
INFO
Definition: jobset.py:111
ASSERT_THAT
#define ASSERT_THAT(value, matcher)
absl::optional::value_or
constexpr T value_or(U &&v) const &
Definition: abseil-cpp/absl/types/optional.h:506
DoNothing
static void DoNothing(absl::string_view, void *)
Definition: abseil-cpp/absl/strings/cord_test.cc:113
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
absl::Cord::EstimatedMemoryUsage
size_t EstimatedMemoryUsage(CordMemoryAccounting accounting_method=CordMemoryAccounting::kTotal) const
Definition: abseil-cpp/absl/strings/cord.h:1295
TestConstinitConstructor
void TestConstinitConstructor(Str)
Definition: abseil-cpp/absl/strings/cord_test.cc:2542
MakeComposite
static absl::Cord MakeComposite()
Definition: abseil-cpp/absl/strings/cord_test.cc:175
absl::cord_internal::FLAT
@ FLAT
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:194
absl::cord_internal::kFlatOverhead
static constexpr size_t kFlatOverhead
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:42
absl::Cord::Prepend
void Prepend(const Cord &src)
Definition: abseil-cpp/absl/strings/cord.cc:586
MAX_FLAT_TAG
static constexpr auto MAX_FLAT_TAG
Definition: abseil-cpp/absl/strings/cord_test.cc:48
MakeExternalCord
static absl::Cord MakeExternalCord(int size)
Definition: abseil-cpp/absl/strings/cord_test.cc:381
arg
Definition: cmdline.cc:40
CordLeaker::cord
absl::Cord cord
Definition: abseil-cpp/absl/strings/cord_test.cc:2528
absl::compare_internal::value_type
int8_t value_type
Definition: abseil-cpp/absl/types/compare.h:45
absl::cord_internal::CordRepFlat::AllocatedSize
size_t AllocatedSize() const
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:169
AfterExitCordTester
Definition: abseil-cpp/absl/strings/cord_test.cc:2506
intptr_t
_W64 signed int intptr_t
Definition: stdint-msvc2008.h:118
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
google::protobuf::WARNING
static const LogLevel WARNING
Definition: bloaty/third_party/protobuf/src/google/protobuf/testing/googletest.h:71
gen_synthetic_protos.base
base
Definition: gen_synthetic_protos.py:31
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
callback
static void callback(void *arg, int status, int timeouts, struct hostent *host)
Definition: acountry.c:224
buffer
char buffer[1024]
Definition: libuv/docs/code/idle-compute/main.c:8
absl::CordTestPeer
Definition: abseil-cpp/absl/strings/cord_test.cc:197
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
d
static const fe d
Definition: curve25519_tables.h:19
RandomEngine
std::mt19937_64 RandomEngine
Definition: abseil-cpp/absl/strings/cord_test.cc:50
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
tests.qps.qps_worker.dest
dest
Definition: qps_worker.py:45
EXPECT_DEATH_IF_SUPPORTED
#define EXPECT_DEATH_IF_SUPPORTED(statement, regex)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-death-test.h:335
absl::Cord::RemovePrefix
void RemovePrefix(size_t n)
Definition: abseil-cpp/absl/strings/cord.cc:657
google_benchmark.example.empty
def empty(state)
Definition: example.py:31
absl::strings_internal::MakeStringConstant
constexpr StringConstant< T > MakeStringConstant(T)
Definition: abseil-cpp/absl/strings/internal/string_constant.h:64
absl::Cord::contents_
InlineRep contents_
Definition: abseil-cpp/absl/strings/cord.h:937
absl::Cord::CharIterator
Definition: abseil-cpp/absl/strings/cord.h:573
absl::Cord::Subcord
Cord Subcord(size_t pos, size_t new_size) const
Definition: abseil-cpp/absl/strings/cord.cc:715
value
const char * value
Definition: hpack_parser_table.cc:165
CordTest::UseCrc
bool UseCrc() const
Definition: abseil-cpp/absl/strings/cord_test.cc:231
MakeHuge
static absl::Cord MakeHuge(absl::string_view prefix)
Definition: abseil-cpp/absl/strings/cord_test.cc:1920
abseil.generate
def generate(args)
Definition: abseil-cpp/absl/abseil.podspec.gen.py:200
absl::hash_internal::c1
static const uint32_t c1
Definition: abseil-cpp/absl/hash/internal/city.cc:58
contents
string_view contents
Definition: elf.cc:597
absl::Cord::char_end
CharIterator char_end() const
Definition: abseil-cpp/absl/strings/cord.h:1560
AfterExitCordTester::expected_
absl::string_view expected_
Definition: abseil-cpp/absl/strings/cord_test.cc:2519
absl::CordBuffer::CreateWithDefaultLimit
static CordBuffer CreateWithDefaultLimit(size_t capacity)
Definition: cord_buffer.h:465
absl::Cord::SetExpectedChecksum
void SetExpectedChecksum(uint32_t crc)
Definition: abseil-cpp/absl/strings/cord.cc:838
testing::Values
internal::ValueArray< T... > Values(T... v)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-param-test.h:335
N
#define N
Definition: sync_test.cc:37
suffix
unsigned char suffix[65536]
Definition: bloaty/third_party/zlib/examples/gun.c:164
absl::cord_internal::CordRepBtree
Definition: cord_rep_btree.h:63
absl::Cord::InlineRep::tree
absl::cord_internal::CordRep * tree() const
Definition: abseil-cpp/absl/strings/cord.h:1162
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
absl::CordTestPeer::Tree
static CordRep * Tree(const Cord &c)
Definition: abseil-cpp/absl/strings/cord_test.cc:205
absl::cord_internal::CordzInfo
Definition: abseil-cpp/absl/strings/internal/cordz_info.h:47
CordTest
Definition: abseil-cpp/absl/strings/cord_test.cc:228
AfterExitCordTester::~AfterExitCordTester
~AfterExitCordTester()
Definition: abseil-cpp/absl/strings/cord_test.cc:2514
testing::Le
internal::LeMatcher< Rhs > Le(Rhs x)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8597
absl::CopyCordToString
void CopyCordToString(const Cord &src, std::string *dst)
Definition: abseil-cpp/absl/strings/cord.cc:1013
re2::T2
@ T2
Definition: bloaty/third_party/re2/util/rune.cc:33
absl::Cord::CharRange::begin
CharIterator begin() const
Definition: abseil-cpp/absl/strings/cord.h:1562
absl::flags_internal::FlagOp::kCopy
@ kCopy
absl::cord_internal::CordRepFlat::Data
char * Data()
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:162
kIters
constexpr int32_t kIters
Definition: abseil-cpp/absl/base/spinlock_test_common.cc:38
absl::Cord::chunk_end
ChunkIterator chunk_end() const
Definition: abseil-cpp/absl/strings/cord.h:1499
absl::random_internal::NonsecureURBGBase< random_internal::randen_engine< uint64_t > >
string_view
absl::string_view string_view
Definition: attr.cc:22
absl::Cord::Flatten
absl::string_view Flatten()
Definition: abseil-cpp/absl/strings/cord.h:1320
EXPECT_LT
#define EXPECT_LT(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2032
TEST_P
TEST_P(CordTest, AllFlatSizes)
Definition: abseil-cpp/absl/strings/cord_test.cc:327
absl::strings_internal::CordTestAccess
Definition: abseil-cpp/absl/strings/cord.h:1629
absl::cord_internal::MAX_FLAT_TAG
@ MAX_FLAT_TAG
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:195
prefix
static const char prefix[]
Definition: head_of_line_blocking.cc:28
ASSERT_TRUE
#define ASSERT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1973
testing::WithParamInterface< int >::GetParam
static const ParamType & GetParam()
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1855
rep
const CordRep * rep
Definition: cord_analysis.cc:53
absl::Format
bool Format(FormatRawSink raw_sink, const FormatSpec< Args... > &format, const Args &... args)
Definition: abseil-cpp/absl/strings/str_format.h:504
arg
struct arg arg
ShortView
Definition: abseil-cpp/absl/strings/cord_test.cc:2587
absl::CordBuffer::kDefaultLimit
static constexpr size_t kDefaultLimit
Definition: cord_buffer.h:111
data_
std::string data_
Definition: cord_rep_btree_navigator_test.cc:84
python_utils.upload_rbe_results.test_cases
list test_cases
Definition: upload_rbe_results.py:197
TEST
TEST(CordRepFlat, AllFlatCapacities)
Definition: abseil-cpp/absl/strings/cord_test.cc:259
absl::CordTestPeer::IsTree
static bool IsTree(const Cord &c)
Definition: abseil-cpp/absl/strings/cord_test.cc:204
EXPECT_GE
#define EXPECT_GE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2034
absl::FunctionRef
Definition: abseil-cpp/absl/functional/function_ref.h:65
absl::CordBuffer
Definition: cord_buffer.h:105
CordLeaker::CordLeaker
constexpr CordLeaker(const Str &str)
Definition: abseil-cpp/absl/strings/cord_test.cc:2532
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
absl::strings_internal::Compare
int Compare(const BigUnsigned< N > &lhs, const BigUnsigned< M > &rhs)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:353
GTEST_FLAG_GET
#define GTEST_FLAG_GET(name)
Definition: googletest/googletest/include/gtest/internal/gtest-port.h:2218
absl::MakeFragmentedCord
Cord MakeFragmentedCord(const Container &c)
Definition: abseil-cpp/absl/strings/cord_test_helpers.h:103
AddNewStringBlock
static void AddNewStringBlock(const std::string &str, absl::Cord *dst)
Definition: abseil-cpp/absl/strings/cord_test.cc:166
tracker
SessionTracker * tracker
Definition: ssl_session_cache_test.cc:38
generator_
Generator generator_
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc:124
RandomLowercaseString
static std::string RandomLowercaseString(RandomEngine *rng)
Definition: abseil-cpp/absl/strings/cord_test.cc:90
LongView
Definition: abseil-cpp/absl/strings/cord_test.cc:2593
absl::string_view::empty
constexpr bool empty() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:292
DumpGrowth
static void DumpGrowth()
Definition: abseil-cpp/absl/strings/cord_test.cc:129
absl::Cord::AdvanceAndRead
static Cord AdvanceAndRead(CharIterator *it, size_t n_bytes)
Definition: abseil-cpp/absl/strings/cord.h:1542
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::Cord::InlineRep::is_tree
bool is_tree() const
Definition: abseil-cpp/absl/strings/cord.h:899
absl::Cord::InlineRep::EmplaceTree
void EmplaceTree(CordRep *rep, MethodIdentifier method)
Definition: abseil-cpp/absl/strings/cord.h:1186
AfterExitCordTester::Set
bool Set(absl::Cord *cord, absl::string_view expected)
Definition: abseil-cpp/absl/strings/cord_test.cc:2508
ch
char ch
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3621
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
SimpleStrlen
constexpr int SimpleStrlen(const char *p)
Definition: abseil-cpp/absl/strings/cord_test.cc:2583
autogen_x86imm.tmp
tmp
Definition: autogen_x86imm.py:12
ASSERT_GT
#define ASSERT_GT(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2076
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
length
std::size_t length
Definition: abseil-cpp/absl/time/internal/test_util.cc:57
absl::Cord::chunk_begin
ChunkIterator chunk_begin() const
Definition: abseil-cpp/absl/strings/cord.h:1495
testing::Ref
internal::RefMatcher< T & > Ref(T &x)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8628
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
absl::cord_internal::SkipCrcNode
CordRep * SkipCrcNode(CordRep *rep)
Definition: cord_rep_crc.h:70
absl::Cord::Chars
CharRange Chars() const
Definition: abseil-cpp/absl/strings/cord.h:1570
absl::string_view::data
constexpr const_pointer data() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:336
absl::Cord::CharRange::end
CharIterator end() const
Definition: abseil-cpp/absl/strings/cord.h:1566
absl::cord_internal::CordRepSubstring
Definition: abseil-cpp/absl/strings/internal/cord_internal.h:280
absl::CordTestPeer::ForEachChunk
static void ForEachChunk(const Cord &c, absl::FunctionRef< void(absl::string_view)> callback)
Definition: abseil-cpp/absl/strings/cord_test.cc:199
VerifyCharIterator
static void VerifyCharIterator(const absl::Cord &cord)
Definition: abseil-cpp/absl/strings/cord_test.cc:2240
ABSL_RAW_LOG
#define ABSL_RAW_LOG(severity,...)
Definition: abseil-cpp/absl/base/internal/raw_logging.h:44
absl::string_view::substr
constexpr string_view substr(size_type pos=0, size_type n=npos) const
Definition: abseil-cpp/absl/strings/string_view.h:399
absl::cord_internal::CordRepFlat
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:107
absl::Cord::ChunkIterator
Definition: abseil-cpp/absl/strings/cord.h:412
absl::Cord::Append
void Append(const Cord &src)
Definition: abseil-cpp/absl/strings/cord.cc:566
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
offset
voidpf uLong offset
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:142
GenerateSkewedRandom
static int32_t GenerateSkewedRandom(RandomEngine *rng, int max_log)
Definition: abseil-cpp/absl/strings/cord_test.cc:84
ASSERT_EQ
#define ASSERT_EQ(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2056
absl::hash_internal::c2
static const uint32_t c2
Definition: abseil-cpp/absl/hash/internal/city.cc:59
DeleteExternalString
static void DeleteExternalString(absl::string_view data, void *arg)
Definition: abseil-cpp/absl/strings/cord_test.cc:115
absl::cord_internal::CordRep::flat
CordRepFlat * flat()
Definition: abseil-cpp/absl/strings/internal/cord_rep_flat.h:173
absl::Uniform
absl::enable_if_t<!std::is_same< R, void >::value, R > Uniform(TagType tag, URBG &&urbg, R lo, R hi)
Definition: abseil-cpp/absl/random/distributions.h:123


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:03