• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <array>
19 #include <cassert>
20 #include <cstddef>
21 #include <cstdint>
22 #include <cstdio>
23 #include <cstring>
24 #include <iostream>
25 #include <iterator>
26 #include <limits>
27 #include <random>
28 #include <set>
29 #include <sstream>
30 #include <string>
31 #include <type_traits>
32 #include <utility>
33 #include <vector>
34 
35 #include "gmock/gmock.h"
36 #include "gtest/gtest.h"
37 #include "absl/base/attributes.h"
38 #include "absl/base/config.h"
39 #include "absl/base/internal/endian.h"
40 #include "absl/base/macros.h"
41 #include "absl/base/no_destructor.h"
42 #include "absl/base/options.h"
43 #include "absl/container/fixed_array.h"
44 #include "absl/functional/function_ref.h"
45 #include "absl/hash/hash.h"
46 #include "absl/hash/hash_testing.h"
47 #include "absl/log/check.h"
48 #include "absl/log/log.h"
49 #include "absl/random/random.h"
50 #include "absl/strings/cord_buffer.h"
51 #include "absl/strings/cord_test_helpers.h"
52 #include "absl/strings/cordz_test_helpers.h"
53 #include "absl/strings/internal/cord_internal.h"
54 #include "absl/strings/internal/cord_rep_crc.h"
55 #include "absl/strings/internal/cord_rep_flat.h"
56 #include "absl/strings/internal/cordz_statistics.h"
57 #include "absl/strings/internal/cordz_update_tracker.h"
58 #include "absl/strings/internal/string_constant.h"
59 #include "absl/strings/match.h"
60 #include "absl/strings/str_cat.h"
61 #include "absl/strings/str_format.h"
62 #include "absl/strings/string_view.h"
63 #include "absl/types/optional.h"
64 
65 // convenience local constants
66 static constexpr auto FLAT = absl::cord_internal::FLAT;
67 static constexpr auto MAX_FLAT_TAG = absl::cord_internal::MAX_FLAT_TAG;
68 
69 typedef std::mt19937_64 RandomEngine;
70 
71 using absl::cord_internal::CordRep;
72 using absl::cord_internal::CordRepBtree;
73 using absl::cord_internal::CordRepConcat;
74 using absl::cord_internal::CordRepCrc;
75 using absl::cord_internal::CordRepExternal;
76 using absl::cord_internal::CordRepFlat;
77 using absl::cord_internal::CordRepSubstring;
78 using absl::cord_internal::CordzUpdateTracker;
79 using absl::cord_internal::kFlatOverhead;
80 using absl::cord_internal::kMaxFlatLength;
81 using ::testing::ElementsAre;
82 using ::testing::Le;
83 
84 static std::string RandomLowercaseString(RandomEngine* rng);
85 static std::string RandomLowercaseString(RandomEngine* rng, size_t length);
86 
GetUniformRandomUpTo(RandomEngine * rng,int upper_bound)87 static int GetUniformRandomUpTo(RandomEngine* rng, int upper_bound) {
88   if (upper_bound > 0) {
89     std::uniform_int_distribution<int> uniform(0, upper_bound - 1);
90     return uniform(*rng);
91   } else {
92     return 0;
93   }
94 }
95 
GetUniformRandomUpTo(RandomEngine * rng,size_t upper_bound)96 static size_t GetUniformRandomUpTo(RandomEngine* rng, size_t upper_bound) {
97   if (upper_bound > 0) {
98     std::uniform_int_distribution<size_t> uniform(0, upper_bound - 1);
99     return uniform(*rng);
100   } else {
101     return 0;
102   }
103 }
104 
GenerateSkewedRandom(RandomEngine * rng,int max_log)105 static int32_t GenerateSkewedRandom(RandomEngine* rng, int max_log) {
106   const uint32_t base = (*rng)() % (max_log + 1);
107   const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u;
108   return (*rng)() & mask;
109 }
110 
RandomLowercaseString(RandomEngine * rng)111 static std::string RandomLowercaseString(RandomEngine* rng) {
112   int length;
113   std::bernoulli_distribution one_in_1k(0.001);
114   std::bernoulli_distribution one_in_10k(0.0001);
115   // With low probability, make a large fragment
116   if (one_in_10k(*rng)) {
117     length = GetUniformRandomUpTo(rng, 1048576);
118   } else if (one_in_1k(*rng)) {
119     length = GetUniformRandomUpTo(rng, 10000);
120   } else {
121     length = GenerateSkewedRandom(rng, 10);
122   }
123   return RandomLowercaseString(rng, length);
124 }
125 
RandomLowercaseString(RandomEngine * rng,size_t length)126 static std::string RandomLowercaseString(RandomEngine* rng, size_t length) {
127   std::string result(length, '\0');
128   std::uniform_int_distribution<int> chars('a', 'z');
129   std::generate(result.begin(), result.end(),
130                 [&]() { return static_cast<char>(chars(*rng)); });
131   return result;
132 }
133 
DoNothing(absl::string_view,void *)134 static void DoNothing(absl::string_view /* data */, void* /* arg */) {}
135 
DeleteExternalString(absl::string_view data,void * arg)136 static void DeleteExternalString(absl::string_view data, void* arg) {
137   std::string* s = reinterpret_cast<std::string*>(arg);
138   EXPECT_EQ(data, *s);
139   delete s;
140 }
141 
142 // Add "s" to *dst via `MakeCordFromExternal`
AddExternalMemory(absl::string_view s,absl::Cord * dst)143 static void AddExternalMemory(absl::string_view s, absl::Cord* dst) {
144   std::string* str = new std::string(s.data(), s.size());
145   dst->Append(absl::MakeCordFromExternal(*str, [str](absl::string_view data) {
146     DeleteExternalString(data, str);
147   }));
148 }
149 
DumpGrowth()150 static void DumpGrowth() {
151   absl::Cord str;
152   for (int i = 0; i < 1000; i++) {
153     char c = 'a' + i % 26;
154     str.Append(absl::string_view(&c, 1));
155   }
156 }
157 
158 // Make a Cord with some number of fragments.  Return the size (in bytes)
159 // of the smallest fragment.
AppendWithFragments(const std::string & s,RandomEngine * rng,absl::Cord * cord)160 static size_t AppendWithFragments(const std::string& s, RandomEngine* rng,
161                                   absl::Cord* cord) {
162   size_t j = 0;
163   const size_t max_size = s.size() / 5;  // Make approx. 10 fragments
164   size_t min_size = max_size;            // size of smallest fragment
165   while (j < s.size()) {
166     size_t N = 1 + GetUniformRandomUpTo(rng, max_size);
167     if (N > (s.size() - j)) {
168       N = s.size() - j;
169     }
170     if (N < min_size) {
171       min_size = N;
172     }
173 
174     std::bernoulli_distribution coin_flip(0.5);
175     if (coin_flip(*rng)) {
176       // Grow by adding an external-memory.
177       AddExternalMemory(absl::string_view(s.data() + j, N), cord);
178     } else {
179       cord->Append(absl::string_view(s.data() + j, N));
180     }
181     j += N;
182   }
183   return min_size;
184 }
185 
186 // Add an external memory that contains the specified std::string to cord
AddNewStringBlock(const std::string & str,absl::Cord * dst)187 static void AddNewStringBlock(const std::string& str, absl::Cord* dst) {
188   char* data = new char[str.size()];
189   memcpy(data, str.data(), str.size());
190   dst->Append(absl::MakeCordFromExternal(
191       absl::string_view(data, str.size()),
192       [](absl::string_view s) { delete[] s.data(); }));
193 }
194 
195 // Make a Cord out of many different types of nodes.
MakeComposite()196 static absl::Cord MakeComposite() {
197   absl::Cord cord;
198   cord.Append("the");
199   AddExternalMemory(" quick brown", &cord);
200   AddExternalMemory(" fox jumped", &cord);
201 
202   absl::Cord full(" over");
203   AddExternalMemory(" the lazy", &full);
204   AddNewStringBlock(" dog slept the whole day away", &full);
205   absl::Cord substring = full.Subcord(0, 18);
206 
207   // Make substring long enough to defeat the copying fast path in Append.
208   substring.Append(std::string(1000, '.'));
209   cord.Append(substring);
210   cord = cord.Subcord(0, cord.size() - 998);  // Remove most of extra junk
211 
212   return cord;
213 }
214 
215 namespace absl {
216 ABSL_NAMESPACE_BEGIN
217 
218 class CordTestPeer {
219  public:
ForEachChunk(const Cord & c,absl::FunctionRef<void (absl::string_view)> callback)220   static void ForEachChunk(
221       const Cord& c, absl::FunctionRef<void(absl::string_view)> callback) {
222     c.ForEachChunk(callback);
223   }
224 
IsTree(const Cord & c)225   static bool IsTree(const Cord& c) { return c.contents_.is_tree(); }
Tree(const Cord & c)226   static CordRep* Tree(const Cord& c) { return c.contents_.tree(); }
227 
GetCordzInfo(const Cord & c)228   static cord_internal::CordzInfo* GetCordzInfo(const Cord& c) {
229     return c.contents_.cordz_info();
230   }
231 
MakeSubstring(Cord src,size_t offset,size_t length)232   static Cord MakeSubstring(Cord src, size_t offset, size_t length) {
233     CHECK(src.contents_.is_tree()) << "Can not be inlined";
234     CHECK(!src.ExpectedChecksum().has_value()) << "Can not be hardened";
235     Cord cord;
236     auto* tree = cord_internal::SkipCrcNode(src.contents_.tree());
237     auto* rep = CordRepSubstring::Create(CordRep::Ref(tree), offset, length);
238     cord.contents_.EmplaceTree(rep, CordzUpdateTracker::kSubCord);
239     return cord;
240   }
241 };
242 
243 ABSL_NAMESPACE_END
244 }  // namespace absl
245 
246 
247 
248 // The CordTest fixture runs all tests with and without expected CRCs being set
249 // on the subject Cords.
250 class CordTest : public testing::TestWithParam<bool /*useCrc*/> {
251  public:
252   // Returns true if test is running with Crc enabled.
UseCrc() const253   bool UseCrc() const { return GetParam(); }
MaybeHarden(absl::Cord & c)254   void MaybeHarden(absl::Cord& c) {
255     if (UseCrc()) {
256       c.SetExpectedChecksum(1);
257     }
258   }
MaybeHardened(absl::Cord c)259   absl::Cord MaybeHardened(absl::Cord c) {
260     MaybeHarden(c);
261     return c;
262   }
263 
264   // Returns human readable string representation of the test parameter.
ToString(testing::TestParamInfo<bool> useCrc)265   static std::string ToString(testing::TestParamInfo<bool> useCrc) {
266     if (useCrc.param) {
267       return "BtreeHardened";
268     } else {
269       return "Btree";
270     }
271   }
272 };
273 
274 INSTANTIATE_TEST_SUITE_P(WithParam, CordTest, testing::Bool(),
275                          CordTest::ToString);
276 
TEST(CordRepFlat,AllFlatCapacities)277 TEST(CordRepFlat, AllFlatCapacities) {
278   // Explicitly and redundantly assert built-in min/max limits
279   static_assert(absl::cord_internal::kFlatOverhead < 32, "");
280   static_assert(absl::cord_internal::kMinFlatSize == 32, "");
281   static_assert(absl::cord_internal::kMaxLargeFlatSize == 256 << 10, "");
282   EXPECT_EQ(absl::cord_internal::TagToAllocatedSize(FLAT), 32);
283   EXPECT_EQ(absl::cord_internal::TagToAllocatedSize(MAX_FLAT_TAG), 256 << 10);
284 
285   // Verify all tags to map perfectly back and forth, and
286   // that sizes are monotonically increasing.
287   size_t last_size = 0;
288   for (int tag = FLAT; tag <= MAX_FLAT_TAG; ++tag) {
289     size_t size = absl::cord_internal::TagToAllocatedSize(tag);
290     ASSERT_GT(size, last_size);
291     ASSERT_EQ(absl::cord_internal::TagToAllocatedSize(tag), size);
292     last_size = size;
293   }
294 
295   // All flat size from 32 - 512 are 8 byte granularity
296   for (size_t size = 32; size <= 512; size += 8) {
297     ASSERT_EQ(absl::cord_internal::RoundUpForTag(size), size);
298     uint8_t tag = absl::cord_internal::AllocatedSizeToTag(size);
299     ASSERT_EQ(absl::cord_internal::TagToAllocatedSize(tag), size);
300   }
301 
302   // All flat sizes from 512 - 8192 are 64 byte granularity
303   for (size_t size = 512; size <= 8192; size += 64) {
304     ASSERT_EQ(absl::cord_internal::RoundUpForTag(size), size);
305     uint8_t tag = absl::cord_internal::AllocatedSizeToTag(size);
306     ASSERT_EQ(absl::cord_internal::TagToAllocatedSize(tag), size);
307   }
308 
309   // All flat sizes from 8KB to 256KB are 4KB granularity
310   for (size_t size = 8192; size <= 256 * 1024; size += 4 * 1024) {
311     ASSERT_EQ(absl::cord_internal::RoundUpForTag(size), size);
312     uint8_t tag = absl::cord_internal::AllocatedSizeToTag(size);
313     ASSERT_EQ(absl::cord_internal::TagToAllocatedSize(tag), size);
314   }
315 }
316 
TEST(CordRepFlat,MaxFlatSize)317 TEST(CordRepFlat, MaxFlatSize) {
318   CordRepFlat* flat = CordRepFlat::New(kMaxFlatLength);
319   EXPECT_EQ(flat->Capacity(), kMaxFlatLength);
320   CordRep::Unref(flat);
321 
322   flat = CordRepFlat::New(kMaxFlatLength * 4);
323   EXPECT_EQ(flat->Capacity(), kMaxFlatLength);
324   CordRep::Unref(flat);
325 }
326 
TEST(CordRepFlat,MaxLargeFlatSize)327 TEST(CordRepFlat, MaxLargeFlatSize) {
328   const size_t size = 256 * 1024 - kFlatOverhead;
329   CordRepFlat* flat = CordRepFlat::New(CordRepFlat::Large(), size);
330   EXPECT_GE(flat->Capacity(), size);
331   CordRep::Unref(flat);
332 }
333 
TEST(CordRepFlat,AllFlatSizes)334 TEST(CordRepFlat, AllFlatSizes) {
335   const size_t kMaxSize = 256 * 1024;
336   for (size_t size = 32; size <= kMaxSize; size *=2) {
337     const size_t length = size - kFlatOverhead - 1;
338     CordRepFlat* flat = CordRepFlat::New(CordRepFlat::Large(), length);
339     EXPECT_GE(flat->Capacity(), length);
340     memset(flat->Data(), 0xCD, flat->Capacity());
341     CordRep::Unref(flat);
342   }
343 }
344 
TEST_P(CordTest,AllFlatSizes)345 TEST_P(CordTest, AllFlatSizes) {
346   using absl::strings_internal::CordTestAccess;
347 
348   for (size_t s = 0; s < CordTestAccess::MaxFlatLength(); s++) {
349     // Make a string of length s.
350     std::string src;
351     while (src.size() < s) {
352       src.push_back('a' + (src.size() % 26));
353     }
354 
355     absl::Cord dst(src);
356     MaybeHarden(dst);
357     EXPECT_EQ(std::string(dst), src) << s;
358   }
359 }
360 
361 // We create a Cord at least 128GB in size using the fact that Cords can
362 // internally reference-count; thus the Cord is enormous without actually
363 // consuming very much memory.
TEST_P(CordTest,GigabyteCordFromExternal)364 TEST_P(CordTest, GigabyteCordFromExternal) {
365   const size_t one_gig = 1024U * 1024U * 1024U;
366   size_t max_size = 2 * one_gig;
367   if (sizeof(max_size) > 4) max_size = 128 * one_gig;
368 
369   size_t length = 128 * 1024;
370   char* data = new char[length];
371   absl::Cord from = absl::MakeCordFromExternal(
372       absl::string_view(data, length),
373       [](absl::string_view sv) { delete[] sv.data(); });
374 
375   // This loop may seem odd due to its combination of exponential doubling of
376   // size and incremental size increases.  We do it incrementally to be sure the
377   // Cord will need rebalancing and will exercise code that, in the past, has
378   // caused crashes in production.  We grow exponentially so that the code will
379   // execute in a reasonable amount of time.
380   absl::Cord c;
381   c.Append(from);
382   while (c.size() < max_size) {
383     c.Append(c);
384     c.Append(from);
385     c.Append(from);
386     c.Append(from);
387     c.Append(from);
388     MaybeHarden(c);
389   }
390 
391   for (int i = 0; i < 1024; ++i) {
392     c.Append(from);
393   }
394   LOG(INFO) << "Made a Cord with " << c.size() << " bytes!";
395   // Note: on a 32-bit build, this comes out to   2,818,048,000 bytes.
396   // Note: on a 64-bit build, this comes out to 171,932,385,280 bytes.
397 }
398 
MakeExternalCord(int size)399 static absl::Cord MakeExternalCord(int size) {
400   char* buffer = new char[size];
401   memset(buffer, 'x', size);
402   absl::Cord cord;
403   cord.Append(absl::MakeCordFromExternal(
404       absl::string_view(buffer, size),
405       [](absl::string_view s) { delete[] s.data(); }));
406   return cord;
407 }
408 
409 // Extern to fool clang that this is not constant. Needed to suppress
410 // a warning of unsafe code we want to test.
411 extern bool my_unique_true_boolean;
412 bool my_unique_true_boolean = true;
413 
TEST_P(CordTest,Assignment)414 TEST_P(CordTest, Assignment) {
415   absl::Cord x(absl::string_view("hi there"));
416   absl::Cord y(x);
417   MaybeHarden(y);
418   ASSERT_EQ(x.ExpectedChecksum(), absl::nullopt);
419   ASSERT_EQ(std::string(x), "hi there");
420   ASSERT_EQ(std::string(y), "hi there");
421   ASSERT_TRUE(x == y);
422   ASSERT_TRUE(x <= y);
423   ASSERT_TRUE(y <= x);
424 
425   x = absl::string_view("foo");
426   ASSERT_EQ(std::string(x), "foo");
427   ASSERT_EQ(std::string(y), "hi there");
428   ASSERT_TRUE(x < y);
429   ASSERT_TRUE(y > x);
430   ASSERT_TRUE(x != y);
431   ASSERT_TRUE(x <= y);
432   ASSERT_TRUE(y >= x);
433 
434   x = "foo";
435   ASSERT_EQ(x, "foo");
436 
437   // Test that going from inline rep to tree we don't leak memory.
438   std::vector<std::pair<absl::string_view, absl::string_view>>
439       test_string_pairs = {{"hi there", "foo"},
440                            {"loooooong coooooord", "short cord"},
441                            {"short cord", "loooooong coooooord"},
442                            {"loooooong coooooord1", "loooooong coooooord2"}};
443   for (std::pair<absl::string_view, absl::string_view> test_strings :
444        test_string_pairs) {
445     absl::Cord tmp(test_strings.first);
446     absl::Cord z(std::move(tmp));
447     ASSERT_EQ(std::string(z), test_strings.first);
448     tmp = test_strings.second;
449     z = std::move(tmp);
450     ASSERT_EQ(std::string(z), test_strings.second);
451   }
452   {
453     // Test that self-move assignment doesn't crash/leak.
454     // Do not write such code!
455     absl::Cord my_small_cord("foo");
456     absl::Cord my_big_cord("loooooong coooooord");
457     // Bypass clang's warning on self move-assignment.
458     absl::Cord* my_small_alias =
459         my_unique_true_boolean ? &my_small_cord : &my_big_cord;
460     absl::Cord* my_big_alias =
461         !my_unique_true_boolean ? &my_small_cord : &my_big_cord;
462 
463     *my_small_alias = std::move(my_small_cord);
464     *my_big_alias = std::move(my_big_cord);
465     // my_small_cord and my_big_cord are in an unspecified but valid
466     // state, and will be correctly destroyed here.
467   }
468 }
469 
TEST_P(CordTest,StartsEndsWith)470 TEST_P(CordTest, StartsEndsWith) {
471   absl::Cord x(absl::string_view("abcde"));
472   MaybeHarden(x);
473   absl::Cord empty("");
474 
475   ASSERT_TRUE(x.StartsWith(absl::Cord("abcde")));
476   ASSERT_TRUE(x.StartsWith(absl::Cord("abc")));
477   ASSERT_TRUE(x.StartsWith(absl::Cord("")));
478   ASSERT_TRUE(empty.StartsWith(absl::Cord("")));
479   ASSERT_TRUE(x.EndsWith(absl::Cord("abcde")));
480   ASSERT_TRUE(x.EndsWith(absl::Cord("cde")));
481   ASSERT_TRUE(x.EndsWith(absl::Cord("")));
482   ASSERT_TRUE(empty.EndsWith(absl::Cord("")));
483 
484   ASSERT_TRUE(!x.StartsWith(absl::Cord("xyz")));
485   ASSERT_TRUE(!empty.StartsWith(absl::Cord("xyz")));
486   ASSERT_TRUE(!x.EndsWith(absl::Cord("xyz")));
487   ASSERT_TRUE(!empty.EndsWith(absl::Cord("xyz")));
488 
489   ASSERT_TRUE(x.StartsWith("abcde"));
490   ASSERT_TRUE(x.StartsWith("abc"));
491   ASSERT_TRUE(x.StartsWith(""));
492   ASSERT_TRUE(empty.StartsWith(""));
493   ASSERT_TRUE(x.EndsWith("abcde"));
494   ASSERT_TRUE(x.EndsWith("cde"));
495   ASSERT_TRUE(x.EndsWith(""));
496   ASSERT_TRUE(empty.EndsWith(""));
497 
498   ASSERT_TRUE(!x.StartsWith("xyz"));
499   ASSERT_TRUE(!empty.StartsWith("xyz"));
500   ASSERT_TRUE(!x.EndsWith("xyz"));
501   ASSERT_TRUE(!empty.EndsWith("xyz"));
502 }
503 
TEST_P(CordTest,Contains)504 TEST_P(CordTest, Contains) {
505   auto flat_haystack = absl::Cord("this is a flat cord");
506   auto fragmented_haystack = absl::MakeFragmentedCord(
507       {"this", " ", "is", " ", "a", " ", "fragmented", " ", "cord"});
508 
509   EXPECT_TRUE(flat_haystack.Contains(""));
510   EXPECT_TRUE(fragmented_haystack.Contains(""));
511   EXPECT_TRUE(flat_haystack.Contains(absl::Cord("")));
512   EXPECT_TRUE(fragmented_haystack.Contains(absl::Cord("")));
513   EXPECT_TRUE(absl::Cord("").Contains(""));
514   EXPECT_TRUE(absl::Cord("").Contains(absl::Cord("")));
515   EXPECT_FALSE(absl::Cord("").Contains(flat_haystack));
516   EXPECT_FALSE(absl::Cord("").Contains(fragmented_haystack));
517 
518   EXPECT_FALSE(flat_haystack.Contains("z"));
519   EXPECT_FALSE(fragmented_haystack.Contains("z"));
520   EXPECT_FALSE(flat_haystack.Contains(absl::Cord("z")));
521   EXPECT_FALSE(fragmented_haystack.Contains(absl::Cord("z")));
522 
523   EXPECT_FALSE(flat_haystack.Contains("is an"));
524   EXPECT_FALSE(fragmented_haystack.Contains("is an"));
525   EXPECT_FALSE(flat_haystack.Contains(absl::Cord("is an")));
526   EXPECT_FALSE(fragmented_haystack.Contains(absl::Cord("is an")));
527   EXPECT_FALSE(
528       flat_haystack.Contains(absl::MakeFragmentedCord({"is", " ", "an"})));
529   EXPECT_FALSE(fragmented_haystack.Contains(
530       absl::MakeFragmentedCord({"is", " ", "an"})));
531 
532   EXPECT_TRUE(flat_haystack.Contains("is a"));
533   EXPECT_TRUE(fragmented_haystack.Contains("is a"));
534   EXPECT_TRUE(flat_haystack.Contains(absl::Cord("is a")));
535   EXPECT_TRUE(fragmented_haystack.Contains(absl::Cord("is a")));
536   EXPECT_TRUE(
537       flat_haystack.Contains(absl::MakeFragmentedCord({"is", " ", "a"})));
538   EXPECT_TRUE(
539       fragmented_haystack.Contains(absl::MakeFragmentedCord({"is", " ", "a"})));
540 }
541 
TEST_P(CordTest,Find)542 TEST_P(CordTest, Find) {
543   auto flat_haystack = absl::Cord("this is a flat cord");
544   auto fragmented_haystack = absl::MakeFragmentedCord(
545       {"this", " ", "is", " ", "a", " ", "fragmented", " ", "cord"});
546   auto empty_haystack = absl::Cord("");
547 
548   EXPECT_EQ(flat_haystack.Find(""), flat_haystack.char_begin());
549   EXPECT_EQ(fragmented_haystack.Find(""), fragmented_haystack.char_begin());
550   EXPECT_EQ(flat_haystack.Find(absl::Cord("")), flat_haystack.char_begin());
551   EXPECT_EQ(fragmented_haystack.Find(absl::Cord("")),
552             fragmented_haystack.char_begin());
553   EXPECT_EQ(empty_haystack.Find(""), empty_haystack.char_begin());
554   EXPECT_EQ(empty_haystack.Find(absl::Cord("")), empty_haystack.char_begin());
555   EXPECT_EQ(empty_haystack.Find(flat_haystack), empty_haystack.char_end());
556   EXPECT_EQ(empty_haystack.Find(fragmented_haystack),
557             empty_haystack.char_end());
558 
559   EXPECT_EQ(flat_haystack.Find("z"), flat_haystack.char_end());
560   EXPECT_EQ(fragmented_haystack.Find("z"), fragmented_haystack.char_end());
561   EXPECT_EQ(flat_haystack.Find(absl::Cord("z")), flat_haystack.char_end());
562   EXPECT_EQ(fragmented_haystack.Find(absl::Cord("z")),
563             fragmented_haystack.char_end());
564 
565   EXPECT_EQ(flat_haystack.Find("is an"), flat_haystack.char_end());
566   EXPECT_EQ(fragmented_haystack.Find("is an"), fragmented_haystack.char_end());
567   EXPECT_EQ(flat_haystack.Find(absl::Cord("is an")), flat_haystack.char_end());
568   EXPECT_EQ(fragmented_haystack.Find(absl::Cord("is an")),
569             fragmented_haystack.char_end());
570   EXPECT_EQ(flat_haystack.Find(absl::MakeFragmentedCord({"is", " ", "an"})),
571             flat_haystack.char_end());
572   EXPECT_EQ(
573       fragmented_haystack.Find(absl::MakeFragmentedCord({"is", " ", "an"})),
574       fragmented_haystack.char_end());
575 
576   EXPECT_EQ(flat_haystack.Find("is a"),
577             std::next(flat_haystack.char_begin(), 5));
578   EXPECT_EQ(fragmented_haystack.Find("is a"),
579             std::next(fragmented_haystack.char_begin(), 5));
580   EXPECT_EQ(flat_haystack.Find(absl::Cord("is a")),
581             std::next(flat_haystack.char_begin(), 5));
582   EXPECT_EQ(fragmented_haystack.Find(absl::Cord("is a")),
583             std::next(fragmented_haystack.char_begin(), 5));
584   EXPECT_EQ(flat_haystack.Find(absl::MakeFragmentedCord({"is", " ", "a"})),
585             std::next(flat_haystack.char_begin(), 5));
586   EXPECT_EQ(
587       fragmented_haystack.Find(absl::MakeFragmentedCord({"is", " ", "a"})),
588       std::next(fragmented_haystack.char_begin(), 5));
589 }
590 
TEST_P(CordTest,Subcord)591 TEST_P(CordTest, Subcord) {
592   RandomEngine rng(GTEST_FLAG_GET(random_seed));
593   const std::string s = RandomLowercaseString(&rng, 1024);
594 
595   absl::Cord a;
596   AppendWithFragments(s, &rng, &a);
597   MaybeHarden(a);
598   ASSERT_EQ(s, std::string(a));
599 
600   // Check subcords of a, from a variety of interesting points.
601   std::set<size_t> positions;
602   for (int i = 0; i <= 32; ++i) {
603     positions.insert(i);
604     positions.insert(i * 32 - 1);
605     positions.insert(i * 32);
606     positions.insert(i * 32 + 1);
607     positions.insert(a.size() - i);
608   }
609   positions.insert(237);
610   positions.insert(732);
611   for (size_t pos : positions) {
612     if (pos > a.size()) continue;
613     for (size_t end_pos : positions) {
614       if (end_pos < pos || end_pos > a.size()) continue;
615       absl::Cord sa = a.Subcord(pos, end_pos - pos);
616       ASSERT_EQ(absl::string_view(s).substr(pos, end_pos - pos),
617                 std::string(sa))
618           << a;
619       if (pos != 0 || end_pos != a.size()) {
620         ASSERT_EQ(sa.ExpectedChecksum(), absl::nullopt);
621       }
622     }
623   }
624 
625   // Do the same thing for an inline cord.
626   const std::string sh = "short";
627   absl::Cord c(sh);
628   for (size_t pos = 0; pos <= sh.size(); ++pos) {
629     for (size_t n = 0; n <= sh.size() - pos; ++n) {
630       absl::Cord sc = c.Subcord(pos, n);
631       ASSERT_EQ(sh.substr(pos, n), std::string(sc)) << c;
632     }
633   }
634 
635   // Check subcords of subcords.
636   absl::Cord sa = a.Subcord(0, a.size());
637   std::string ss = s.substr(0, s.size());
638   while (sa.size() > 1) {
639     sa = sa.Subcord(1, sa.size() - 2);
640     ss = ss.substr(1, ss.size() - 2);
641     ASSERT_EQ(ss, std::string(sa)) << a;
642     if (HasFailure()) break;  // halt cascade
643   }
644 
645   // It is OK to ask for too much.
646   sa = a.Subcord(0, a.size() + 1);
647   EXPECT_EQ(s, std::string(sa));
648 
649   // It is OK to ask for something beyond the end.
650   sa = a.Subcord(a.size() + 1, 0);
651   EXPECT_TRUE(sa.empty());
652   sa = a.Subcord(a.size() + 1, 1);
653   EXPECT_TRUE(sa.empty());
654 }
655 
TEST_P(CordTest,Swap)656 TEST_P(CordTest, Swap) {
657   absl::string_view a("Dexter");
658   absl::string_view b("Mandark");
659   absl::Cord x(a);
660   absl::Cord y(b);
661   MaybeHarden(x);
662   swap(x, y);
663   if (UseCrc()) {
664     ASSERT_EQ(x.ExpectedChecksum(), absl::nullopt);
665     ASSERT_EQ(y.ExpectedChecksum(), 1);
666   }
667   ASSERT_EQ(x, absl::Cord(b));
668   ASSERT_EQ(y, absl::Cord(a));
669   x.swap(y);
670   if (UseCrc()) {
671     ASSERT_EQ(x.ExpectedChecksum(), 1);
672     ASSERT_EQ(y.ExpectedChecksum(), absl::nullopt);
673   }
674   ASSERT_EQ(x, absl::Cord(a));
675   ASSERT_EQ(y, absl::Cord(b));
676 }
677 
VerifyCopyToString(const absl::Cord & cord)678 static void VerifyCopyToString(const absl::Cord& cord) {
679   std::string initially_empty;
680   absl::CopyCordToString(cord, &initially_empty);
681   EXPECT_EQ(initially_empty, cord);
682 
683   constexpr size_t kInitialLength = 1024;
684   std::string has_initial_contents(kInitialLength, 'x');
685   const char* address_before_copy = has_initial_contents.data();
686   absl::CopyCordToString(cord, &has_initial_contents);
687   EXPECT_EQ(has_initial_contents, cord);
688 
689   if (cord.size() <= kInitialLength) {
690     EXPECT_EQ(has_initial_contents.data(), address_before_copy)
691         << "CopyCordToString allocated new string storage; "
692            "has_initial_contents = \""
693         << has_initial_contents << "\"";
694   }
695 }
696 
TEST_P(CordTest,CopyToString)697 TEST_P(CordTest, CopyToString) {
698   VerifyCopyToString(absl::Cord());  // empty cords cannot carry CRCs
699   VerifyCopyToString(MaybeHardened(absl::Cord("small cord")));
700   VerifyCopyToString(MaybeHardened(
701       absl::MakeFragmentedCord({"fragmented ", "cord ", "to ", "test ",
702                                 "copying ", "to ", "a ", "string."})));
703 }
704 
VerifyAppendCordToString(const absl::Cord & cord)705 static void VerifyAppendCordToString(const absl::Cord& cord) {
706   std::string initially_empty;
707   absl::AppendCordToString(cord, &initially_empty);
708   EXPECT_EQ(initially_empty, cord);
709 
710   const absl::string_view kInitialContents = "initial contents.";
711   std::string expected_after_append =
712       absl::StrCat(kInitialContents, std::string(cord));
713 
714   std::string no_reserve(kInitialContents);
715   absl::AppendCordToString(cord, &no_reserve);
716   EXPECT_EQ(no_reserve, expected_after_append);
717 
718   std::string has_reserved_capacity(kInitialContents);
719   has_reserved_capacity.reserve(has_reserved_capacity.size() + cord.size());
720   const char* address_before_copy = has_reserved_capacity.data();
721   absl::AppendCordToString(cord, &has_reserved_capacity);
722   EXPECT_EQ(has_reserved_capacity, expected_after_append);
723   EXPECT_EQ(has_reserved_capacity.data(), address_before_copy)
724       << "AppendCordToString allocated new string storage; "
725          "has_reserved_capacity = \""
726       << has_reserved_capacity << "\"";
727 }
728 
TEST_P(CordTest,AppendToString)729 TEST_P(CordTest, AppendToString) {
730   VerifyAppendCordToString(absl::Cord());  // empty cords cannot carry CRCs
731   VerifyAppendCordToString(MaybeHardened(absl::Cord("small cord")));
732   VerifyAppendCordToString(MaybeHardened(
733       absl::MakeFragmentedCord({"fragmented ", "cord ", "to ", "test ",
734                                 "appending ", "to ", "a ", "string."})));
735 }
736 
TEST_P(CordTest,AppendEmptyBuffer)737 TEST_P(CordTest, AppendEmptyBuffer) {
738   absl::Cord cord;
739   cord.Append(absl::CordBuffer());
740   cord.Append(absl::CordBuffer::CreateWithDefaultLimit(2000));
741 }
742 
TEST_P(CordTest,AppendEmptyBufferToFlat)743 TEST_P(CordTest, AppendEmptyBufferToFlat) {
744   absl::Cord cord(std::string(2000, 'x'));
745   cord.Append(absl::CordBuffer());
746   cord.Append(absl::CordBuffer::CreateWithDefaultLimit(2000));
747 }
748 
TEST_P(CordTest,AppendEmptyBufferToTree)749 TEST_P(CordTest, AppendEmptyBufferToTree) {
750   absl::Cord cord(std::string(2000, 'x'));
751   cord.Append(std::string(2000, 'y'));
752   cord.Append(absl::CordBuffer());
753   cord.Append(absl::CordBuffer::CreateWithDefaultLimit(2000));
754 }
755 
TEST_P(CordTest,AppendSmallBuffer)756 TEST_P(CordTest, AppendSmallBuffer) {
757   absl::Cord cord;
758   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(3);
759   ASSERT_THAT(buffer.capacity(), Le(15));
760   memcpy(buffer.data(), "Abc", 3);
761   buffer.SetLength(3);
762   cord.Append(std::move(buffer));
763   EXPECT_EQ(buffer.length(), 0);    // NOLINT
764   EXPECT_GT(buffer.capacity(), 0);  // NOLINT
765 
766   buffer = absl::CordBuffer::CreateWithDefaultLimit(3);
767   memcpy(buffer.data(), "defgh", 5);
768   buffer.SetLength(5);
769   cord.Append(std::move(buffer));
770   EXPECT_EQ(buffer.length(), 0);    // NOLINT
771   EXPECT_GT(buffer.capacity(), 0);  // NOLINT
772 
773   EXPECT_THAT(cord.Chunks(), ElementsAre("Abcdefgh"));
774 }
775 
TEST_P(CordTest,AppendAndPrependBufferArePrecise)776 TEST_P(CordTest, AppendAndPrependBufferArePrecise) {
777   // Create a cord large enough to force 40KB flats.
778   std::string test_data(absl::cord_internal::kMaxFlatLength * 10, 'x');
779   absl::Cord cord1(test_data);
780   absl::Cord cord2(test_data);
781   const size_t size1 = cord1.EstimatedMemoryUsage();
782   const size_t size2 = cord2.EstimatedMemoryUsage();
783 
784   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(3);
785   memcpy(buffer.data(), "Abc", 3);
786   buffer.SetLength(3);
787   cord1.Append(std::move(buffer));
788 
789   buffer = absl::CordBuffer::CreateWithDefaultLimit(3);
790   memcpy(buffer.data(), "Abc", 3);
791   buffer.SetLength(3);
792   cord2.Prepend(std::move(buffer));
793 
794 #ifndef NDEBUG
795   // Allow 32 bytes new CordRepFlat, and 128 bytes for 'glue nodes'
796   constexpr size_t kMaxDelta = 128 + 32;
797 #else
798   // Allow 256 bytes extra for 'allocation debug overhead'
799   constexpr size_t kMaxDelta = 128 + 32 + 256;
800 #endif
801 
802   EXPECT_LE(cord1.EstimatedMemoryUsage() - size1, kMaxDelta);
803   EXPECT_LE(cord2.EstimatedMemoryUsage() - size2, kMaxDelta);
804 
805   EXPECT_EQ(cord1, absl::StrCat(test_data, "Abc"));
806   EXPECT_EQ(cord2, absl::StrCat("Abc", test_data));
807 }
808 
TEST_P(CordTest,PrependSmallBuffer)809 TEST_P(CordTest, PrependSmallBuffer) {
810   absl::Cord cord;
811   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(3);
812   ASSERT_THAT(buffer.capacity(), Le(15));
813   memcpy(buffer.data(), "Abc", 3);
814   buffer.SetLength(3);
815   cord.Prepend(std::move(buffer));
816   EXPECT_EQ(buffer.length(), 0);    // NOLINT
817   EXPECT_GT(buffer.capacity(), 0);  // NOLINT
818 
819   buffer = absl::CordBuffer::CreateWithDefaultLimit(3);
820   memcpy(buffer.data(), "defgh", 5);
821   buffer.SetLength(5);
822   cord.Prepend(std::move(buffer));
823   EXPECT_EQ(buffer.length(), 0);    // NOLINT
824   EXPECT_GT(buffer.capacity(), 0);  // NOLINT
825 
826   EXPECT_THAT(cord.Chunks(), ElementsAre("defghAbc"));
827 }
828 
TEST_P(CordTest,AppendLargeBuffer)829 TEST_P(CordTest, AppendLargeBuffer) {
830   absl::Cord cord;
831 
832   std::string s1(700, '1');
833   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(s1.size());
834   memcpy(buffer.data(), s1.data(), s1.size());
835   buffer.SetLength(s1.size());
836   cord.Append(std::move(buffer));
837   EXPECT_EQ(buffer.length(), 0);    // NOLINT
838   EXPECT_GT(buffer.capacity(), 0);  // NOLINT
839 
840   std::string s2(1000, '2');
841   buffer = absl::CordBuffer::CreateWithDefaultLimit(s2.size());
842   memcpy(buffer.data(), s2.data(), s2.size());
843   buffer.SetLength(s2.size());
844   cord.Append(std::move(buffer));
845   EXPECT_EQ(buffer.length(), 0);    // NOLINT
846   EXPECT_GT(buffer.capacity(), 0);  // NOLINT
847 
848   EXPECT_THAT(cord.Chunks(), ElementsAre(s1, s2));
849 }
850 
TEST_P(CordTest,PrependLargeBuffer)851 TEST_P(CordTest, PrependLargeBuffer) {
852   absl::Cord cord;
853 
854   std::string s1(700, '1');
855   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(s1.size());
856   memcpy(buffer.data(), s1.data(), s1.size());
857   buffer.SetLength(s1.size());
858   cord.Prepend(std::move(buffer));
859   EXPECT_EQ(buffer.length(), 0);    // NOLINT
860   EXPECT_GT(buffer.capacity(), 0);  // NOLINT
861 
862   std::string s2(1000, '2');
863   buffer = absl::CordBuffer::CreateWithDefaultLimit(s2.size());
864   memcpy(buffer.data(), s2.data(), s2.size());
865   buffer.SetLength(s2.size());
866   cord.Prepend(std::move(buffer));
867   EXPECT_EQ(buffer.length(), 0);    // NOLINT
868   EXPECT_GT(buffer.capacity(), 0);  // NOLINT
869 
870   EXPECT_THAT(cord.Chunks(), ElementsAre(s2, s1));
871 }
872 
873 class CordAppendBufferTest : public testing::TestWithParam<bool> {
874  public:
is_default() const875   size_t is_default() const { return GetParam(); }
876 
877   // Returns human readable string representation of the test parameter.
ToString(testing::TestParamInfo<bool> param)878   static std::string ToString(testing::TestParamInfo<bool> param) {
879     return param.param ? "DefaultLimit" : "CustomLimit";
880   }
881 
limit() const882   size_t limit() const {
883     return is_default() ? absl::CordBuffer::kDefaultLimit
884                         : absl::CordBuffer::kCustomLimit;
885   }
886 
maximum_payload() const887   size_t maximum_payload() const {
888     return is_default() ? absl::CordBuffer::MaximumPayload()
889                         : absl::CordBuffer::MaximumPayload(limit());
890   }
891 
GetAppendBuffer(absl::Cord & cord,size_t capacity,size_t min_capacity=16)892   absl::CordBuffer GetAppendBuffer(absl::Cord& cord, size_t capacity,
893                                    size_t min_capacity = 16) {
894     return is_default()
895                ? cord.GetAppendBuffer(capacity, min_capacity)
896                : cord.GetCustomAppendBuffer(limit(), capacity, min_capacity);
897   }
898 };
899 
900 INSTANTIATE_TEST_SUITE_P(WithParam, CordAppendBufferTest, testing::Bool(),
901                          CordAppendBufferTest::ToString);
902 
TEST_P(CordAppendBufferTest,GetAppendBufferOnEmptyCord)903 TEST_P(CordAppendBufferTest, GetAppendBufferOnEmptyCord) {
904   absl::Cord cord;
905   absl::CordBuffer buffer = GetAppendBuffer(cord, 1000);
906   EXPECT_GE(buffer.capacity(), 1000);
907   EXPECT_EQ(buffer.length(), 0);
908 }
909 
TEST_P(CordAppendBufferTest,GetAppendBufferOnInlinedCord)910 TEST_P(CordAppendBufferTest, GetAppendBufferOnInlinedCord) {
911   static constexpr int kInlinedSize = sizeof(absl::CordBuffer) - 1;
912   for (int size : {6, kInlinedSize - 3, kInlinedSize - 2, 1000}) {
913     absl::Cord cord("Abc");
914     absl::CordBuffer buffer = GetAppendBuffer(cord, size, 1);
915     EXPECT_GE(buffer.capacity(), 3 + size);
916     EXPECT_EQ(buffer.length(), 3);
917     EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), "Abc");
918     EXPECT_TRUE(cord.empty());
919   }
920 }
921 
TEST_P(CordAppendBufferTest,GetAppendBufferOnInlinedCordCapacityCloseToMax)922 TEST_P(CordAppendBufferTest, GetAppendBufferOnInlinedCordCapacityCloseToMax) {
923   // Cover the use case where we have a non empty inlined cord with some size
924   // 'n', and ask for something like 'uint64_max - k', assuming internal logic
925   // could overflow on 'uint64_max - k + size', and return a valid, but
926   // inefficiently smaller buffer if it would provide is the max allowed size.
927   for (size_t dist_from_max = 0; dist_from_max <= 4; ++dist_from_max) {
928     absl::Cord cord("Abc");
929     size_t size = std::numeric_limits<size_t>::max() - dist_from_max;
930     absl::CordBuffer buffer = GetAppendBuffer(cord, size, 1);
931     EXPECT_GE(buffer.capacity(), maximum_payload());
932     EXPECT_EQ(buffer.length(), 3);
933     EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), "Abc");
934     EXPECT_TRUE(cord.empty());
935   }
936 }
937 
TEST_P(CordAppendBufferTest,GetAppendBufferOnFlat)938 TEST_P(CordAppendBufferTest, GetAppendBufferOnFlat) {
939   // Create a cord with a single flat and extra capacity
940   absl::Cord cord;
941   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
942   const size_t expected_capacity = buffer.capacity();
943   buffer.SetLength(3);
944   memcpy(buffer.data(), "Abc", 3);
945   cord.Append(std::move(buffer));
946 
947   buffer = GetAppendBuffer(cord, 6);
948   EXPECT_EQ(buffer.capacity(), expected_capacity);
949   EXPECT_EQ(buffer.length(), 3);
950   EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), "Abc");
951   EXPECT_TRUE(cord.empty());
952 }
953 
TEST_P(CordAppendBufferTest,GetAppendBufferOnFlatWithoutMinCapacity)954 TEST_P(CordAppendBufferTest, GetAppendBufferOnFlatWithoutMinCapacity) {
955   // Create a cord with a single flat and extra capacity
956   absl::Cord cord;
957   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
958   buffer.SetLength(30);
959   memset(buffer.data(), 'x', 30);
960   cord.Append(std::move(buffer));
961 
962   buffer = GetAppendBuffer(cord, 1000, 900);
963   EXPECT_GE(buffer.capacity(), 1000);
964   EXPECT_EQ(buffer.length(), 0);
965   EXPECT_EQ(cord, std::string(30, 'x'));
966 }
967 
TEST_P(CordAppendBufferTest,GetAppendBufferOnTree)968 TEST_P(CordAppendBufferTest, GetAppendBufferOnTree) {
969   RandomEngine rng;
970   for (int num_flats : {2, 3, 100}) {
971     // Create a cord with `num_flats` flats and extra capacity
972     absl::Cord cord;
973     std::string prefix;
974     std::string last;
975     for (int i = 0; i < num_flats - 1; ++i) {
976       prefix += last;
977       last = RandomLowercaseString(&rng, 10);
978       absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
979       buffer.SetLength(10);
980       memcpy(buffer.data(), last.data(), 10);
981       cord.Append(std::move(buffer));
982     }
983     absl::CordBuffer buffer = GetAppendBuffer(cord, 6);
984     EXPECT_GE(buffer.capacity(), 500);
985     EXPECT_EQ(buffer.length(), 10);
986     EXPECT_EQ(absl::string_view(buffer.data(), buffer.length()), last);
987     EXPECT_EQ(cord, prefix);
988   }
989 }
990 
TEST_P(CordAppendBufferTest,GetAppendBufferOnTreeWithoutMinCapacity)991 TEST_P(CordAppendBufferTest, GetAppendBufferOnTreeWithoutMinCapacity) {
992   absl::Cord cord;
993   for (int i = 0; i < 2; ++i) {
994     absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
995     buffer.SetLength(3);
996     memcpy(buffer.data(), i ? "def" : "Abc", 3);
997     cord.Append(std::move(buffer));
998   }
999   absl::CordBuffer buffer = GetAppendBuffer(cord, 1000, 900);
1000   EXPECT_GE(buffer.capacity(), 1000);
1001   EXPECT_EQ(buffer.length(), 0);
1002   EXPECT_EQ(cord, "Abcdef");
1003 }
1004 
TEST_P(CordAppendBufferTest,GetAppendBufferOnSubstring)1005 TEST_P(CordAppendBufferTest, GetAppendBufferOnSubstring) {
1006   // Create a large cord with a single flat and some extra capacity
1007   absl::Cord cord;
1008   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
1009   buffer.SetLength(450);
1010   memset(buffer.data(), 'x', 450);
1011   cord.Append(std::move(buffer));
1012   cord.RemovePrefix(1);
1013 
1014   // Deny on substring
1015   buffer = GetAppendBuffer(cord, 6);
1016   EXPECT_EQ(buffer.length(), 0);
1017   EXPECT_EQ(cord, std::string(449, 'x'));
1018 }
1019 
TEST_P(CordAppendBufferTest,GetAppendBufferOnSharedCord)1020 TEST_P(CordAppendBufferTest, GetAppendBufferOnSharedCord) {
1021   // Create a shared cord with a single flat and extra capacity
1022   absl::Cord cord;
1023   absl::CordBuffer buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
1024   buffer.SetLength(3);
1025   memcpy(buffer.data(), "Abc", 3);
1026   cord.Append(std::move(buffer));
1027   absl::Cord shared_cord = cord;
1028 
1029   // Deny on flat
1030   buffer = GetAppendBuffer(cord, 6);
1031   EXPECT_EQ(buffer.length(), 0);
1032   EXPECT_EQ(cord, "Abc");
1033 
1034   buffer = absl::CordBuffer::CreateWithDefaultLimit(500);
1035   buffer.SetLength(3);
1036   memcpy(buffer.data(), "def", 3);
1037   cord.Append(std::move(buffer));
1038   shared_cord = cord;
1039 
1040   // Deny on tree
1041   buffer = GetAppendBuffer(cord, 6);
1042   EXPECT_EQ(buffer.length(), 0);
1043   EXPECT_EQ(cord, "Abcdef");
1044 }
1045 
TEST_P(CordTest,TryFlatEmpty)1046 TEST_P(CordTest, TryFlatEmpty) {
1047   absl::Cord c;
1048   EXPECT_EQ(c.TryFlat(), "");
1049 }
1050 
TEST_P(CordTest,TryFlatFlat)1051 TEST_P(CordTest, TryFlatFlat) {
1052   absl::Cord c("hello");
1053   MaybeHarden(c);
1054   EXPECT_EQ(c.TryFlat(), "hello");
1055 }
1056 
TEST_P(CordTest,TryFlatSubstrInlined)1057 TEST_P(CordTest, TryFlatSubstrInlined) {
1058   absl::Cord c("hello");
1059   c.RemovePrefix(1);
1060   MaybeHarden(c);
1061   EXPECT_EQ(c.TryFlat(), "ello");
1062 }
1063 
TEST_P(CordTest,TryFlatSubstrFlat)1064 TEST_P(CordTest, TryFlatSubstrFlat) {
1065   absl::Cord c("longer than 15 bytes");
1066   absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
1067   MaybeHarden(sub);
1068   EXPECT_EQ(sub.TryFlat(), "onger than 15 bytes");
1069 }
1070 
TEST_P(CordTest,TryFlatConcat)1071 TEST_P(CordTest, TryFlatConcat) {
1072   absl::Cord c = absl::MakeFragmentedCord({"hel", "lo"});
1073   MaybeHarden(c);
1074   EXPECT_EQ(c.TryFlat(), absl::nullopt);
1075 }
1076 
TEST_P(CordTest,TryFlatExternal)1077 TEST_P(CordTest, TryFlatExternal) {
1078   absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
1079   MaybeHarden(c);
1080   EXPECT_EQ(c.TryFlat(), "hell");
1081 }
1082 
TEST_P(CordTest,TryFlatSubstrExternal)1083 TEST_P(CordTest, TryFlatSubstrExternal) {
1084   absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
1085   absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
1086   MaybeHarden(sub);
1087   EXPECT_EQ(sub.TryFlat(), "ell");
1088 }
1089 
TEST_P(CordTest,TryFlatCommonlyAssumedInvariants)1090 TEST_P(CordTest, TryFlatCommonlyAssumedInvariants) {
1091   // The behavior tested below is not part of the API contract of Cord, but it's
1092   // something we intend to be true in our current implementation.  This test
1093   // exists to detect and prevent accidental breakage of the implementation.
1094   absl::string_view fragments[] = {"A fragmented test",
1095                                    " cord",
1096                                    " to test subcords",
1097                                    " of ",
1098                                    "a",
1099                                    " cord for",
1100                                    " each chunk "
1101                                    "returned by the ",
1102                                    "iterator"};
1103   absl::Cord c = absl::MakeFragmentedCord(fragments);
1104   MaybeHarden(c);
1105   int fragment = 0;
1106   int offset = 0;
1107   absl::Cord::CharIterator itc = c.char_begin();
1108   for (absl::string_view sv : c.Chunks()) {
1109     absl::string_view expected = fragments[fragment];
1110     absl::Cord subcord1 = c.Subcord(offset, sv.length());
1111     absl::Cord subcord2 = absl::Cord::AdvanceAndRead(&itc, sv.size());
1112     EXPECT_EQ(subcord1.TryFlat(), expected);
1113     EXPECT_EQ(subcord2.TryFlat(), expected);
1114     ++fragment;
1115     offset += sv.length();
1116   }
1117 }
1118 
IsFlat(const absl::Cord & c)1119 static bool IsFlat(const absl::Cord& c) {
1120   return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end();
1121 }
1122 
VerifyFlatten(absl::Cord c)1123 static void VerifyFlatten(absl::Cord c) {
1124   std::string old_contents(c);
1125   absl::string_view old_flat;
1126   bool already_flat_and_non_empty = IsFlat(c) && !c.empty();
1127   if (already_flat_and_non_empty) {
1128     old_flat = *c.chunk_begin();
1129   }
1130   absl::string_view new_flat = c.Flatten();
1131 
1132   // Verify that the contents of the flattened Cord are correct.
1133   EXPECT_EQ(new_flat, old_contents);
1134   EXPECT_EQ(std::string(c), old_contents);
1135 
1136   // If the Cord contained data and was already flat, verify that the data
1137   // wasn't copied.
1138   if (already_flat_and_non_empty) {
1139     EXPECT_EQ(old_flat.data(), new_flat.data())
1140         << "Allocated new memory even though the Cord was already flat.";
1141   }
1142 
1143   // Verify that the flattened Cord is in fact flat.
1144   EXPECT_TRUE(IsFlat(c));
1145 }
1146 
TEST_P(CordTest,Flatten)1147 TEST_P(CordTest, Flatten) {
1148   VerifyFlatten(absl::Cord());
1149   VerifyFlatten(MaybeHardened(absl::Cord("small cord")));
1150   VerifyFlatten(
1151       MaybeHardened(absl::Cord("larger than small buffer optimization")));
1152   VerifyFlatten(MaybeHardened(
1153       absl::MakeFragmentedCord({"small ", "fragmented ", "cord"})));
1154 
1155   // Test with a cord that is longer than the largest flat buffer
1156   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1157   VerifyFlatten(MaybeHardened(absl::Cord(RandomLowercaseString(&rng, 8192))));
1158 }
1159 
1160 // Test data
1161 namespace {
1162 class TestData {
1163  private:
1164   std::vector<std::string> data_;
1165 
1166   // Return a std::string of the specified length.
MakeString(int length)1167   static std::string MakeString(int length) {
1168     std::string result;
1169     char buf[30];
1170     snprintf(buf, sizeof(buf), "(%d)", length);
1171     while (result.size() < length) {
1172       result += buf;
1173     }
1174     result.resize(length);
1175     return result;
1176   }
1177 
1178  public:
TestData()1179   TestData() {
1180     // short strings increasing in length by one
1181     for (int i = 0; i < 30; i++) {
1182       data_.push_back(MakeString(i));
1183     }
1184 
1185     // strings around half kMaxFlatLength
1186     static const int kMaxFlatLength = 4096 - 9;
1187     static const int kHalf = kMaxFlatLength / 2;
1188 
1189     for (int i = -10; i <= +10; i++) {
1190       data_.push_back(MakeString(kHalf + i));
1191     }
1192 
1193     for (int i = -10; i <= +10; i++) {
1194       data_.push_back(MakeString(kMaxFlatLength + i));
1195     }
1196   }
1197 
size() const1198   size_t size() const { return data_.size(); }
data(size_t i) const1199   const std::string& data(size_t i) const { return data_[i]; }
1200 };
1201 }  // namespace
1202 
TEST_P(CordTest,MultipleLengths)1203 TEST_P(CordTest, MultipleLengths) {
1204   TestData d;
1205   for (size_t i = 0; i < d.size(); i++) {
1206     std::string a = d.data(i);
1207 
1208     {  // Construct from Cord
1209       absl::Cord tmp(a);
1210       absl::Cord x(tmp);
1211       MaybeHarden(x);
1212       EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
1213     }
1214 
1215     {  // Construct from absl::string_view
1216       absl::Cord x(a);
1217       MaybeHarden(x);
1218       EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
1219     }
1220 
1221     {  // Append cord to self
1222       absl::Cord self(a);
1223       MaybeHarden(self);
1224       self.Append(self);
1225       EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
1226     }
1227 
1228     {  // Prepend cord to self
1229       absl::Cord self(a);
1230       MaybeHarden(self);
1231       self.Prepend(self);
1232       EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
1233     }
1234 
1235     // Try to append/prepend others
1236     for (size_t j = 0; j < d.size(); j++) {
1237       std::string b = d.data(j);
1238 
1239       {  // CopyFrom Cord
1240         absl::Cord x(a);
1241         absl::Cord y(b);
1242         MaybeHarden(x);
1243         x = y;
1244         EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
1245       }
1246 
1247       {  // CopyFrom absl::string_view
1248         absl::Cord x(a);
1249         MaybeHarden(x);
1250         x = b;
1251         EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
1252       }
1253 
1254       {  // Cord::Append(Cord)
1255         absl::Cord x(a);
1256         absl::Cord y(b);
1257         MaybeHarden(x);
1258         x.Append(y);
1259         EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
1260       }
1261 
1262       {  // Cord::Append(absl::string_view)
1263         absl::Cord x(a);
1264         MaybeHarden(x);
1265         x.Append(b);
1266         EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
1267       }
1268 
1269       {  // Cord::Prepend(Cord)
1270         absl::Cord x(a);
1271         absl::Cord y(b);
1272         MaybeHarden(x);
1273         x.Prepend(y);
1274         EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
1275       }
1276 
1277       {  // Cord::Prepend(absl::string_view)
1278         absl::Cord x(a);
1279         MaybeHarden(x);
1280         x.Prepend(b);
1281         EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
1282       }
1283     }
1284   }
1285 }
1286 
1287 namespace {
1288 
TEST_P(CordTest,RemoveSuffixWithExternalOrSubstring)1289 TEST_P(CordTest, RemoveSuffixWithExternalOrSubstring) {
1290   absl::Cord cord = absl::MakeCordFromExternal(
1291       "foo bar baz", [](absl::string_view s) { DoNothing(s, nullptr); });
1292   EXPECT_EQ("foo bar baz", std::string(cord));
1293 
1294   MaybeHarden(cord);
1295 
1296   // This RemoveSuffix() will wrap the EXTERNAL node in a SUBSTRING node.
1297   cord.RemoveSuffix(4);
1298   EXPECT_EQ("foo bar", std::string(cord));
1299 
1300   MaybeHarden(cord);
1301 
1302   // This RemoveSuffix() will adjust the SUBSTRING node in-place.
1303   cord.RemoveSuffix(4);
1304   EXPECT_EQ("foo", std::string(cord));
1305 }
1306 
TEST_P(CordTest,RemoveSuffixMakesZeroLengthNode)1307 TEST_P(CordTest, RemoveSuffixMakesZeroLengthNode) {
1308   absl::Cord c;
1309   c.Append(absl::Cord(std::string(100, 'x')));
1310   absl::Cord other_ref = c;  // Prevent inplace appends
1311   MaybeHarden(c);
1312   c.Append(absl::Cord(std::string(200, 'y')));
1313   c.RemoveSuffix(200);
1314   EXPECT_EQ(std::string(100, 'x'), std::string(c));
1315 }
1316 
1317 }  // namespace
1318 
1319 // CordSpliceTest contributed by hendrie.
1320 namespace {
1321 
1322 // Create a cord with an external memory block filled with 'z'
CordWithZedBlock(size_t size)1323 absl::Cord CordWithZedBlock(size_t size) {
1324   char* data = new char[size];
1325   if (size > 0) {
1326     memset(data, 'z', size);
1327   }
1328   absl::Cord cord = absl::MakeCordFromExternal(
1329       absl::string_view(data, size),
1330       [](absl::string_view s) { delete[] s.data(); });
1331   return cord;
1332 }
1333 
1334 // Establish that ZedBlock does what we think it does.
TEST_P(CordTest,CordSpliceTestZedBlock)1335 TEST_P(CordTest, CordSpliceTestZedBlock) {
1336   absl::Cord blob = CordWithZedBlock(10);
1337   MaybeHarden(blob);
1338   EXPECT_EQ(10, blob.size());
1339   std::string s;
1340   absl::CopyCordToString(blob, &s);
1341   EXPECT_EQ("zzzzzzzzzz", s);
1342 }
1343 
TEST_P(CordTest,CordSpliceTestZedBlock0)1344 TEST_P(CordTest, CordSpliceTestZedBlock0) {
1345   absl::Cord blob = CordWithZedBlock(0);
1346   MaybeHarden(blob);
1347   EXPECT_EQ(0, blob.size());
1348   std::string s;
1349   absl::CopyCordToString(blob, &s);
1350   EXPECT_EQ("", s);
1351 }
1352 
TEST_P(CordTest,CordSpliceTestZedBlockSuffix1)1353 TEST_P(CordTest, CordSpliceTestZedBlockSuffix1) {
1354   absl::Cord blob = CordWithZedBlock(10);
1355   MaybeHarden(blob);
1356   EXPECT_EQ(10, blob.size());
1357   absl::Cord suffix(blob);
1358   suffix.RemovePrefix(9);
1359   EXPECT_EQ(1, suffix.size());
1360   std::string s;
1361   absl::CopyCordToString(suffix, &s);
1362   EXPECT_EQ("z", s);
1363 }
1364 
1365 // Remove all of a prefix block
TEST_P(CordTest,CordSpliceTestZedBlockSuffix0)1366 TEST_P(CordTest, CordSpliceTestZedBlockSuffix0) {
1367   absl::Cord blob = CordWithZedBlock(10);
1368   MaybeHarden(blob);
1369   EXPECT_EQ(10, blob.size());
1370   absl::Cord suffix(blob);
1371   suffix.RemovePrefix(10);
1372   EXPECT_EQ(0, suffix.size());
1373   std::string s;
1374   absl::CopyCordToString(suffix, &s);
1375   EXPECT_EQ("", s);
1376 }
1377 
BigCord(size_t len,char v)1378 absl::Cord BigCord(size_t len, char v) {
1379   std::string s(len, v);
1380   return absl::Cord(s);
1381 }
1382 
1383 // Splice block into cord.
SpliceCord(const absl::Cord & blob,int64_t offset,const absl::Cord & block)1384 absl::Cord SpliceCord(const absl::Cord& blob, int64_t offset,
1385                       const absl::Cord& block) {
1386   CHECK_GE(offset, 0);
1387   CHECK_LE(static_cast<size_t>(offset) + block.size(), blob.size());
1388   absl::Cord result(blob);
1389   result.RemoveSuffix(blob.size() - offset);
1390   result.Append(block);
1391   absl::Cord suffix(blob);
1392   suffix.RemovePrefix(offset + block.size());
1393   result.Append(suffix);
1394   CHECK_EQ(blob.size(), result.size());
1395   return result;
1396 }
1397 
1398 // Taking an empty suffix of a block breaks appending.
TEST_P(CordTest,CordSpliceTestRemoveEntireBlock1)1399 TEST_P(CordTest, CordSpliceTestRemoveEntireBlock1) {
1400   absl::Cord zero = CordWithZedBlock(10);
1401   MaybeHarden(zero);
1402   absl::Cord suffix(zero);
1403   suffix.RemovePrefix(10);
1404   absl::Cord result;
1405   result.Append(suffix);
1406 }
1407 
TEST_P(CordTest,CordSpliceTestRemoveEntireBlock2)1408 TEST_P(CordTest, CordSpliceTestRemoveEntireBlock2) {
1409   absl::Cord zero = CordWithZedBlock(10);
1410   MaybeHarden(zero);
1411   absl::Cord prefix(zero);
1412   prefix.RemoveSuffix(10);
1413   absl::Cord suffix(zero);
1414   suffix.RemovePrefix(10);
1415   absl::Cord result(prefix);
1416   result.Append(suffix);
1417 }
1418 
TEST_P(CordTest,CordSpliceTestRemoveEntireBlock3)1419 TEST_P(CordTest, CordSpliceTestRemoveEntireBlock3) {
1420   absl::Cord blob = CordWithZedBlock(10);
1421   absl::Cord block = BigCord(10, 'b');
1422   MaybeHarden(blob);
1423   MaybeHarden(block);
1424   blob = SpliceCord(blob, 0, block);
1425 }
1426 
1427 struct CordCompareTestCase {
1428   template <typename LHS, typename RHS>
CordCompareTestCase__anondd0221c80b11::CordCompareTestCase1429   CordCompareTestCase(const LHS& lhs, const RHS& rhs, bool use_crc)
1430       : lhs_cord(lhs), rhs_cord(rhs) {
1431     if (use_crc) {
1432       lhs_cord.SetExpectedChecksum(1);
1433     }
1434   }
1435 
1436   absl::Cord lhs_cord;
1437   absl::Cord rhs_cord;
1438 };
1439 
__anondd0221c80d02(int x) 1440 const auto sign = [](int x) { return x == 0 ? 0 : (x > 0 ? 1 : -1); };
1441 
VerifyComparison(const CordCompareTestCase & test_case)1442 void VerifyComparison(const CordCompareTestCase& test_case) {
1443   std::string lhs_string(test_case.lhs_cord);
1444   std::string rhs_string(test_case.rhs_cord);
1445   int expected = sign(lhs_string.compare(rhs_string));
1446   EXPECT_EQ(expected, test_case.lhs_cord.Compare(test_case.rhs_cord))
1447       << "LHS=" << lhs_string << "; RHS=" << rhs_string;
1448   EXPECT_EQ(expected, test_case.lhs_cord.Compare(rhs_string))
1449       << "LHS=" << lhs_string << "; RHS=" << rhs_string;
1450   EXPECT_EQ(-expected, test_case.rhs_cord.Compare(test_case.lhs_cord))
1451       << "LHS=" << rhs_string << "; RHS=" << lhs_string;
1452   EXPECT_EQ(-expected, test_case.rhs_cord.Compare(lhs_string))
1453       << "LHS=" << rhs_string << "; RHS=" << lhs_string;
1454 }
1455 
TEST_P(CordTest,Compare)1456 TEST_P(CordTest, Compare) {
1457   absl::Cord subcord("aaaaaBBBBBcccccDDDDD");
1458   subcord = subcord.Subcord(3, 10);
1459 
1460   absl::Cord tmp("aaaaaaaaaaaaaaaa");
1461   tmp.Append("BBBBBBBBBBBBBBBB");
1462   absl::Cord concat = absl::Cord("cccccccccccccccc");
1463   concat.Append("DDDDDDDDDDDDDDDD");
1464   concat.Prepend(tmp);
1465 
1466   absl::Cord concat2("aaaaaaaaaaaaa");
1467   concat2.Append("aaaBBBBBBBBBBBBBBBBccccc");
1468   concat2.Append("cccccccccccDDDDDDDDDDDDDD");
1469   concat2.Append("DD");
1470 
1471   const bool use_crc = UseCrc();
1472 
1473   std::vector<CordCompareTestCase> test_cases = {{
1474       // Inline cords
1475       {"abcdef", "abcdef", use_crc},
1476       {"abcdef", "abcdee", use_crc},
1477       {"abcdef", "abcdeg", use_crc},
1478       {"bbcdef", "abcdef", use_crc},
1479       {"bbcdef", "abcdeg", use_crc},
1480       {"abcdefa", "abcdef", use_crc},
1481       {"abcdef", "abcdefa", use_crc},
1482 
1483       // Small flat cords
1484       {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDD", use_crc},
1485       {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBxccccDDDDD", use_crc},
1486       {"aaaaaBBBBBcxcccDDDDD", "aaaaaBBBBBcccccDDDDD", use_crc},
1487       {"aaaaaBBBBBxccccDDDDD", "aaaaaBBBBBcccccDDDDX", use_crc},
1488       {"aaaaaBBBBBcccccDDDDDa", "aaaaaBBBBBcccccDDDDD", use_crc},
1489       {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDDa", use_crc},
1490 
1491       // Subcords
1492       {subcord, subcord, use_crc},
1493       {subcord, "aaBBBBBccc", use_crc},
1494       {subcord, "aaBBBBBccd", use_crc},
1495       {subcord, "aaBBBBBccb", use_crc},
1496       {subcord, "aaBBBBBxcb", use_crc},
1497       {subcord, "aaBBBBBccca", use_crc},
1498       {subcord, "aaBBBBBcc", use_crc},
1499 
1500       // Concats
1501       {concat, concat, use_crc},
1502       {concat,
1503        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDD",
1504        use_crc},
1505       {concat,
1506        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBcccccccccccccccxDDDDDDDDDDDDDDDD",
1507        use_crc},
1508       {concat,
1509        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBacccccccccccccccDDDDDDDDDDDDDDDD",
1510        use_crc},
1511       {concat,
1512        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDD",
1513        use_crc},
1514       {concat,
1515        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDDe",
1516        use_crc},
1517 
1518       {concat, concat2, use_crc},
1519   }};
1520 
1521   for (const auto& tc : test_cases) {
1522     VerifyComparison(tc);
1523   }
1524 }
1525 
TEST_P(CordTest,CompareAfterAssign)1526 TEST_P(CordTest, CompareAfterAssign) {
1527   absl::Cord a("aaaaaa1111111");
1528   absl::Cord b("aaaaaa2222222");
1529   MaybeHarden(a);
1530   a = "cccccc";
1531   b = "cccccc";
1532   EXPECT_EQ(a, b);
1533   EXPECT_FALSE(a < b);
1534 
1535   a = "aaaa";
1536   b = "bbbbb";
1537   a = "";
1538   b = "";
1539   EXPECT_EQ(a, b);
1540   EXPECT_FALSE(a < b);
1541 }
1542 
1543 // Test CompareTo() and ComparePrefix() against string and substring
1544 // comparison methods from basic_string.
TestCompare(const absl::Cord & c,const absl::Cord & d,RandomEngine * rng)1545 static void TestCompare(const absl::Cord& c, const absl::Cord& d,
1546                         RandomEngine* rng) {
1547   // char_traits<char>::lt is guaranteed to do an unsigned comparison:
1548   // https://en.cppreference.com/w/cpp/string/char_traits/cmp. We also expect
1549   // Cord comparisons to be based on unsigned byte comparisons regardless of
1550   // whether char is signed.
1551   int expected = sign(std::string(c).compare(std::string(d)));
1552   EXPECT_EQ(expected, sign(c.Compare(d))) << c << ", " << d;
1553 }
1554 
TEST_P(CordTest,CompareComparisonIsUnsigned)1555 TEST_P(CordTest, CompareComparisonIsUnsigned) {
1556   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1557   std::uniform_int_distribution<uint32_t> uniform_uint8(0, 255);
1558   char x = static_cast<char>(uniform_uint8(rng));
1559   TestCompare(
1560       absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x)),
1561       absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x ^ 0x80)), &rng);
1562 }
1563 
TEST_P(CordTest,CompareRandomComparisons)1564 TEST_P(CordTest, CompareRandomComparisons) {
1565   const int kIters = 5000;
1566   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1567 
1568   int n = GetUniformRandomUpTo(&rng, 5000);
1569   absl::Cord a[] = {MakeExternalCord(n),
1570                     absl::Cord("ant"),
1571                     absl::Cord("elephant"),
1572                     absl::Cord("giraffe"),
1573                     absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100),
1574                                            GetUniformRandomUpTo(&rng, 100))),
1575                     absl::Cord(""),
1576                     absl::Cord("x"),
1577                     absl::Cord("A"),
1578                     absl::Cord("B"),
1579                     absl::Cord("C")};
1580   for (int i = 0; i < kIters; i++) {
1581     absl::Cord c, d;
1582     for (int j = 0; j < (i % 7) + 1; j++) {
1583       c.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
1584       d.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
1585     }
1586     std::bernoulli_distribution coin_flip(0.5);
1587     MaybeHarden(c);
1588     MaybeHarden(d);
1589     TestCompare(coin_flip(rng) ? c : absl::Cord(std::string(c)),
1590                 coin_flip(rng) ? d : absl::Cord(std::string(d)), &rng);
1591   }
1592 }
1593 
1594 template <typename T1, typename T2>
CompareOperators()1595 void CompareOperators() {
1596   const T1 a("a");
1597   const T2 b("b");
1598 
1599   EXPECT_TRUE(a == a);
1600   // For pointer type (i.e. `const char*`), operator== compares the address
1601   // instead of the string, so `a == const char*("a")` isn't necessarily true.
1602   EXPECT_TRUE(std::is_pointer<T1>::value || a == T1("a"));
1603   EXPECT_TRUE(std::is_pointer<T2>::value || a == T2("a"));
1604   EXPECT_FALSE(a == b);
1605 
1606   EXPECT_TRUE(a != b);
1607   EXPECT_FALSE(a != a);
1608 
1609   EXPECT_TRUE(a < b);
1610   EXPECT_FALSE(b < a);
1611 
1612   EXPECT_TRUE(b > a);
1613   EXPECT_FALSE(a > b);
1614 
1615   EXPECT_TRUE(a >= a);
1616   EXPECT_TRUE(b >= a);
1617   EXPECT_FALSE(a >= b);
1618 
1619   EXPECT_TRUE(a <= a);
1620   EXPECT_TRUE(a <= b);
1621   EXPECT_FALSE(b <= a);
1622 }
1623 
TEST_P(CordTest,ComparisonOperators_Cord_Cord)1624 TEST_P(CordTest, ComparisonOperators_Cord_Cord) {
1625   CompareOperators<absl::Cord, absl::Cord>();
1626 }
1627 
TEST_P(CordTest,ComparisonOperators_Cord_StringPiece)1628 TEST_P(CordTest, ComparisonOperators_Cord_StringPiece) {
1629   CompareOperators<absl::Cord, absl::string_view>();
1630 }
1631 
TEST_P(CordTest,ComparisonOperators_StringPiece_Cord)1632 TEST_P(CordTest, ComparisonOperators_StringPiece_Cord) {
1633   CompareOperators<absl::string_view, absl::Cord>();
1634 }
1635 
TEST_P(CordTest,ComparisonOperators_Cord_string)1636 TEST_P(CordTest, ComparisonOperators_Cord_string) {
1637   CompareOperators<absl::Cord, std::string>();
1638 }
1639 
TEST_P(CordTest,ComparisonOperators_string_Cord)1640 TEST_P(CordTest, ComparisonOperators_string_Cord) {
1641   CompareOperators<std::string, absl::Cord>();
1642 }
1643 
TEST_P(CordTest,ComparisonOperators_stdstring_Cord)1644 TEST_P(CordTest, ComparisonOperators_stdstring_Cord) {
1645   CompareOperators<std::string, absl::Cord>();
1646 }
1647 
TEST_P(CordTest,ComparisonOperators_Cord_stdstring)1648 TEST_P(CordTest, ComparisonOperators_Cord_stdstring) {
1649   CompareOperators<absl::Cord, std::string>();
1650 }
1651 
TEST_P(CordTest,ComparisonOperators_charstar_Cord)1652 TEST_P(CordTest, ComparisonOperators_charstar_Cord) {
1653   CompareOperators<const char*, absl::Cord>();
1654 }
1655 
TEST_P(CordTest,ComparisonOperators_Cord_charstar)1656 TEST_P(CordTest, ComparisonOperators_Cord_charstar) {
1657   CompareOperators<absl::Cord, const char*>();
1658 }
1659 
TEST_P(CordTest,ConstructFromExternalReleaserInvoked)1660 TEST_P(CordTest, ConstructFromExternalReleaserInvoked) {
1661   // Empty external memory means the releaser should be called immediately.
1662   {
1663     bool invoked = false;
1664     auto releaser = [&invoked](absl::string_view) { invoked = true; };
1665     {
1666       auto c = absl::MakeCordFromExternal("", releaser);
1667       EXPECT_TRUE(invoked);
1668     }
1669   }
1670 
1671   // If the size of the data is small enough, a future constructor
1672   // implementation may copy the bytes and immediately invoke the releaser
1673   // instead of creating an external node. We make a large dummy std::string to
1674   // make this test independent of such an optimization.
1675   std::string large_dummy(2048, 'c');
1676   {
1677     bool invoked = false;
1678     auto releaser = [&invoked](absl::string_view) { invoked = true; };
1679     {
1680       auto c = absl::MakeCordFromExternal(large_dummy, releaser);
1681       EXPECT_FALSE(invoked);
1682     }
1683     EXPECT_TRUE(invoked);
1684   }
1685 
1686   {
1687     bool invoked = false;
1688     auto releaser = [&invoked](absl::string_view) { invoked = true; };
1689     {
1690       absl::Cord copy;
1691       {
1692         auto c = absl::MakeCordFromExternal(large_dummy, releaser);
1693         copy = c;
1694         EXPECT_FALSE(invoked);
1695       }
1696       EXPECT_FALSE(invoked);
1697     }
1698     EXPECT_TRUE(invoked);
1699   }
1700 }
1701 
TEST_P(CordTest,ConstructFromExternalCompareContents)1702 TEST_P(CordTest, ConstructFromExternalCompareContents) {
1703   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1704 
1705   for (int length = 1; length <= 2048; length *= 2) {
1706     std::string data = RandomLowercaseString(&rng, length);
1707     auto* external = new std::string(data);
1708     auto cord =
1709         absl::MakeCordFromExternal(*external, [external](absl::string_view sv) {
1710           EXPECT_EQ(external->data(), sv.data());
1711           EXPECT_EQ(external->size(), sv.size());
1712           delete external;
1713         });
1714     MaybeHarden(cord);
1715     EXPECT_EQ(data, cord);
1716   }
1717 }
1718 
TEST_P(CordTest,ConstructFromExternalLargeReleaser)1719 TEST_P(CordTest, ConstructFromExternalLargeReleaser) {
1720   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1721   constexpr size_t kLength = 256;
1722   std::string data = RandomLowercaseString(&rng, kLength);
1723   std::array<char, kLength> data_array;
1724   for (size_t i = 0; i < kLength; ++i) data_array[i] = data[i];
1725   bool invoked = false;
1726   auto releaser = [data_array, &invoked](absl::string_view data) {
1727     EXPECT_EQ(data, absl::string_view(data_array.data(), data_array.size()));
1728     invoked = true;
1729   };
1730   (void)MaybeHardened(absl::MakeCordFromExternal(data, releaser));
1731   EXPECT_TRUE(invoked);
1732 }
1733 
TEST_P(CordTest,ConstructFromExternalFunctionPointerReleaser)1734 TEST_P(CordTest, ConstructFromExternalFunctionPointerReleaser) {
1735   static absl::string_view data("hello world");
1736   static bool invoked;
1737   auto* releaser =
1738       static_cast<void (*)(absl::string_view)>([](absl::string_view sv) {
1739         EXPECT_EQ(data, sv);
1740         invoked = true;
1741       });
1742   invoked = false;
1743   (void)MaybeHardened(absl::MakeCordFromExternal(data, releaser));
1744   EXPECT_TRUE(invoked);
1745 
1746   invoked = false;
1747   (void)MaybeHardened(absl::MakeCordFromExternal(data, *releaser));
1748   EXPECT_TRUE(invoked);
1749 }
1750 
TEST_P(CordTest,ConstructFromExternalMoveOnlyReleaser)1751 TEST_P(CordTest, ConstructFromExternalMoveOnlyReleaser) {
1752   struct Releaser {
1753     explicit Releaser(bool* invoked) : invoked(invoked) {}
1754     Releaser(Releaser&& other) noexcept : invoked(other.invoked) {}
1755     void operator()(absl::string_view) const { *invoked = true; }
1756 
1757     bool* invoked;
1758   };
1759 
1760   bool invoked = false;
1761   (void)MaybeHardened(absl::MakeCordFromExternal("dummy", Releaser(&invoked)));
1762   EXPECT_TRUE(invoked);
1763 }
1764 
TEST_P(CordTest,ConstructFromExternalNoArgLambda)1765 TEST_P(CordTest, ConstructFromExternalNoArgLambda) {
1766   bool invoked = false;
1767   (void)MaybeHardened(
1768       absl::MakeCordFromExternal("dummy", [&invoked]() { invoked = true; }));
1769   EXPECT_TRUE(invoked);
1770 }
1771 
TEST_P(CordTest,ConstructFromExternalStringViewArgLambda)1772 TEST_P(CordTest, ConstructFromExternalStringViewArgLambda) {
1773   bool invoked = false;
1774   (void)MaybeHardened(absl::MakeCordFromExternal(
1775       "dummy", [&invoked](absl::string_view) { invoked = true; }));
1776   EXPECT_TRUE(invoked);
1777 }
1778 
TEST_P(CordTest,ConstructFromExternalNonTrivialReleaserDestructor)1779 TEST_P(CordTest, ConstructFromExternalNonTrivialReleaserDestructor) {
1780   struct Releaser {
1781     explicit Releaser(bool* destroyed) : destroyed(destroyed) {}
1782     ~Releaser() { *destroyed = true; }
1783     void operator()(absl::string_view) const {}
1784 
1785     bool* destroyed;
1786   };
1787 
1788   bool destroyed = false;
1789   Releaser releaser(&destroyed);
1790   (void)MaybeHardened(absl::MakeCordFromExternal("dummy", releaser));
1791   EXPECT_TRUE(destroyed);
1792 }
1793 
TEST_P(CordTest,ConstructFromExternalReferenceQualifierOverloads)1794 TEST_P(CordTest, ConstructFromExternalReferenceQualifierOverloads) {
1795   enum InvokedAs { kMissing, kLValue, kRValue };
1796   enum CopiedAs { kNone, kMove, kCopy };
1797   struct Tracker {
1798     CopiedAs copied_as = kNone;
1799     InvokedAs invoked_as = kMissing;
1800 
1801     void Record(InvokedAs rhs) {
1802       ASSERT_EQ(invoked_as, kMissing);
1803       invoked_as = rhs;
1804     }
1805 
1806     void Record(CopiedAs rhs) {
1807       if (copied_as == kNone || rhs == kCopy) copied_as = rhs;
1808     }
1809   } tracker;
1810 
1811   class Releaser {
1812    public:
1813     explicit Releaser(Tracker* tracker) : tr_(tracker) { *tracker = Tracker(); }
1814     Releaser(Releaser&& rhs) : tr_(rhs.tr_) { tr_->Record(kMove); }
1815     Releaser(const Releaser& rhs) : tr_(rhs.tr_) { tr_->Record(kCopy); }
1816 
1817     void operator()(absl::string_view) & { tr_->Record(kLValue); }
1818     void operator()(absl::string_view) && { tr_->Record(kRValue); }
1819 
1820    private:
1821     Tracker* tr_;
1822   };
1823 
1824   const Releaser releaser1(&tracker);
1825   (void)MaybeHardened(absl::MakeCordFromExternal("", releaser1));
1826   EXPECT_EQ(tracker.copied_as, kCopy);
1827   EXPECT_EQ(tracker.invoked_as, kRValue);
1828 
1829   const Releaser releaser2(&tracker);
1830   (void)MaybeHardened(absl::MakeCordFromExternal("", releaser2));
1831   EXPECT_EQ(tracker.copied_as, kCopy);
1832   EXPECT_EQ(tracker.invoked_as, kRValue);
1833 
1834   Releaser releaser3(&tracker);
1835   (void)MaybeHardened(absl::MakeCordFromExternal("", std::move(releaser3)));
1836   EXPECT_EQ(tracker.copied_as, kMove);
1837   EXPECT_EQ(tracker.invoked_as, kRValue);
1838 
1839   Releaser releaser4(&tracker);
1840   (void)MaybeHardened(absl::MakeCordFromExternal("dummy", releaser4));
1841   EXPECT_EQ(tracker.copied_as, kCopy);
1842   EXPECT_EQ(tracker.invoked_as, kRValue);
1843 
1844   const Releaser releaser5(&tracker);
1845   (void)MaybeHardened(absl::MakeCordFromExternal("dummy", releaser5));
1846   EXPECT_EQ(tracker.copied_as, kCopy);
1847   EXPECT_EQ(tracker.invoked_as, kRValue);
1848 
1849   Releaser releaser6(&tracker);
1850   (void)MaybeHardened(absl::MakeCordFromExternal("foo", std::move(releaser6)));
1851   EXPECT_EQ(tracker.copied_as, kMove);
1852   EXPECT_EQ(tracker.invoked_as, kRValue);
1853 }
1854 
TEST_P(CordTest,ExternalMemoryBasicUsage)1855 TEST_P(CordTest, ExternalMemoryBasicUsage) {
1856   static const char* strings[] = {"", "hello", "there"};
1857   for (const char* str : strings) {
1858     absl::Cord dst("(prefix)");
1859     MaybeHarden(dst);
1860     AddExternalMemory(str, &dst);
1861     MaybeHarden(dst);
1862     dst.Append("(suffix)");
1863     EXPECT_EQ((std::string("(prefix)") + str + std::string("(suffix)")),
1864               std::string(dst));
1865   }
1866 }
1867 
TEST_P(CordTest,ExternalMemoryRemovePrefixSuffix)1868 TEST_P(CordTest, ExternalMemoryRemovePrefixSuffix) {
1869   // Exhaustively try all sub-strings.
1870   absl::Cord cord = MakeComposite();
1871   std::string s = std::string(cord);
1872   for (int offset = 0; offset <= s.size(); offset++) {
1873     for (int length = 0; length <= s.size() - offset; length++) {
1874       absl::Cord result(cord);
1875       MaybeHarden(result);
1876       result.RemovePrefix(offset);
1877       MaybeHarden(result);
1878       result.RemoveSuffix(result.size() - length);
1879       EXPECT_EQ(s.substr(offset, length), std::string(result))
1880           << offset << " " << length;
1881     }
1882   }
1883 }
1884 
TEST_P(CordTest,ExternalMemoryGet)1885 TEST_P(CordTest, ExternalMemoryGet) {
1886   absl::Cord cord("hello");
1887   AddExternalMemory(" world!", &cord);
1888   MaybeHarden(cord);
1889   AddExternalMemory(" how are ", &cord);
1890   cord.Append(" you?");
1891   MaybeHarden(cord);
1892   std::string s = std::string(cord);
1893   for (int i = 0; i < s.size(); i++) {
1894     EXPECT_EQ(s[i], cord[i]);
1895   }
1896 }
1897 
1898 // CordMemoryUsage tests verify the correctness of the EstimatedMemoryUsage()
1899 // We use whiteboxed expectations based on our knowledge of the layout and size
1900 // of empty and inlined cords, and flat nodes.
1901 
1902 constexpr auto kFairShare = absl::CordMemoryAccounting::kFairShare;
1903 constexpr auto kTotalMorePrecise =
1904     absl::CordMemoryAccounting::kTotalMorePrecise;
1905 
1906 // Creates a cord of `n` `c` values, making sure no string stealing occurs.
MakeCord(size_t n,char c)1907 absl::Cord MakeCord(size_t n, char c) {
1908   const std::string s(n, c);
1909   return absl::Cord(s);
1910 }
1911 
TEST(CordTest,CordMemoryUsageEmpty)1912 TEST(CordTest, CordMemoryUsageEmpty) {
1913   absl::Cord cord;
1914   EXPECT_EQ(sizeof(absl::Cord), cord.EstimatedMemoryUsage());
1915   EXPECT_EQ(sizeof(absl::Cord), cord.EstimatedMemoryUsage(kFairShare));
1916   EXPECT_EQ(sizeof(absl::Cord), cord.EstimatedMemoryUsage(kTotalMorePrecise));
1917 }
1918 
TEST(CordTest,CordMemoryUsageInlined)1919 TEST(CordTest, CordMemoryUsageInlined) {
1920   absl::Cord a("hello");
1921   EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
1922   EXPECT_EQ(a.EstimatedMemoryUsage(kFairShare), sizeof(absl::Cord));
1923   EXPECT_EQ(a.EstimatedMemoryUsage(kTotalMorePrecise), sizeof(absl::Cord));
1924 }
1925 
TEST(CordTest,CordMemoryUsageExternalMemory)1926 TEST(CordTest, CordMemoryUsageExternalMemory) {
1927   absl::Cord cord;
1928   AddExternalMemory(std::string(1000, 'x'), &cord);
1929   const size_t expected =
1930       sizeof(absl::Cord) + 1000 + sizeof(CordRepExternal) + sizeof(intptr_t);
1931   EXPECT_EQ(cord.EstimatedMemoryUsage(), expected);
1932   EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare), expected);
1933   EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise), expected);
1934 }
1935 
TEST(CordTest,CordMemoryUsageFlat)1936 TEST(CordTest, CordMemoryUsageFlat) {
1937   absl::Cord cord = MakeCord(1000, 'a');
1938   const size_t flat_size =
1939       absl::CordTestPeer::Tree(cord)->flat()->AllocatedSize();
1940   EXPECT_EQ(cord.EstimatedMemoryUsage(), sizeof(absl::Cord) + flat_size);
1941   EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
1942             sizeof(absl::Cord) + flat_size);
1943   EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise),
1944             sizeof(absl::Cord) + flat_size);
1945 }
1946 
TEST(CordTest,CordMemoryUsageSubStringSharedFlat)1947 TEST(CordTest, CordMemoryUsageSubStringSharedFlat) {
1948   absl::Cord flat = MakeCord(2000, 'a');
1949   const size_t flat_size =
1950       absl::CordTestPeer::Tree(flat)->flat()->AllocatedSize();
1951   absl::Cord cord = flat.Subcord(500, 1000);
1952   EXPECT_EQ(cord.EstimatedMemoryUsage(),
1953             sizeof(absl::Cord) + sizeof(CordRepSubstring) + flat_size);
1954   EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise),
1955             sizeof(absl::Cord) + sizeof(CordRepSubstring) + flat_size);
1956   EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
1957             sizeof(absl::Cord) + sizeof(CordRepSubstring) + flat_size / 2);
1958 }
1959 
TEST(CordTest,CordMemoryUsageFlatShared)1960 TEST(CordTest, CordMemoryUsageFlatShared) {
1961   absl::Cord shared = MakeCord(1000, 'a');
1962   absl::Cord cord(shared);
1963   const size_t flat_size =
1964       absl::CordTestPeer::Tree(cord)->flat()->AllocatedSize();
1965   EXPECT_EQ(cord.EstimatedMemoryUsage(), sizeof(absl::Cord) + flat_size);
1966   EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise),
1967             sizeof(absl::Cord) + flat_size);
1968   EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
1969             sizeof(absl::Cord) + flat_size / 2);
1970 }
1971 
TEST(CordTest,CordMemoryUsageFlatHardenedAndShared)1972 TEST(CordTest, CordMemoryUsageFlatHardenedAndShared) {
1973   absl::Cord shared = MakeCord(1000, 'a');
1974   absl::Cord cord(shared);
1975   const size_t flat_size =
1976       absl::CordTestPeer::Tree(cord)->flat()->AllocatedSize();
1977   cord.SetExpectedChecksum(1);
1978   EXPECT_EQ(cord.EstimatedMemoryUsage(),
1979             sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size);
1980   EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
1981             sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size / 2);
1982 
1983   absl::Cord cord2(cord);
1984   EXPECT_EQ(cord2.EstimatedMemoryUsage(),
1985             sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size);
1986   EXPECT_EQ(cord2.EstimatedMemoryUsage(kTotalMorePrecise),
1987             sizeof(absl::Cord) + sizeof(CordRepCrc) + flat_size);
1988   EXPECT_EQ(cord2.EstimatedMemoryUsage(kFairShare),
1989             sizeof(absl::Cord) + (sizeof(CordRepCrc) + flat_size / 2) / 2);
1990 }
1991 
TEST(CordTest,CordMemoryUsageBTree)1992 TEST(CordTest, CordMemoryUsageBTree) {
1993   absl::Cord cord1;
1994   size_t flats1_size = 0;
1995   absl::Cord flats1[4] = {MakeCord(1000, 'a'), MakeCord(1100, 'a'),
1996                           MakeCord(1200, 'a'), MakeCord(1300, 'a')};
1997   for (absl::Cord flat : flats1) {
1998     flats1_size += absl::CordTestPeer::Tree(flat)->flat()->AllocatedSize();
1999     cord1.Append(std::move(flat));
2000   }
2001 
2002   // Make sure the created cord is a BTREE tree. Under some builds such as
2003   // windows DLL, we may have ODR like effects on the flag, meaning the DLL
2004   // code will run with the picked up default.
2005   if (!absl::CordTestPeer::Tree(cord1)->IsBtree()) {
2006     LOG(WARNING) << "Cord library code not respecting btree flag";
2007     return;
2008   }
2009 
2010   size_t rep1_size = sizeof(CordRepBtree) + flats1_size;
2011   size_t rep1_shared_size = sizeof(CordRepBtree) + flats1_size / 2;
2012 
2013   EXPECT_EQ(cord1.EstimatedMemoryUsage(), sizeof(absl::Cord) + rep1_size);
2014   EXPECT_EQ(cord1.EstimatedMemoryUsage(kTotalMorePrecise),
2015             sizeof(absl::Cord) + rep1_size);
2016   EXPECT_EQ(cord1.EstimatedMemoryUsage(kFairShare),
2017             sizeof(absl::Cord) + rep1_shared_size);
2018 
2019   absl::Cord cord2;
2020   size_t flats2_size = 0;
2021   absl::Cord flats2[4] = {MakeCord(600, 'a'), MakeCord(700, 'a'),
2022                           MakeCord(800, 'a'), MakeCord(900, 'a')};
2023   for (absl::Cord& flat : flats2) {
2024     flats2_size += absl::CordTestPeer::Tree(flat)->flat()->AllocatedSize();
2025     cord2.Append(std::move(flat));
2026   }
2027   size_t rep2_size = sizeof(CordRepBtree) + flats2_size;
2028 
2029   EXPECT_EQ(cord2.EstimatedMemoryUsage(), sizeof(absl::Cord) + rep2_size);
2030   EXPECT_EQ(cord2.EstimatedMemoryUsage(kTotalMorePrecise),
2031             sizeof(absl::Cord) + rep2_size);
2032   EXPECT_EQ(cord2.EstimatedMemoryUsage(kFairShare),
2033             sizeof(absl::Cord) + rep2_size);
2034 
2035   absl::Cord cord(cord1);
2036   cord.Append(std::move(cord2));
2037 
2038   EXPECT_EQ(cord.EstimatedMemoryUsage(),
2039             sizeof(absl::Cord) + sizeof(CordRepBtree) + rep1_size + rep2_size);
2040   EXPECT_EQ(cord.EstimatedMemoryUsage(kTotalMorePrecise),
2041             sizeof(absl::Cord) + sizeof(CordRepBtree) + rep1_size + rep2_size);
2042   EXPECT_EQ(cord.EstimatedMemoryUsage(kFairShare),
2043             sizeof(absl::Cord) + sizeof(CordRepBtree) + rep1_shared_size / 2 +
2044                 rep2_size);
2045 }
2046 
TEST(CordTest,TestHashFragmentation)2047 TEST(CordTest, TestHashFragmentation) {
2048   // Make sure we hit these boundary cases precisely.
2049   EXPECT_EQ(1024, absl::hash_internal::PiecewiseChunkSize());
2050   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
2051       absl::Cord(),
2052       absl::MakeFragmentedCord({std::string(600, 'a'), std::string(600, 'a')}),
2053       absl::MakeFragmentedCord({std::string(1200, 'a')}),
2054       absl::MakeFragmentedCord({std::string(900, 'b'), std::string(900, 'b')}),
2055       absl::MakeFragmentedCord({std::string(1800, 'b')}),
2056       absl::MakeFragmentedCord(
2057           {std::string(2000, 'c'), std::string(2000, 'c')}),
2058       absl::MakeFragmentedCord({std::string(4000, 'c')}),
2059       absl::MakeFragmentedCord({std::string(1024, 'd')}),
2060       absl::MakeFragmentedCord({std::string(1023, 'd'), "d"}),
2061       absl::MakeFragmentedCord({std::string(1025, 'e')}),
2062       absl::MakeFragmentedCord({std::string(1024, 'e'), "e"}),
2063       absl::MakeFragmentedCord({std::string(1023, 'e'), "e", "e"}),
2064   }));
2065 }
2066 
2067 // Regtest for a change that had to be rolled back because it expanded out
2068 // of the InlineRep too soon, which was observable through MemoryUsage().
TEST_P(CordTest,CordMemoryUsageInlineRep)2069 TEST_P(CordTest, CordMemoryUsageInlineRep) {
2070   constexpr size_t kMaxInline = 15;  // Cord::InlineRep::N
2071   const std::string small_string(kMaxInline, 'x');
2072   absl::Cord c1(small_string);
2073 
2074   absl::Cord c2;
2075   c2.Append(small_string);
2076   EXPECT_EQ(c1, c2);
2077   EXPECT_EQ(c1.EstimatedMemoryUsage(), c2.EstimatedMemoryUsage());
2078 }
2079 
TEST_P(CordTest,CordMemoryUsageTotalMorePreciseMode)2080 TEST_P(CordTest, CordMemoryUsageTotalMorePreciseMode) {
2081   constexpr size_t kChunkSize = 2000;
2082   std::string tmp_str(kChunkSize, 'x');
2083   const absl::Cord flat(std::move(tmp_str));
2084 
2085   // Construct `fragmented` with two references into the same
2086   // underlying buffer shared with `flat`:
2087   absl::Cord fragmented(flat);
2088   fragmented.Append(flat);
2089 
2090   // Memory usage of `flat`, minus the top-level Cord object:
2091   const size_t flat_internal_usage =
2092       flat.EstimatedMemoryUsage() - sizeof(absl::Cord);
2093 
2094   // `fragmented` holds a Cord and a CordRepBtree. That tree points to two
2095   // copies of flat's internals, which we expect to dedup:
2096   EXPECT_EQ(fragmented.EstimatedMemoryUsage(kTotalMorePrecise),
2097             sizeof(absl::Cord) +
2098             sizeof(CordRepBtree) +
2099             flat_internal_usage);
2100 
2101   // This is a case where kTotal produces an overestimate:
2102   EXPECT_EQ(fragmented.EstimatedMemoryUsage(),
2103             sizeof(absl::Cord) +
2104             sizeof(CordRepBtree) +
2105             2 * flat_internal_usage);
2106 }
2107 
TEST_P(CordTest,CordMemoryUsageTotalMorePreciseModeWithSubstring)2108 TEST_P(CordTest, CordMemoryUsageTotalMorePreciseModeWithSubstring) {
2109   constexpr size_t kChunkSize = 2000;
2110   std::string tmp_str(kChunkSize, 'x');
2111   const absl::Cord flat(std::move(tmp_str));
2112 
2113   // Construct `fragmented` with two references into the same
2114   // underlying buffer shared with `flat`.
2115   //
2116   // This time, each reference is through a Subcord():
2117   absl::Cord fragmented;
2118   fragmented.Append(flat.Subcord(1, kChunkSize - 2));
2119   fragmented.Append(flat.Subcord(1, kChunkSize - 2));
2120 
2121   // Memory usage of `flat`, minus the top-level Cord object:
2122   const size_t flat_internal_usage =
2123       flat.EstimatedMemoryUsage() - sizeof(absl::Cord);
2124 
2125   // `fragmented` holds a Cord and a CordRepBtree. That tree points to two
2126   // CordRepSubstrings, each pointing at flat's internals.
2127   EXPECT_EQ(fragmented.EstimatedMemoryUsage(kTotalMorePrecise),
2128             sizeof(absl::Cord) +
2129             sizeof(CordRepBtree) +
2130             2 * sizeof(CordRepSubstring) +
2131             flat_internal_usage);
2132 
2133   // This is a case where kTotal produces an overestimate:
2134   EXPECT_EQ(fragmented.EstimatedMemoryUsage(),
2135             sizeof(absl::Cord) +
2136             sizeof(CordRepBtree) +
2137             2 * sizeof(CordRepSubstring) +
2138             2 * flat_internal_usage);
2139 }
2140 }  // namespace
2141 
2142 // Regtest for 7510292 (fix a bug introduced by 7465150)
TEST_P(CordTest,Concat_Append)2143 TEST_P(CordTest, Concat_Append) {
2144   // Create a rep of type CONCAT
2145   absl::Cord s1("foobarbarbarbarbar");
2146   MaybeHarden(s1);
2147   s1.Append("abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg");
2148   size_t size = s1.size();
2149 
2150   // Create a copy of s1 and append to it.
2151   absl::Cord s2 = s1;
2152   MaybeHarden(s2);
2153   s2.Append("x");
2154 
2155   // 7465150 modifies s1 when it shouldn't.
2156   EXPECT_EQ(s1.size(), size);
2157   EXPECT_EQ(s2.size(), size + 1);
2158 }
2159 
TEST_P(CordTest,DiabolicalGrowth)2160 TEST_P(CordTest, DiabolicalGrowth) {
2161   // This test exercises a diabolical Append(<one char>) on a cord, making the
2162   // cord shared before each Append call resulting in a terribly fragmented
2163   // resulting cord.
2164   RandomEngine rng(GTEST_FLAG_GET(random_seed));
2165   const std::string expected = RandomLowercaseString(&rng, 5000);
2166   absl::Cord cord;
2167   for (char c : expected) {
2168     absl::Cord shared(cord);
2169     cord.Append(absl::string_view(&c, 1));
2170     MaybeHarden(cord);
2171   }
2172   std::string value;
2173   absl::CopyCordToString(cord, &value);
2174   EXPECT_EQ(value, expected);
2175   LOG(INFO) << "Diabolical size allocated = " << cord.EstimatedMemoryUsage();
2176 }
2177 
2178 // The following tests check support for >4GB cords in 64-bit binaries, and
2179 // 2GB-4GB cords in 32-bit binaries.  This function returns the large cord size
2180 // that's appropriate for the binary.
2181 
2182 // Construct a huge cord with the specified valid prefix.
MakeHuge(absl::string_view prefix)2183 static absl::Cord MakeHuge(absl::string_view prefix) {
2184   absl::Cord cord;
2185   if (sizeof(size_t) > 4) {
2186     // In 64-bit binaries, test 64-bit Cord support.
2187     const size_t size =
2188         static_cast<size_t>(std::numeric_limits<uint32_t>::max()) + 314;
2189     cord.Append(absl::MakeCordFromExternal(
2190         absl::string_view(prefix.data(), size),
2191         [](absl::string_view s) { DoNothing(s, nullptr); }));
2192   } else {
2193     // Cords are limited to 32-bit lengths in 32-bit binaries.  The following
2194     // tests check for use of "signed int" to represent Cord length/offset.
2195     // However absl::string_view does not allow lengths >= (1u<<31), so we need
2196     // to append in two parts;
2197     const size_t s1 = (1u << 31) - 1;
2198     // For shorter cord, `Append` copies the data rather than allocating a new
2199     // node. The threshold is currently set to 511, so `s2` needs to be bigger
2200     // to not trigger the copy.
2201     const size_t s2 = 600;
2202     cord.Append(absl::MakeCordFromExternal(
2203         absl::string_view(prefix.data(), s1),
2204         [](absl::string_view s) { DoNothing(s, nullptr); }));
2205     cord.Append(absl::MakeCordFromExternal(
2206         absl::string_view("", s2),
2207         [](absl::string_view s) { DoNothing(s, nullptr); }));
2208   }
2209   return cord;
2210 }
2211 
TEST_P(CordTest,HugeCord)2212 TEST_P(CordTest, HugeCord) {
2213   absl::Cord cord = MakeHuge("huge cord");
2214   MaybeHarden(cord);
2215 
2216   const size_t acceptable_delta =
2217       100 + (UseCrc() ? sizeof(absl::cord_internal::CordRepCrc) : 0);
2218   EXPECT_LE(cord.size(), cord.EstimatedMemoryUsage());
2219   EXPECT_GE(cord.size() + acceptable_delta, cord.EstimatedMemoryUsage());
2220 }
2221 
2222 // Tests that Append() works ok when handed a self reference
TEST_P(CordTest,AppendSelf)2223 TEST_P(CordTest, AppendSelf) {
2224   // Test the empty case.
2225   absl::Cord empty;
2226   MaybeHarden(empty);
2227   empty.Append(empty);
2228   ASSERT_EQ(empty, "");
2229 
2230   // We run the test until data is ~16K
2231   // This guarantees it covers small, medium and large data.
2232   std::string control_data = "Abc";
2233   absl::Cord data(control_data);
2234   while (control_data.length() < 0x4000) {
2235     MaybeHarden(data);
2236     data.Append(data);
2237     control_data.append(control_data);
2238     ASSERT_EQ(control_data, data);
2239   }
2240 }
2241 
TEST_P(CordTest,MakeFragmentedCordFromInitializerList)2242 TEST_P(CordTest, MakeFragmentedCordFromInitializerList) {
2243   absl::Cord fragmented =
2244       absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
2245 
2246   MaybeHarden(fragmented);
2247 
2248   EXPECT_EQ("A fragmented Cord", fragmented);
2249 
2250   auto chunk_it = fragmented.chunk_begin();
2251 
2252   ASSERT_TRUE(chunk_it != fragmented.chunk_end());
2253   EXPECT_EQ("A ", *chunk_it);
2254 
2255   ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
2256   EXPECT_EQ("fragmented ", *chunk_it);
2257 
2258   ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
2259   EXPECT_EQ("Cord", *chunk_it);
2260 
2261   ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
2262 }
2263 
TEST_P(CordTest,MakeFragmentedCordFromVector)2264 TEST_P(CordTest, MakeFragmentedCordFromVector) {
2265   std::vector<absl::string_view> chunks = {"A ", "fragmented ", "Cord"};
2266   absl::Cord fragmented = absl::MakeFragmentedCord(chunks);
2267 
2268   MaybeHarden(fragmented);
2269 
2270   EXPECT_EQ("A fragmented Cord", fragmented);
2271 
2272   auto chunk_it = fragmented.chunk_begin();
2273 
2274   ASSERT_TRUE(chunk_it != fragmented.chunk_end());
2275   EXPECT_EQ("A ", *chunk_it);
2276 
2277   ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
2278   EXPECT_EQ("fragmented ", *chunk_it);
2279 
2280   ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
2281   EXPECT_EQ("Cord", *chunk_it);
2282 
2283   ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
2284 }
2285 
TEST_P(CordTest,CordChunkIteratorTraits)2286 TEST_P(CordTest, CordChunkIteratorTraits) {
2287   static_assert(std::is_copy_constructible<absl::Cord::ChunkIterator>::value,
2288                 "");
2289   static_assert(std::is_copy_assignable<absl::Cord::ChunkIterator>::value, "");
2290 
2291   // Move semantics to satisfy swappable via std::swap
2292   static_assert(std::is_move_constructible<absl::Cord::ChunkIterator>::value,
2293                 "");
2294   static_assert(std::is_move_assignable<absl::Cord::ChunkIterator>::value, "");
2295 
2296   static_assert(
2297       std::is_same<
2298           std::iterator_traits<absl::Cord::ChunkIterator>::iterator_category,
2299           std::input_iterator_tag>::value,
2300       "");
2301   static_assert(
2302       std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::value_type,
2303                    absl::string_view>::value,
2304       "");
2305   static_assert(
2306       std::is_same<
2307           std::iterator_traits<absl::Cord::ChunkIterator>::difference_type,
2308           ptrdiff_t>::value,
2309       "");
2310   static_assert(
2311       std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::pointer,
2312                    const absl::string_view*>::value,
2313       "");
2314   static_assert(
2315       std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::reference,
2316                    absl::string_view>::value,
2317       "");
2318 }
2319 
VerifyChunkIterator(const absl::Cord & cord,size_t expected_chunks)2320 static void VerifyChunkIterator(const absl::Cord& cord,
2321                                 size_t expected_chunks) {
2322   EXPECT_EQ(cord.chunk_begin() == cord.chunk_end(), cord.empty()) << cord;
2323   EXPECT_EQ(cord.chunk_begin() != cord.chunk_end(), !cord.empty());
2324 
2325   absl::Cord::ChunkRange range = cord.Chunks();
2326   EXPECT_EQ(range.begin() == range.end(), cord.empty());
2327   EXPECT_EQ(range.begin() != range.end(), !cord.empty());
2328 
2329   std::string content(cord);
2330   size_t pos = 0;
2331   auto pre_iter = cord.chunk_begin(), post_iter = cord.chunk_begin();
2332   size_t n_chunks = 0;
2333   while (pre_iter != cord.chunk_end() && post_iter != cord.chunk_end()) {
2334     EXPECT_FALSE(pre_iter == cord.chunk_end());   // NOLINT: explicitly test ==
2335     EXPECT_FALSE(post_iter == cord.chunk_end());  // NOLINT
2336 
2337     EXPECT_EQ(pre_iter, post_iter);
2338     EXPECT_EQ(*pre_iter, *post_iter);
2339 
2340     EXPECT_EQ(pre_iter->data(), (*pre_iter).data());
2341     EXPECT_EQ(pre_iter->size(), (*pre_iter).size());
2342 
2343     absl::string_view chunk = *pre_iter;
2344     EXPECT_FALSE(chunk.empty());
2345     EXPECT_LE(pos + chunk.size(), content.size());
2346     EXPECT_EQ(absl::string_view(content.c_str() + pos, chunk.size()), chunk);
2347 
2348     int n_equal_iterators = 0;
2349     for (absl::Cord::ChunkIterator it = range.begin(); it != range.end();
2350          ++it) {
2351       n_equal_iterators += static_cast<int>(it == pre_iter);
2352     }
2353     EXPECT_EQ(n_equal_iterators, 1);
2354 
2355     ++pre_iter;
2356     EXPECT_EQ(*post_iter++, chunk);
2357 
2358     pos += chunk.size();
2359     ++n_chunks;
2360   }
2361   EXPECT_EQ(expected_chunks, n_chunks);
2362   EXPECT_EQ(pos, content.size());
2363   EXPECT_TRUE(pre_iter == cord.chunk_end());   // NOLINT: explicitly test ==
2364   EXPECT_TRUE(post_iter == cord.chunk_end());  // NOLINT
2365 }
2366 
TEST_P(CordTest,CordChunkIteratorOperations)2367 TEST_P(CordTest, CordChunkIteratorOperations) {
2368   absl::Cord empty_cord;
2369   VerifyChunkIterator(empty_cord, 0);
2370 
2371   absl::Cord small_buffer_cord("small cord");
2372   MaybeHarden(small_buffer_cord);
2373   VerifyChunkIterator(small_buffer_cord, 1);
2374 
2375   absl::Cord flat_node_cord("larger than small buffer optimization");
2376   MaybeHarden(flat_node_cord);
2377   VerifyChunkIterator(flat_node_cord, 1);
2378 
2379   VerifyChunkIterator(MaybeHardened(absl::MakeFragmentedCord(
2380                           {"a ", "small ", "fragmented ", "cord ", "for ",
2381                            "testing ", "chunk ", "iterations."})),
2382                       8);
2383 
2384   absl::Cord reused_nodes_cord(std::string(40, 'c'));
2385   reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'b')));
2386   MaybeHarden(reused_nodes_cord);
2387   reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'a')));
2388   size_t expected_chunks = 3;
2389   for (int i = 0; i < 8; ++i) {
2390     reused_nodes_cord.Prepend(reused_nodes_cord);
2391     MaybeHarden(reused_nodes_cord);
2392     expected_chunks *= 2;
2393     VerifyChunkIterator(reused_nodes_cord, expected_chunks);
2394   }
2395 
2396   RandomEngine rng(GTEST_FLAG_GET(random_seed));
2397   absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
2398   absl::Cord subcords;
2399   for (int i = 0; i < 128; ++i) subcords.Prepend(flat_cord.Subcord(i, 128));
2400   VerifyChunkIterator(subcords, 128);
2401 }
2402 
2403 
TEST_P(CordTest,AdvanceAndReadOnDataEdge)2404 TEST_P(CordTest, AdvanceAndReadOnDataEdge) {
2405   RandomEngine rng(GTEST_FLAG_GET(random_seed));
2406   const std::string data = RandomLowercaseString(&rng, 2000);
2407   for (bool as_flat : {true, false}) {
2408     SCOPED_TRACE(as_flat ? "Flat" : "External");
2409 
2410     absl::Cord cord =
2411         as_flat ? absl::Cord(data)
2412                 : absl::MakeCordFromExternal(data, [](absl::string_view) {});
2413     auto it = cord.Chars().begin();
2414 #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
2415     EXPECT_DEATH_IF_SUPPORTED(cord.AdvanceAndRead(&it, 2001), ".*");
2416 #endif
2417 
2418     it = cord.Chars().begin();
2419     absl::Cord frag = cord.AdvanceAndRead(&it, 2000);
2420     EXPECT_EQ(frag, data);
2421     EXPECT_TRUE(it == cord.Chars().end());
2422 
2423     it = cord.Chars().begin();
2424     frag = cord.AdvanceAndRead(&it, 200);
2425     EXPECT_EQ(frag, data.substr(0, 200));
2426     EXPECT_FALSE(it == cord.Chars().end());
2427 
2428     frag = cord.AdvanceAndRead(&it, 1500);
2429     EXPECT_EQ(frag, data.substr(200, 1500));
2430     EXPECT_FALSE(it == cord.Chars().end());
2431 
2432     frag = cord.AdvanceAndRead(&it, 300);
2433     EXPECT_EQ(frag, data.substr(1700, 300));
2434     EXPECT_TRUE(it == cord.Chars().end());
2435   }
2436 }
2437 
TEST_P(CordTest,AdvanceAndReadOnSubstringDataEdge)2438 TEST_P(CordTest, AdvanceAndReadOnSubstringDataEdge) {
2439   RandomEngine rng(GTEST_FLAG_GET(random_seed));
2440   const std::string data = RandomLowercaseString(&rng, 2500);
2441   for (bool as_flat : {true, false}) {
2442     SCOPED_TRACE(as_flat ? "Flat" : "External");
2443 
2444     absl::Cord cord =
2445         as_flat ? absl::Cord(data)
2446                 : absl::MakeCordFromExternal(data, [](absl::string_view) {});
2447     cord = cord.Subcord(200, 2000);
2448     const std::string substr = data.substr(200, 2000);
2449 
2450     auto it = cord.Chars().begin();
2451 #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
2452     EXPECT_DEATH_IF_SUPPORTED(cord.AdvanceAndRead(&it, 2001), ".*");
2453 #endif
2454 
2455     it = cord.Chars().begin();
2456     absl::Cord frag = cord.AdvanceAndRead(&it, 2000);
2457     EXPECT_EQ(frag, substr);
2458     EXPECT_TRUE(it == cord.Chars().end());
2459 
2460     it = cord.Chars().begin();
2461     frag = cord.AdvanceAndRead(&it, 200);
2462     EXPECT_EQ(frag, substr.substr(0, 200));
2463     EXPECT_FALSE(it == cord.Chars().end());
2464 
2465     frag = cord.AdvanceAndRead(&it, 1500);
2466     EXPECT_EQ(frag, substr.substr(200, 1500));
2467     EXPECT_FALSE(it == cord.Chars().end());
2468 
2469     frag = cord.AdvanceAndRead(&it, 300);
2470     EXPECT_EQ(frag, substr.substr(1700, 300));
2471     EXPECT_TRUE(it == cord.Chars().end());
2472   }
2473 }
2474 
TEST_P(CordTest,CharIteratorTraits)2475 TEST_P(CordTest, CharIteratorTraits) {
2476   static_assert(std::is_copy_constructible<absl::Cord::CharIterator>::value,
2477                 "");
2478   static_assert(std::is_copy_assignable<absl::Cord::CharIterator>::value, "");
2479 
2480   // Move semantics to satisfy swappable via std::swap
2481   static_assert(std::is_move_constructible<absl::Cord::CharIterator>::value,
2482                 "");
2483   static_assert(std::is_move_assignable<absl::Cord::CharIterator>::value, "");
2484 
2485   static_assert(
2486       std::is_same<
2487           std::iterator_traits<absl::Cord::CharIterator>::iterator_category,
2488           std::input_iterator_tag>::value,
2489       "");
2490   static_assert(
2491       std::is_same<std::iterator_traits<absl::Cord::CharIterator>::value_type,
2492                    char>::value,
2493       "");
2494   static_assert(
2495       std::is_same<
2496           std::iterator_traits<absl::Cord::CharIterator>::difference_type,
2497           ptrdiff_t>::value,
2498       "");
2499   static_assert(
2500       std::is_same<std::iterator_traits<absl::Cord::CharIterator>::pointer,
2501                    const char*>::value,
2502       "");
2503   static_assert(
2504       std::is_same<std::iterator_traits<absl::Cord::CharIterator>::reference,
2505                    const char&>::value,
2506       "");
2507 }
2508 
VerifyCharIterator(const absl::Cord & cord)2509 static void VerifyCharIterator(const absl::Cord& cord) {
2510   EXPECT_EQ(cord.char_begin() == cord.char_end(), cord.empty());
2511   EXPECT_EQ(cord.char_begin() != cord.char_end(), !cord.empty());
2512 
2513   absl::Cord::CharRange range = cord.Chars();
2514   EXPECT_EQ(range.begin() == range.end(), cord.empty());
2515   EXPECT_EQ(range.begin() != range.end(), !cord.empty());
2516 
2517   size_t i = 0;
2518   absl::Cord::CharIterator pre_iter = cord.char_begin();
2519   absl::Cord::CharIterator post_iter = cord.char_begin();
2520   std::string content(cord);
2521   while (pre_iter != cord.char_end() && post_iter != cord.char_end()) {
2522     EXPECT_FALSE(pre_iter == cord.char_end());   // NOLINT: explicitly test ==
2523     EXPECT_FALSE(post_iter == cord.char_end());  // NOLINT
2524 
2525     EXPECT_LT(i, cord.size());
2526     EXPECT_EQ(content[i], *pre_iter);
2527 
2528     EXPECT_EQ(pre_iter, post_iter);
2529     EXPECT_EQ(*pre_iter, *post_iter);
2530     EXPECT_EQ(&*pre_iter, &*post_iter);
2531 
2532     EXPECT_EQ(&*pre_iter, pre_iter.operator->());
2533 
2534     const char* character_address = &*pre_iter;
2535     absl::Cord::CharIterator copy = pre_iter;
2536     ++copy;
2537     EXPECT_EQ(character_address, &*pre_iter);
2538 
2539     int n_equal_iterators = 0;
2540     for (absl::Cord::CharIterator it = range.begin(); it != range.end(); ++it) {
2541       n_equal_iterators += static_cast<int>(it == pre_iter);
2542     }
2543     EXPECT_EQ(n_equal_iterators, 1);
2544 
2545     absl::Cord::CharIterator advance_iter = range.begin();
2546     absl::Cord::Advance(&advance_iter, i);
2547     EXPECT_EQ(pre_iter, advance_iter);
2548 
2549     advance_iter = range.begin();
2550     EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, i), cord.Subcord(0, i));
2551     EXPECT_EQ(pre_iter, advance_iter);
2552 
2553     advance_iter = pre_iter;
2554     absl::Cord::Advance(&advance_iter, cord.size() - i);
2555     EXPECT_EQ(range.end(), advance_iter);
2556 
2557     advance_iter = pre_iter;
2558     EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, cord.size() - i),
2559               cord.Subcord(i, cord.size() - i));
2560     EXPECT_EQ(range.end(), advance_iter);
2561 
2562     ++i;
2563     ++pre_iter;
2564     post_iter++;
2565   }
2566   EXPECT_EQ(i, cord.size());
2567   EXPECT_TRUE(pre_iter == cord.char_end());   // NOLINT: explicitly test ==
2568   EXPECT_TRUE(post_iter == cord.char_end());  // NOLINT
2569 
2570   absl::Cord::CharIterator zero_advanced_end = cord.char_end();
2571   absl::Cord::Advance(&zero_advanced_end, 0);
2572   EXPECT_EQ(zero_advanced_end, cord.char_end());
2573 
2574   absl::Cord::CharIterator it = cord.char_begin();
2575   for (absl::string_view chunk : cord.Chunks()) {
2576     while (!chunk.empty()) {
2577       EXPECT_EQ(absl::Cord::ChunkRemaining(it), chunk);
2578       chunk.remove_prefix(1);
2579       ++it;
2580     }
2581   }
2582 }
2583 
TEST_P(CordTest,CharIteratorOperations)2584 TEST_P(CordTest, CharIteratorOperations) {
2585   absl::Cord empty_cord;
2586   VerifyCharIterator(empty_cord);
2587 
2588   absl::Cord small_buffer_cord("small cord");
2589   MaybeHarden(small_buffer_cord);
2590   VerifyCharIterator(small_buffer_cord);
2591 
2592   absl::Cord flat_node_cord("larger than small buffer optimization");
2593   MaybeHarden(flat_node_cord);
2594   VerifyCharIterator(flat_node_cord);
2595 
2596   VerifyCharIterator(MaybeHardened(
2597       absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ",
2598                                 "testing ", "character ", "iteration."})));
2599 
2600   absl::Cord reused_nodes_cord("ghi");
2601   reused_nodes_cord.Prepend(absl::Cord("def"));
2602   reused_nodes_cord.Prepend(absl::Cord("abc"));
2603   for (int i = 0; i < 4; ++i) {
2604     reused_nodes_cord.Prepend(reused_nodes_cord);
2605     MaybeHarden(reused_nodes_cord);
2606     VerifyCharIterator(reused_nodes_cord);
2607   }
2608 
2609   RandomEngine rng(GTEST_FLAG_GET(random_seed));
2610   absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
2611   absl::Cord subcords;
2612   for (int i = 0; i < 4; ++i) {
2613     subcords.Prepend(flat_cord.Subcord(16 * i, 128));
2614     MaybeHarden(subcords);
2615   }
2616   VerifyCharIterator(subcords);
2617 }
2618 
TEST_P(CordTest,CharIteratorAdvanceAndRead)2619 TEST_P(CordTest, CharIteratorAdvanceAndRead) {
2620   // Create a Cord holding 6 flats of 2500 bytes each, and then iterate over it
2621   // reading 150, 1500, 2500 and 3000 bytes. This will result in all possible
2622   // partial, full and straddled read combinations including reads below
2623   // kMaxBytesToCopy. b/197776822 surfaced a bug for a specific partial, small
2624   // read 'at end' on Cord which caused a failure on attempting to read past the
2625   // end in CordRepBtreeReader which was not covered by any existing test.
2626   constexpr int kBlocks = 6;
2627   constexpr size_t kBlockSize = 2500;
2628   constexpr size_t kChunkSize1 = 1500;
2629   constexpr size_t kChunkSize2 = 2500;
2630   constexpr size_t kChunkSize3 = 3000;
2631   constexpr size_t kChunkSize4 = 150;
2632   RandomEngine rng;
2633   std::string data = RandomLowercaseString(&rng, kBlocks * kBlockSize);
2634   absl::Cord cord;
2635   for (int i = 0; i < kBlocks; ++i) {
2636     const std::string block = data.substr(i * kBlockSize, kBlockSize);
2637     cord.Append(absl::Cord(block));
2638   }
2639 
2640   MaybeHarden(cord);
2641 
2642   for (size_t chunk_size :
2643        {kChunkSize1, kChunkSize2, kChunkSize3, kChunkSize4}) {
2644     absl::Cord::CharIterator it = cord.char_begin();
2645     size_t offset = 0;
2646     while (offset < data.length()) {
2647       const size_t n = std::min<size_t>(data.length() - offset, chunk_size);
2648       absl::Cord chunk = cord.AdvanceAndRead(&it, n);
2649       ASSERT_EQ(chunk.size(), n);
2650       ASSERT_EQ(chunk.Compare(data.substr(offset, n)), 0);
2651       offset += n;
2652     }
2653   }
2654 }
2655 
TEST_P(CordTest,StreamingOutput)2656 TEST_P(CordTest, StreamingOutput) {
2657   absl::Cord c =
2658       absl::MakeFragmentedCord({"A ", "small ", "fragmented ", "Cord", "."});
2659   MaybeHarden(c);
2660   std::stringstream output;
2661   output << c;
2662   EXPECT_EQ("A small fragmented Cord.", output.str());
2663 }
2664 
TEST_P(CordTest,ForEachChunk)2665 TEST_P(CordTest, ForEachChunk) {
2666   for (int num_elements : {1, 10, 200}) {
2667     SCOPED_TRACE(num_elements);
2668     std::vector<std::string> cord_chunks;
2669     for (int i = 0; i < num_elements; ++i) {
2670       cord_chunks.push_back(absl::StrCat("[", i, "]"));
2671     }
2672     absl::Cord c = absl::MakeFragmentedCord(cord_chunks);
2673     MaybeHarden(c);
2674 
2675     std::vector<std::string> iterated_chunks;
2676     absl::CordTestPeer::ForEachChunk(c,
2677                                      [&iterated_chunks](absl::string_view sv) {
2678                                        iterated_chunks.emplace_back(sv);
2679                                      });
2680     EXPECT_EQ(iterated_chunks, cord_chunks);
2681   }
2682 }
2683 
TEST_P(CordTest,SmallBufferAssignFromOwnData)2684 TEST_P(CordTest, SmallBufferAssignFromOwnData) {
2685   constexpr size_t kMaxInline = 15;
2686   std::string contents = "small buff cord";
2687   EXPECT_EQ(contents.size(), kMaxInline);
2688   for (size_t pos = 0; pos < contents.size(); ++pos) {
2689     for (size_t count = contents.size() - pos; count > 0; --count) {
2690       absl::Cord c(contents);
2691       MaybeHarden(c);
2692       absl::string_view flat = c.Flatten();
2693       c = flat.substr(pos, count);
2694       EXPECT_EQ(c, contents.substr(pos, count))
2695           << "pos = " << pos << "; count = " << count;
2696     }
2697   }
2698 }
2699 
TEST_P(CordTest,Format)2700 TEST_P(CordTest, Format) {
2701   absl::Cord c;
2702   absl::Format(&c, "There were %04d little %s.", 3, "pigs");
2703   EXPECT_EQ(c, "There were 0003 little pigs.");
2704   MaybeHarden(c);
2705   absl::Format(&c, "And %-3llx bad wolf!", 1);
2706   MaybeHarden(c);
2707   EXPECT_EQ(c, "There were 0003 little pigs.And 1   bad wolf!");
2708 }
2709 
TEST_P(CordTest,Stringify)2710 TEST_P(CordTest, Stringify) {
2711   absl::Cord c =
2712       absl::MakeFragmentedCord({"A ", "small ", "fragmented ", "Cord", "."});
2713   MaybeHarden(c);
2714   EXPECT_EQ(absl::StrCat(c), "A small fragmented Cord.");
2715 }
2716 
TEST_P(CordTest,Hardening)2717 TEST_P(CordTest, Hardening) {
2718   absl::Cord cord("hello");
2719   MaybeHarden(cord);
2720 
2721   // These statement should abort the program in all builds modes.
2722   EXPECT_DEATH_IF_SUPPORTED(cord.RemovePrefix(6), "");
2723   EXPECT_DEATH_IF_SUPPORTED(cord.RemoveSuffix(6), "");
2724 
2725   bool test_hardening = false;
2726   ABSL_HARDENING_ASSERT([&]() {
2727     // This only runs when ABSL_HARDENING_ASSERT is active.
2728     test_hardening = true;
2729     return true;
2730   }());
2731   if (!test_hardening) return;
2732 
2733   EXPECT_DEATH_IF_SUPPORTED(cord[5], "");
2734   EXPECT_DEATH_IF_SUPPORTED(*cord.chunk_end(), "");
2735   EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), "");
2736   EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), "");
2737 }
2738 
2739 // This test mimics a specific (and rare) application repeatedly splitting a
2740 // cord, inserting (overwriting) a string value, and composing a new cord from
2741 // the three pieces. This is hostile towards a Btree implementation: A split of
2742 // a node at any level is likely to have the right-most edge of the left split,
2743 // and the left-most edge of the right split shared. For example, splitting a
2744 // leaf node with 6 edges will result likely in a 1-6, 2-5, 3-4, etc. split,
2745 // sharing the 'split node'. When recomposing such nodes, we 'injected' an edge
2746 // in that node. As this happens with some probability on each level of the
2747 // tree, this will quickly grow the tree until it reaches maximum height.
TEST_P(CordTest,BtreeHostileSplitInsertJoin)2748 TEST_P(CordTest, BtreeHostileSplitInsertJoin) {
2749   absl::BitGen bitgen;
2750 
2751   // Start with about 1GB of data
2752   std::string data(1 << 10, 'x');
2753   absl::Cord buffer(data);
2754   absl::Cord cord;
2755   for (int i = 0; i < 1000000; ++i) {
2756     cord.Append(buffer);
2757   }
2758 
2759   for (int j = 0; j < 1000; ++j) {
2760     MaybeHarden(cord);
2761     size_t offset = absl::Uniform(bitgen, 0u, cord.size());
2762     size_t length = absl::Uniform(bitgen, 100u, data.size());
2763     if (cord.size() == offset) {
2764       cord.Append(absl::string_view(data.data(), length));
2765     } else {
2766       absl::Cord suffix;
2767       if (offset + length < cord.size()) {
2768         suffix = cord;
2769         suffix.RemovePrefix(offset + length);
2770       }
2771       if (cord.size() > offset) {
2772         cord.RemoveSuffix(cord.size() - offset);
2773       }
2774       cord.Append(absl::string_view(data.data(), length));
2775       if (!suffix.empty()) {
2776         cord.Append(suffix);
2777       }
2778     }
2779   }
2780 }
2781 
2782 class AfterExitCordTester {
2783  public:
Set(absl::Cord * cord,absl::string_view expected)2784   bool Set(absl::Cord* cord, absl::string_view expected) {
2785     cord_ = cord;
2786     expected_ = expected;
2787     return true;
2788   }
2789 
~AfterExitCordTester()2790   ~AfterExitCordTester() {
2791     EXPECT_EQ(*cord_, expected_);
2792   }
2793  private:
2794   absl::Cord* cord_;
2795   absl::string_view expected_;
2796 };
2797 
2798 template <typename Str>
TestAfterExit(Str)2799 void TestAfterExit(Str) {
2800   const auto expected = Str::value;
2801   // Defined before `cord` to be destroyed after it.
2802   static AfterExitCordTester exit_tester;  // NOLINT
2803   static absl::NoDestructor<absl::Cord> cord_leaker(Str{});
2804   // cord_leaker is static, so this reference will remain valid through the end
2805   // of program execution.
2806   static absl::Cord& cord = *cord_leaker;
2807   static bool init_exit_tester = exit_tester.Set(&cord, expected);
2808   (void)init_exit_tester;
2809 
2810   EXPECT_EQ(cord, expected);
2811   // Copy the object and test the copy, and the original.
2812   {
2813     absl::Cord copy = cord;
2814     EXPECT_EQ(copy, expected);
2815   }
2816   // The original still works
2817   EXPECT_EQ(cord, expected);
2818 
2819   // Try making adding more structure to the tree.
2820   {
2821     absl::Cord copy = cord;
2822     std::string expected_copy(expected);
2823     for (int i = 0; i < 10; ++i) {
2824       copy.Append(cord);
2825       absl::StrAppend(&expected_copy, expected);
2826       EXPECT_EQ(copy, expected_copy);
2827     }
2828   }
2829 
2830   // Make sure we are using the right branch during constant evaluation.
2831   EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16);
2832 
2833   for (int i = 0; i < 10; ++i) {
2834     // Make a few more Cords from the same global rep.
2835     // This tests what happens when the refcount for it gets below 1.
2836     EXPECT_EQ(expected, absl::Cord(Str{}));
2837   }
2838 }
2839 
SimpleStrlen(const char * p)2840 constexpr int SimpleStrlen(const char* p) {
2841   return *p ? 1 + SimpleStrlen(p + 1) : 0;
2842 }
2843 
2844 struct ShortView {
operator ()ShortView2845   constexpr absl::string_view operator()() const {
2846     return absl::string_view("SSO string", SimpleStrlen("SSO string"));
2847   }
2848 };
2849 
2850 struct LongView {
operator ()LongView2851   constexpr absl::string_view operator()() const {
2852     return absl::string_view("String that does not fit SSO.",
2853                              SimpleStrlen("String that does not fit SSO."));
2854   }
2855 };
2856 
2857 
TEST_P(CordTest,AfterExit)2858 TEST_P(CordTest, AfterExit) {
2859   TestAfterExit(absl::strings_internal::MakeStringConstant(ShortView{}));
2860   TestAfterExit(absl::strings_internal::MakeStringConstant(LongView{}));
2861 }
2862 
2863 namespace {
2864 
2865 // Test helper that generates a populated cord for future manipulation.
2866 //
2867 // By test convention, all generated cords begin with the characters "abcde" at
2868 // the start of the first chunk.
2869 class PopulatedCordFactory {
2870  public:
PopulatedCordFactory(absl::string_view name,absl::Cord (* generator)())2871   constexpr PopulatedCordFactory(absl::string_view name,
2872                                  absl::Cord (*generator)())
2873       : name_(name), generator_(generator) {}
2874 
Name() const2875   absl::string_view Name() const { return name_; }
Generate() const2876   absl::Cord Generate() const { return generator_(); }
2877 
2878  private:
2879   absl::string_view name_;
2880   absl::Cord (*generator_)();
2881 };
2882 
2883 // clang-format off
2884 // This array is constant-initialized in conformant compilers.
2885 PopulatedCordFactory cord_factories[] = {
__anondd0221c81e02null2886   {"sso", [] { return absl::Cord("abcde"); }},
__anondd0221c81f02null2887   {"flat", [] {
2888     // Too large to live in SSO space, but small enough to be a simple FLAT.
2889     absl::Cord flat(absl::StrCat("abcde", std::string(1000, 'x')));
2890     flat.Flatten();
2891     return flat;
2892   }},
__anondd0221c82002null2893   {"external", [] {
2894     // A cheat: we are using a string literal as the external storage, so a
2895     // no-op releaser is correct here.
2896     return absl::MakeCordFromExternal("abcde External!", []{});
2897   }},
__anondd0221c82202null2898   {"external substring", [] {
2899     // A cheat: we are using a string literal as the external storage, so a
2900     // no-op releaser is correct here.
2901     absl::Cord ext = absl::MakeCordFromExternal("-abcde External!", []{});
2902     return absl::CordTestPeer::MakeSubstring(ext, 1, ext.size() - 1);
2903   }},
__anondd0221c82402null2904   {"substring", [] {
2905     absl::Cord flat(absl::StrCat("-abcde", std::string(1000, 'x')));
2906     flat.Flatten();
2907     return flat.Subcord(1, 998);
2908   }},
__anondd0221c82502null2909   {"fragmented", [] {
2910     std::string fragment = absl::StrCat("abcde", std::string(195, 'x'));
2911     std::vector<std::string> fragments(200, fragment);
2912     absl::Cord cord = absl::MakeFragmentedCord(fragments);
2913     assert(cord.size() == 40000);
2914     return cord;
2915   }},
2916 };
2917 // clang-format on
2918 
2919 // Test helper that can mutate a cord, and possibly undo the mutation, for
2920 // testing.
2921 class CordMutator {
2922  public:
CordMutator(absl::string_view name,void (* mutate)(absl::Cord &),void (* undo)(absl::Cord &)=nullptr)2923   constexpr CordMutator(absl::string_view name, void (*mutate)(absl::Cord&),
2924                         void (*undo)(absl::Cord&) = nullptr)
2925       : name_(name), mutate_(mutate), undo_(undo) {}
2926 
Name() const2927   absl::string_view Name() const { return name_; }
Mutate(absl::Cord & cord) const2928   void Mutate(absl::Cord& cord) const { mutate_(cord); }
CanUndo() const2929   bool CanUndo() const { return undo_ != nullptr; }
Undo(absl::Cord & cord) const2930   void Undo(absl::Cord& cord) const { undo_(cord); }
2931 
2932  private:
2933   absl::string_view name_;
2934   void (*mutate_)(absl::Cord&);
2935   void (*undo_)(absl::Cord&);
2936 };
2937 
2938 // clang-format off
2939 // This array is constant-initialized in conformant compilers.
2940 CordMutator cord_mutators[] = {
__anondd0221c82602() 2941   {"clear", [](absl::Cord& c) { c.Clear(); }},
__anondd0221c82702() 2942   {"overwrite", [](absl::Cord& c) { c = "overwritten"; }},
2943   {
2944     "append string",
__anondd0221c82802() 2945     [](absl::Cord& c) { c.Append("0123456789"); },
__anondd0221c82902() 2946     [](absl::Cord& c) { c.RemoveSuffix(10); }
2947   },
2948   {
2949     "append cord",
__anondd0221c82a02() 2950     [](absl::Cord& c) {
2951       c.Append(absl::MakeFragmentedCord({"12345", "67890"}));
2952     },
__anondd0221c82b02() 2953     [](absl::Cord& c) { c.RemoveSuffix(10); }
2954   },
2955   {
2956     "append checksummed cord",
__anondd0221c82c02() 2957     [](absl::Cord& c) {
2958       absl::Cord to_append = absl::MakeFragmentedCord({"12345", "67890"});
2959       to_append.SetExpectedChecksum(999);
2960       c.Append(to_append);
2961     },
__anondd0221c82d02() 2962     [](absl::Cord& c) { c.RemoveSuffix(10); }
2963   },
2964   {
2965     "append self",
__anondd0221c82e02() 2966     [](absl::Cord& c) { c.Append(c); },
__anondd0221c82f02() 2967     [](absl::Cord& c) { c.RemoveSuffix(c.size() / 2); }
2968   },
2969   {
2970     "append empty string",
__anondd0221c83002() 2971     [](absl::Cord& c) { c.Append(""); },
__anondd0221c83102() 2972     [](absl::Cord& c) { }
2973   },
2974   {
2975     "append empty cord",
__anondd0221c83202() 2976     [](absl::Cord& c) { c.Append(absl::Cord()); },
__anondd0221c83302() 2977     [](absl::Cord& c) { }
2978   },
2979   {
2980     "append empty checksummed cord",
__anondd0221c83402() 2981     [](absl::Cord& c) {
2982       absl::Cord to_append;
2983       to_append.SetExpectedChecksum(999);
2984       c.Append(to_append);
2985     },
__anondd0221c83502() 2986     [](absl::Cord& c) { }
2987   },
2988   {
2989     "prepend string",
__anondd0221c83602() 2990     [](absl::Cord& c) { c.Prepend("9876543210"); },
__anondd0221c83702() 2991     [](absl::Cord& c) { c.RemovePrefix(10); }
2992   },
2993   {
2994     "prepend cord",
__anondd0221c83802() 2995     [](absl::Cord& c) {
2996       c.Prepend(absl::MakeFragmentedCord({"98765", "43210"}));
2997     },
__anondd0221c83902() 2998     [](absl::Cord& c) { c.RemovePrefix(10); }
2999   },
3000   {
3001     "prepend checksummed cord",
__anondd0221c83a02() 3002     [](absl::Cord& c) {
3003       absl::Cord to_prepend = absl::MakeFragmentedCord({"98765", "43210"});
3004       to_prepend.SetExpectedChecksum(999);
3005       c.Prepend(to_prepend);
3006     },
__anondd0221c83b02() 3007     [](absl::Cord& c) { c.RemovePrefix(10); }
3008   },
3009   {
3010     "prepend empty string",
__anondd0221c83c02() 3011     [](absl::Cord& c) { c.Prepend(""); },
__anondd0221c83d02() 3012     [](absl::Cord& c) { }
3013   },
3014   {
3015     "prepend empty cord",
__anondd0221c83e02() 3016     [](absl::Cord& c) { c.Prepend(absl::Cord()); },
__anondd0221c83f02() 3017     [](absl::Cord& c) { }
3018   },
3019   {
3020     "prepend empty checksummed cord",
__anondd0221c84002() 3021     [](absl::Cord& c) {
3022       absl::Cord to_prepend;
3023       to_prepend.SetExpectedChecksum(999);
3024       c.Prepend(to_prepend);
3025     },
__anondd0221c84102() 3026     [](absl::Cord& c) { }
3027   },
3028   {
3029     "prepend self",
__anondd0221c84202() 3030     [](absl::Cord& c) { c.Prepend(c); },
__anondd0221c84302() 3031     [](absl::Cord& c) { c.RemovePrefix(c.size() / 2); }
3032   },
__anondd0221c84402() 3033   {"remove prefix", [](absl::Cord& c) { c.RemovePrefix(c.size() / 2); }},
__anondd0221c84502() 3034   {"remove suffix", [](absl::Cord& c) { c.RemoveSuffix(c.size() / 2); }},
__anondd0221c84602() 3035   {"remove 0-prefix", [](absl::Cord& c) { c.RemovePrefix(0); }},
__anondd0221c84702() 3036   {"remove 0-suffix", [](absl::Cord& c) { c.RemoveSuffix(0); }},
__anondd0221c84802() 3037   {"subcord", [](absl::Cord& c) { c = c.Subcord(1, c.size() - 2); }},
3038   {
3039     "swap inline",
__anondd0221c84902() 3040     [](absl::Cord& c) {
3041       absl::Cord other("swap");
3042       c.swap(other);
3043     }
3044   },
3045   {
3046     "swap tree",
__anondd0221c84a02() 3047     [](absl::Cord& c) {
3048       absl::Cord other(std::string(10000, 'x'));
3049       c.swap(other);
3050     }
3051   },
3052 };
3053 // clang-format on
3054 }  // namespace
3055 
TEST_P(CordTest,ExpectedChecksum)3056 TEST_P(CordTest, ExpectedChecksum) {
3057   for (const PopulatedCordFactory& factory : cord_factories) {
3058     SCOPED_TRACE(factory.Name());
3059     for (bool shared : {false, true}) {
3060       SCOPED_TRACE(shared);
3061 
3062       absl::Cord shared_cord_source = factory.Generate();
3063       auto make_instance = [=] {
3064         return shared ? shared_cord_source : factory.Generate();
3065       };
3066 
3067       const absl::Cord base_value = factory.Generate();
3068       const std::string base_value_as_string(factory.Generate().Flatten());
3069 
3070       absl::Cord c1 = make_instance();
3071       EXPECT_FALSE(c1.ExpectedChecksum().has_value());
3072 
3073       // Setting an expected checksum works, and retains the cord's bytes
3074       c1.SetExpectedChecksum(12345);
3075       EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
3076       EXPECT_EQ(c1, base_value);
3077 
3078       // Test that setting an expected checksum again doesn't crash or leak
3079       // memory.
3080       c1.SetExpectedChecksum(12345);
3081       EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
3082       EXPECT_EQ(c1, base_value);
3083 
3084       // CRC persists through copies, assignments, and moves:
3085       absl::Cord c1_copy_construct = c1;
3086       EXPECT_EQ(c1_copy_construct.ExpectedChecksum().value_or(0), 12345);
3087 
3088       absl::Cord c1_copy_assign;
3089       c1_copy_assign = c1;
3090       EXPECT_EQ(c1_copy_assign.ExpectedChecksum().value_or(0), 12345);
3091 
3092       absl::Cord c1_move(std::move(c1_copy_assign));
3093       EXPECT_EQ(c1_move.ExpectedChecksum().value_or(0), 12345);
3094 
3095       EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
3096 
3097       // A CRC Cord compares equal to its non-CRC value.
3098       EXPECT_EQ(c1, make_instance());
3099 
3100       for (const CordMutator& mutator : cord_mutators) {
3101         SCOPED_TRACE(mutator.Name());
3102 
3103         // Test that mutating a cord removes its stored checksum
3104         absl::Cord c2 = make_instance();
3105         c2.SetExpectedChecksum(24680);
3106 
3107         mutator.Mutate(c2);
3108 
3109         if (c1 == c2) {
3110           // Not a mutation (for example, appending the empty string).
3111           // Whether the checksum is removed is not defined.
3112           continue;
3113         }
3114 
3115         EXPECT_EQ(c2.ExpectedChecksum(), absl::nullopt);
3116 
3117         if (mutator.CanUndo()) {
3118           // Undoing an operation should not restore the checksum
3119           mutator.Undo(c2);
3120           EXPECT_EQ(c2, base_value);
3121           EXPECT_EQ(c2.ExpectedChecksum(), absl::nullopt);
3122         }
3123       }
3124 
3125       absl::Cord c3 = make_instance();
3126       c3.SetExpectedChecksum(999);
3127       const absl::Cord& cc3 = c3;
3128 
3129       // Test that all cord reading operations function in the face of an
3130       // expected checksum.
3131 
3132       // Test data precondition
3133       ASSERT_TRUE(cc3.StartsWith("abcde"));
3134 
3135       EXPECT_EQ(cc3.size(), base_value_as_string.size());
3136       EXPECT_FALSE(cc3.empty());
3137       EXPECT_EQ(cc3.Compare(base_value), 0);
3138       EXPECT_EQ(cc3.Compare(base_value_as_string), 0);
3139       EXPECT_EQ(cc3.Compare("wxyz"), -1);
3140       EXPECT_EQ(cc3.Compare(absl::Cord("wxyz")), -1);
3141       EXPECT_EQ(cc3.Compare("aaaa"), 1);
3142       EXPECT_EQ(cc3.Compare(absl::Cord("aaaa")), 1);
3143       EXPECT_EQ(absl::Cord("wxyz").Compare(cc3), 1);
3144       EXPECT_EQ(absl::Cord("aaaa").Compare(cc3), -1);
3145       EXPECT_TRUE(cc3.StartsWith("abcd"));
3146       EXPECT_EQ(std::string(cc3), base_value_as_string);
3147 
3148       std::string dest;
3149       absl::CopyCordToString(cc3, &dest);
3150       EXPECT_EQ(dest, base_value_as_string);
3151 
3152       bool first_pass = true;
3153       for (absl::string_view chunk : cc3.Chunks()) {
3154         if (first_pass) {
3155           EXPECT_TRUE(absl::StartsWith(chunk, "abcde"));
3156         }
3157         first_pass = false;
3158       }
3159       first_pass = true;
3160       for (char ch : cc3.Chars()) {
3161         if (first_pass) {
3162           EXPECT_EQ(ch, 'a');
3163         }
3164         first_pass = false;
3165       }
3166       EXPECT_TRUE(absl::StartsWith(*cc3.chunk_begin(), "abcde"));
3167       EXPECT_EQ(*cc3.char_begin(), 'a');
3168 
3169       auto char_it = cc3.char_begin();
3170       absl::Cord::Advance(&char_it, 2);
3171       EXPECT_EQ(absl::Cord::AdvanceAndRead(&char_it, 2), "cd");
3172       EXPECT_EQ(*char_it, 'e');
3173       char_it = cc3.char_begin();
3174       absl::Cord::Advance(&char_it, 2);
3175       EXPECT_TRUE(absl::StartsWith(absl::Cord::ChunkRemaining(char_it), "cde"));
3176 
3177       EXPECT_EQ(cc3[0], 'a');
3178       EXPECT_EQ(cc3[4], 'e');
3179       EXPECT_EQ(absl::HashOf(cc3), absl::HashOf(base_value));
3180       EXPECT_EQ(absl::HashOf(cc3), absl::HashOf(base_value_as_string));
3181     }
3182   }
3183 }
3184 
3185 // Test the special cases encountered with an empty checksummed cord.
TEST_P(CordTest,ChecksummedEmptyCord)3186 TEST_P(CordTest, ChecksummedEmptyCord) {
3187   absl::Cord c1;
3188   EXPECT_FALSE(c1.ExpectedChecksum().has_value());
3189 
3190   // Setting an expected checksum works.
3191   c1.SetExpectedChecksum(12345);
3192   EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
3193   EXPECT_EQ(c1, "");
3194   EXPECT_TRUE(c1.empty());
3195 
3196   // Test that setting an expected checksum again doesn't crash or leak memory.
3197   c1.SetExpectedChecksum(12345);
3198   EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
3199   EXPECT_EQ(c1, "");
3200   EXPECT_TRUE(c1.empty());
3201 
3202   // CRC persists through copies, assignments, and moves:
3203   absl::Cord c1_copy_construct = c1;
3204   EXPECT_EQ(c1_copy_construct.ExpectedChecksum().value_or(0), 12345);
3205 
3206   absl::Cord c1_copy_assign;
3207   c1_copy_assign = c1;
3208   EXPECT_EQ(c1_copy_assign.ExpectedChecksum().value_or(0), 12345);
3209 
3210   absl::Cord c1_move(std::move(c1_copy_assign));
3211   EXPECT_EQ(c1_move.ExpectedChecksum().value_or(0), 12345);
3212 
3213   EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
3214 
3215   // A CRC Cord compares equal to its non-CRC value.
3216   EXPECT_EQ(c1, absl::Cord());
3217 
3218   for (const CordMutator& mutator : cord_mutators) {
3219     SCOPED_TRACE(mutator.Name());
3220 
3221     // Exercise mutating an empty checksummed cord to catch crashes and exercise
3222     // memory sanitizers.
3223     absl::Cord c2;
3224     c2.SetExpectedChecksum(24680);
3225     mutator.Mutate(c2);
3226 
3227     if (c2.empty()) {
3228       // Not a mutation
3229       continue;
3230     }
3231     EXPECT_EQ(c2.ExpectedChecksum(), absl::nullopt);
3232 
3233     if (mutator.CanUndo()) {
3234       mutator.Undo(c2);
3235     }
3236   }
3237 
3238   absl::Cord c3;
3239   c3.SetExpectedChecksum(999);
3240   const absl::Cord& cc3 = c3;
3241 
3242   // Test that all cord reading operations function in the face of an
3243   // expected checksum.
3244   EXPECT_TRUE(cc3.StartsWith(""));
3245   EXPECT_TRUE(cc3.EndsWith(""));
3246   EXPECT_TRUE(cc3.empty());
3247   EXPECT_EQ(cc3, "");
3248   EXPECT_EQ(cc3, absl::Cord());
3249   EXPECT_EQ(cc3.size(), 0);
3250   EXPECT_EQ(cc3.Compare(absl::Cord()), 0);
3251   EXPECT_EQ(cc3.Compare(c1), 0);
3252   EXPECT_EQ(cc3.Compare(cc3), 0);
3253   EXPECT_EQ(cc3.Compare(""), 0);
3254   EXPECT_EQ(cc3.Compare("wxyz"), -1);
3255   EXPECT_EQ(cc3.Compare(absl::Cord("wxyz")), -1);
3256   EXPECT_EQ(absl::Cord("wxyz").Compare(cc3), 1);
3257   EXPECT_EQ(std::string(cc3), "");
3258 
3259   std::string dest;
3260   absl::CopyCordToString(cc3, &dest);
3261   EXPECT_EQ(dest, "");
3262 
3263   for (absl::string_view chunk : cc3.Chunks()) {  // NOLINT(unreachable loop)
3264     static_cast<void>(chunk);
3265     GTEST_FAIL() << "no chunks expected";
3266   }
3267   EXPECT_TRUE(cc3.chunk_begin() == cc3.chunk_end());
3268 
3269   for (char ch : cc3.Chars()) {  // NOLINT(unreachable loop)
3270     static_cast<void>(ch);
3271     GTEST_FAIL() << "no chars expected";
3272   }
3273   EXPECT_TRUE(cc3.char_begin() == cc3.char_end());
3274 
3275   EXPECT_EQ(cc3.TryFlat(), "");
3276   EXPECT_EQ(absl::HashOf(c3), absl::HashOf(absl::Cord()));
3277   EXPECT_EQ(absl::HashOf(c3), absl::HashOf(absl::string_view()));
3278 }
3279 
TEST(CrcCordTest,ChecksummedEmptyCordEstimateMemoryUsage)3280 TEST(CrcCordTest, ChecksummedEmptyCordEstimateMemoryUsage) {
3281   absl::Cord cord;
3282   cord.SetExpectedChecksum(0);
3283   EXPECT_NE(cord.EstimatedMemoryUsage(), 0);
3284 }
3285 
3286 #if defined(GTEST_HAS_DEATH_TEST) && defined(ABSL_INTERNAL_CORD_HAVE_SANITIZER)
3287 
3288 // Returns an expected poison / uninitialized death message expression.
MASanDeathExpr()3289 const char* MASanDeathExpr() {
3290   return "(use-after-poison|use-of-uninitialized-value)";
3291 }
3292 
TEST(CordSanitizerTest,SanitizesEmptyCord)3293 TEST(CordSanitizerTest, SanitizesEmptyCord) {
3294   absl::Cord cord;
3295   const char* data = cord.Flatten().data();
3296   EXPECT_DEATH(EXPECT_EQ(data[0], 0), MASanDeathExpr());
3297 }
3298 
TEST(CordSanitizerTest,SanitizesSmallCord)3299 TEST(CordSanitizerTest, SanitizesSmallCord) {
3300   absl::Cord cord("Hello");
3301   const char* data = cord.Flatten().data();
3302   EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());
3303 }
3304 
TEST(CordSanitizerTest,SanitizesCordOnSetSSOValue)3305 TEST(CordSanitizerTest, SanitizesCordOnSetSSOValue) {
3306   absl::Cord cord("String that is too big to be an SSO value");
3307   cord = "Hello";
3308   const char* data = cord.Flatten().data();
3309   EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());
3310 }
3311 
TEST(CordSanitizerTest,SanitizesCordOnCopyCtor)3312 TEST(CordSanitizerTest, SanitizesCordOnCopyCtor) {
3313   absl::Cord src("hello");
3314   absl::Cord dst(src);
3315   const char* data = dst.Flatten().data();
3316   EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());
3317 }
3318 
TEST(CordSanitizerTest,SanitizesCordOnMoveCtor)3319 TEST(CordSanitizerTest, SanitizesCordOnMoveCtor) {
3320   absl::Cord src("hello");
3321   absl::Cord dst(std::move(src));
3322   const char* data = dst.Flatten().data();
3323   EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());
3324 }
3325 
TEST(CordSanitizerTest,SanitizesCordOnAssign)3326 TEST(CordSanitizerTest, SanitizesCordOnAssign) {
3327   absl::Cord src("hello");
3328   absl::Cord dst;
3329   dst = src;
3330   const char* data = dst.Flatten().data();
3331   EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());
3332 }
3333 
TEST(CordSanitizerTest,SanitizesCordOnMoveAssign)3334 TEST(CordSanitizerTest, SanitizesCordOnMoveAssign) {
3335   absl::Cord src("hello");
3336   absl::Cord dst;
3337   dst = std::move(src);
3338   const char* data = dst.Flatten().data();
3339   EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());
3340 }
3341 
TEST(CordSanitizerTest,SanitizesCordOnSsoAssign)3342 TEST(CordSanitizerTest, SanitizesCordOnSsoAssign) {
3343   absl::Cord src("hello");
3344   absl::Cord dst("String that is too big to be an SSO value");
3345   dst = src;
3346   const char* data = dst.Flatten().data();
3347   EXPECT_DEATH(EXPECT_EQ(data[5], 0), MASanDeathExpr());
3348 }
3349 
3350 #endif  // GTEST_HAS_DEATH_TEST && ABSL_INTERNAL_CORD_HAVE_SANITIZER
3351