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