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