tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cord_test.cc (112732B)


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