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