• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/strings/cord.h"
16 
17 #include <algorithm>
18 #include <climits>
19 #include <cstdio>
20 #include <iterator>
21 #include <map>
22 #include <numeric>
23 #include <random>
24 #include <sstream>
25 #include <type_traits>
26 #include <utility>
27 #include <vector>
28 
29 #include "gmock/gmock.h"
30 #include "gtest/gtest.h"
31 #include "absl/base/casts.h"
32 #include "absl/base/config.h"
33 #include "absl/base/internal/endian.h"
34 #include "absl/base/internal/raw_logging.h"
35 #include "absl/base/macros.h"
36 #include "absl/container/fixed_array.h"
37 #include "absl/strings/cord_test_helpers.h"
38 #include "absl/strings/cordz_test_helpers.h"
39 #include "absl/strings/str_cat.h"
40 #include "absl/strings/str_format.h"
41 #include "absl/strings/string_view.h"
42 
43 typedef std::mt19937_64 RandomEngine;
44 
45 static std::string RandomLowercaseString(RandomEngine* rng);
46 static std::string RandomLowercaseString(RandomEngine* rng, size_t length);
47 
GetUniformRandomUpTo(RandomEngine * rng,int upper_bound)48 static int GetUniformRandomUpTo(RandomEngine* rng, int upper_bound) {
49   if (upper_bound > 0) {
50     std::uniform_int_distribution<int> uniform(0, upper_bound - 1);
51     return uniform(*rng);
52   } else {
53     return 0;
54   }
55 }
56 
GetUniformRandomUpTo(RandomEngine * rng,size_t upper_bound)57 static size_t GetUniformRandomUpTo(RandomEngine* rng, size_t upper_bound) {
58   if (upper_bound > 0) {
59     std::uniform_int_distribution<size_t> uniform(0, upper_bound - 1);
60     return uniform(*rng);
61   } else {
62     return 0;
63   }
64 }
65 
GenerateSkewedRandom(RandomEngine * rng,int max_log)66 static int32_t GenerateSkewedRandom(RandomEngine* rng, int max_log) {
67   const uint32_t base = (*rng)() % (max_log + 1);
68   const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u;
69   return (*rng)() & mask;
70 }
71 
RandomLowercaseString(RandomEngine * rng)72 static std::string RandomLowercaseString(RandomEngine* rng) {
73   int length;
74   std::bernoulli_distribution one_in_1k(0.001);
75   std::bernoulli_distribution one_in_10k(0.0001);
76   // With low probability, make a large fragment
77   if (one_in_10k(*rng)) {
78     length = GetUniformRandomUpTo(rng, 1048576);
79   } else if (one_in_1k(*rng)) {
80     length = GetUniformRandomUpTo(rng, 10000);
81   } else {
82     length = GenerateSkewedRandom(rng, 10);
83   }
84   return RandomLowercaseString(rng, length);
85 }
86 
RandomLowercaseString(RandomEngine * rng,size_t length)87 static std::string RandomLowercaseString(RandomEngine* rng, size_t length) {
88   std::string result(length, '\0');
89   std::uniform_int_distribution<int> chars('a', 'z');
90   std::generate(result.begin(), result.end(),
91                 [&]() { return static_cast<char>(chars(*rng)); });
92   return result;
93 }
94 
DoNothing(absl::string_view,void *)95 static void DoNothing(absl::string_view /* data */, void* /* arg */) {}
96 
DeleteExternalString(absl::string_view data,void * arg)97 static void DeleteExternalString(absl::string_view data, void* arg) {
98   std::string* s = reinterpret_cast<std::string*>(arg);
99   EXPECT_EQ(data, *s);
100   delete s;
101 }
102 
103 // Add "s" to *dst via `MakeCordFromExternal`
AddExternalMemory(absl::string_view s,absl::Cord * dst)104 static void AddExternalMemory(absl::string_view s, absl::Cord* dst) {
105   std::string* str = new std::string(s.data(), s.size());
106   dst->Append(absl::MakeCordFromExternal(*str, [str](absl::string_view data) {
107     DeleteExternalString(data, str);
108   }));
109 }
110 
DumpGrowth()111 static void DumpGrowth() {
112   absl::Cord str;
113   for (int i = 0; i < 1000; i++) {
114     char c = 'a' + i % 26;
115     str.Append(absl::string_view(&c, 1));
116   }
117 }
118 
119 // Make a Cord with some number of fragments.  Return the size (in bytes)
120 // of the smallest fragment.
AppendWithFragments(const std::string & s,RandomEngine * rng,absl::Cord * cord)121 static size_t AppendWithFragments(const std::string& s, RandomEngine* rng,
122                                   absl::Cord* cord) {
123   size_t j = 0;
124   const size_t max_size = s.size() / 5;  // Make approx. 10 fragments
125   size_t min_size = max_size;            // size of smallest fragment
126   while (j < s.size()) {
127     size_t N = 1 + GetUniformRandomUpTo(rng, max_size);
128     if (N > (s.size() - j)) {
129       N = s.size() - j;
130     }
131     if (N < min_size) {
132       min_size = N;
133     }
134 
135     std::bernoulli_distribution coin_flip(0.5);
136     if (coin_flip(*rng)) {
137       // Grow by adding an external-memory.
138       AddExternalMemory(absl::string_view(s.data() + j, N), cord);
139     } else {
140       cord->Append(absl::string_view(s.data() + j, N));
141     }
142     j += N;
143   }
144   return min_size;
145 }
146 
147 // Add an external memory that contains the specified std::string to cord
AddNewStringBlock(const std::string & str,absl::Cord * dst)148 static void AddNewStringBlock(const std::string& str, absl::Cord* dst) {
149   char* data = new char[str.size()];
150   memcpy(data, str.data(), str.size());
151   dst->Append(absl::MakeCordFromExternal(
152       absl::string_view(data, str.size()),
153       [](absl::string_view s) { delete[] s.data(); }));
154 }
155 
156 // Make a Cord out of many different types of nodes.
MakeComposite()157 static absl::Cord MakeComposite() {
158   absl::Cord cord;
159   cord.Append("the");
160   AddExternalMemory(" quick brown", &cord);
161   AddExternalMemory(" fox jumped", &cord);
162 
163   absl::Cord full(" over");
164   AddExternalMemory(" the lazy", &full);
165   AddNewStringBlock(" dog slept the whole day away", &full);
166   absl::Cord substring = full.Subcord(0, 18);
167 
168   // Make substring long enough to defeat the copying fast path in Append.
169   substring.Append(std::string(1000, '.'));
170   cord.Append(substring);
171   cord = cord.Subcord(0, cord.size() - 998);  // Remove most of extra junk
172 
173   return cord;
174 }
175 
176 namespace absl {
177 ABSL_NAMESPACE_BEGIN
178 
179 class CordTestPeer {
180  public:
ForEachChunk(const Cord & c,absl::FunctionRef<void (absl::string_view)> callback)181   static void ForEachChunk(
182       const Cord& c, absl::FunctionRef<void(absl::string_view)> callback) {
183     c.ForEachChunk(callback);
184   }
185 
IsTree(const Cord & c)186   static bool IsTree(const Cord& c) { return c.contents_.is_tree(); }
187 
GetCordzInfo(const Cord & c)188   static cord_internal::CordzInfo* GetCordzInfo(const Cord& c) {
189     return c.contents_.cordz_info();
190   }
191 
MakeSubstring(Cord src,size_t offset,size_t length)192   static Cord MakeSubstring(Cord src, size_t offset, size_t length) {
193     ABSL_RAW_CHECK(src.contents_.is_tree(), "Can not be inlined");
194     Cord cord;
195     auto* rep = new cord_internal::CordRepSubstring;
196     rep->tag = cord_internal::SUBSTRING;
197     rep->child = cord_internal::CordRep::Ref(src.contents_.tree());
198     rep->start = offset;
199     rep->length = length;
200     cord.contents_.EmplaceTree(rep,
201                                cord_internal::CordzUpdateTracker::kSubCord);
202     return cord;
203   }
204 };
205 
206 ABSL_NAMESPACE_END
207 }  // namespace absl
208 
209 // The CordTest fixture runs all tests with and without Cord Btree enabled.
210 class CordTest : public testing::TestWithParam<bool> {
211  public:
CordTest()212   CordTest() : was_btree_(absl::cord_internal::cord_btree_enabled.load()) {
213     absl::cord_internal::cord_btree_enabled.store(UseBtree());
214   }
~CordTest()215   ~CordTest() override {
216     absl::cord_internal::cord_btree_enabled.store(was_btree_);
217   }
218 
219   // Returns true if test is running with btree enabled.
UseBtree() const220   bool UseBtree() const { return GetParam(); }
221 
222   // Returns human readable string representation of the test parameter.
ToString(testing::TestParamInfo<bool> param)223   static std::string ToString(testing::TestParamInfo<bool> param) {
224     return param.param ? "Btree" : "Concat";
225   }
226 
227  private:
228   const bool was_btree_;
229 };
230 
231 INSTANTIATE_TEST_SUITE_P(WithParam, CordTest, testing::Bool(),
232                          CordTest::ToString);
233 
TEST_P(CordTest,AllFlatSizes)234 TEST_P(CordTest, AllFlatSizes) {
235   using absl::strings_internal::CordTestAccess;
236 
237   for (size_t s = 0; s < CordTestAccess::MaxFlatLength(); s++) {
238     // Make a string of length s.
239     std::string src;
240     while (src.size() < s) {
241       src.push_back('a' + (src.size() % 26));
242     }
243 
244     absl::Cord dst(src);
245     EXPECT_EQ(std::string(dst), src) << s;
246   }
247 }
248 
249 // We create a Cord at least 128GB in size using the fact that Cords can
250 // internally reference-count; thus the Cord is enormous without actually
251 // consuming very much memory.
TEST_P(CordTest,GigabyteCordFromExternal)252 TEST_P(CordTest, GigabyteCordFromExternal) {
253   const size_t one_gig = 1024U * 1024U * 1024U;
254   size_t max_size = 2 * one_gig;
255   if (sizeof(max_size) > 4) max_size = 128 * one_gig;
256 
257   size_t length = 128 * 1024;
258   char* data = new char[length];
259   absl::Cord from = absl::MakeCordFromExternal(
260       absl::string_view(data, length),
261       [](absl::string_view sv) { delete[] sv.data(); });
262 
263   // This loop may seem odd due to its combination of exponential doubling of
264   // size and incremental size increases.  We do it incrementally to be sure the
265   // Cord will need rebalancing and will exercise code that, in the past, has
266   // caused crashes in production.  We grow exponentially so that the code will
267   // execute in a reasonable amount of time.
268   absl::Cord c;
269   c.Append(from);
270   while (c.size() < max_size) {
271     c.Append(c);
272     c.Append(from);
273     c.Append(from);
274     c.Append(from);
275     c.Append(from);
276   }
277 
278   for (int i = 0; i < 1024; ++i) {
279     c.Append(from);
280   }
281   ABSL_RAW_LOG(INFO, "Made a Cord with %zu bytes!", c.size());
282   // Note: on a 32-bit build, this comes out to   2,818,048,000 bytes.
283   // Note: on a 64-bit build, this comes out to 171,932,385,280 bytes.
284 }
285 
MakeExternalCord(int size)286 static absl::Cord MakeExternalCord(int size) {
287   char* buffer = new char[size];
288   memset(buffer, 'x', size);
289   absl::Cord cord;
290   cord.Append(absl::MakeCordFromExternal(
291       absl::string_view(buffer, size),
292       [](absl::string_view s) { delete[] s.data(); }));
293   return cord;
294 }
295 
296 // Extern to fool clang that this is not constant. Needed to suppress
297 // a warning of unsafe code we want to test.
298 extern bool my_unique_true_boolean;
299 bool my_unique_true_boolean = true;
300 
TEST_P(CordTest,Assignment)301 TEST_P(CordTest, Assignment) {
302   absl::Cord x(absl::string_view("hi there"));
303   absl::Cord y(x);
304   ASSERT_EQ(std::string(x), "hi there");
305   ASSERT_EQ(std::string(y), "hi there");
306   ASSERT_TRUE(x == y);
307   ASSERT_TRUE(x <= y);
308   ASSERT_TRUE(y <= x);
309 
310   x = absl::string_view("foo");
311   ASSERT_EQ(std::string(x), "foo");
312   ASSERT_EQ(std::string(y), "hi there");
313   ASSERT_TRUE(x < y);
314   ASSERT_TRUE(y > x);
315   ASSERT_TRUE(x != y);
316   ASSERT_TRUE(x <= y);
317   ASSERT_TRUE(y >= x);
318 
319   x = "foo";
320   ASSERT_EQ(x, "foo");
321 
322   // Test that going from inline rep to tree we don't leak memory.
323   std::vector<std::pair<absl::string_view, absl::string_view>>
324       test_string_pairs = {{"hi there", "foo"},
325                            {"loooooong coooooord", "short cord"},
326                            {"short cord", "loooooong coooooord"},
327                            {"loooooong coooooord1", "loooooong coooooord2"}};
328   for (std::pair<absl::string_view, absl::string_view> test_strings :
329        test_string_pairs) {
330     absl::Cord tmp(test_strings.first);
331     absl::Cord z(std::move(tmp));
332     ASSERT_EQ(std::string(z), test_strings.first);
333     tmp = test_strings.second;
334     z = std::move(tmp);
335     ASSERT_EQ(std::string(z), test_strings.second);
336   }
337   {
338     // Test that self-move assignment doesn't crash/leak.
339     // Do not write such code!
340     absl::Cord my_small_cord("foo");
341     absl::Cord my_big_cord("loooooong coooooord");
342     // Bypass clang's warning on self move-assignment.
343     absl::Cord* my_small_alias =
344         my_unique_true_boolean ? &my_small_cord : &my_big_cord;
345     absl::Cord* my_big_alias =
346         !my_unique_true_boolean ? &my_small_cord : &my_big_cord;
347 
348     *my_small_alias = std::move(my_small_cord);
349     *my_big_alias = std::move(my_big_cord);
350     // my_small_cord and my_big_cord are in an unspecified but valid
351     // state, and will be correctly destroyed here.
352   }
353 }
354 
TEST_P(CordTest,StartsEndsWith)355 TEST_P(CordTest, StartsEndsWith) {
356   absl::Cord x(absl::string_view("abcde"));
357   absl::Cord empty("");
358 
359   ASSERT_TRUE(x.StartsWith(absl::Cord("abcde")));
360   ASSERT_TRUE(x.StartsWith(absl::Cord("abc")));
361   ASSERT_TRUE(x.StartsWith(absl::Cord("")));
362   ASSERT_TRUE(empty.StartsWith(absl::Cord("")));
363   ASSERT_TRUE(x.EndsWith(absl::Cord("abcde")));
364   ASSERT_TRUE(x.EndsWith(absl::Cord("cde")));
365   ASSERT_TRUE(x.EndsWith(absl::Cord("")));
366   ASSERT_TRUE(empty.EndsWith(absl::Cord("")));
367 
368   ASSERT_TRUE(!x.StartsWith(absl::Cord("xyz")));
369   ASSERT_TRUE(!empty.StartsWith(absl::Cord("xyz")));
370   ASSERT_TRUE(!x.EndsWith(absl::Cord("xyz")));
371   ASSERT_TRUE(!empty.EndsWith(absl::Cord("xyz")));
372 
373   ASSERT_TRUE(x.StartsWith("abcde"));
374   ASSERT_TRUE(x.StartsWith("abc"));
375   ASSERT_TRUE(x.StartsWith(""));
376   ASSERT_TRUE(empty.StartsWith(""));
377   ASSERT_TRUE(x.EndsWith("abcde"));
378   ASSERT_TRUE(x.EndsWith("cde"));
379   ASSERT_TRUE(x.EndsWith(""));
380   ASSERT_TRUE(empty.EndsWith(""));
381 
382   ASSERT_TRUE(!x.StartsWith("xyz"));
383   ASSERT_TRUE(!empty.StartsWith("xyz"));
384   ASSERT_TRUE(!x.EndsWith("xyz"));
385   ASSERT_TRUE(!empty.EndsWith("xyz"));
386 }
387 
TEST_P(CordTest,Subcord)388 TEST_P(CordTest, Subcord) {
389   RandomEngine rng(GTEST_FLAG_GET(random_seed));
390   const std::string s = RandomLowercaseString(&rng, 1024);
391 
392   absl::Cord a;
393   AppendWithFragments(s, &rng, &a);
394   ASSERT_EQ(s, std::string(a));
395 
396   // Check subcords of a, from a variety of interesting points.
397   std::set<size_t> positions;
398   for (int i = 0; i <= 32; ++i) {
399     positions.insert(i);
400     positions.insert(i * 32 - 1);
401     positions.insert(i * 32);
402     positions.insert(i * 32 + 1);
403     positions.insert(a.size() - i);
404   }
405   positions.insert(237);
406   positions.insert(732);
407   for (size_t pos : positions) {
408     if (pos > a.size()) continue;
409     for (size_t end_pos : positions) {
410       if (end_pos < pos || end_pos > a.size()) continue;
411       absl::Cord sa = a.Subcord(pos, end_pos - pos);
412       ASSERT_EQ(absl::string_view(s).substr(pos, end_pos - pos),
413                 std::string(sa))
414           << a;
415     }
416   }
417 
418   // Do the same thing for an inline cord.
419   const std::string sh = "short";
420   absl::Cord c(sh);
421   for (size_t pos = 0; pos <= sh.size(); ++pos) {
422     for (size_t n = 0; n <= sh.size() - pos; ++n) {
423       absl::Cord sc = c.Subcord(pos, n);
424       ASSERT_EQ(sh.substr(pos, n), std::string(sc)) << c;
425     }
426   }
427 
428   // Check subcords of subcords.
429   absl::Cord sa = a.Subcord(0, a.size());
430   std::string ss = s.substr(0, s.size());
431   while (sa.size() > 1) {
432     sa = sa.Subcord(1, sa.size() - 2);
433     ss = ss.substr(1, ss.size() - 2);
434     ASSERT_EQ(ss, std::string(sa)) << a;
435     if (HasFailure()) break;  // halt cascade
436   }
437 
438   // It is OK to ask for too much.
439   sa = a.Subcord(0, a.size() + 1);
440   EXPECT_EQ(s, std::string(sa));
441 
442   // It is OK to ask for something beyond the end.
443   sa = a.Subcord(a.size() + 1, 0);
444   EXPECT_TRUE(sa.empty());
445   sa = a.Subcord(a.size() + 1, 1);
446   EXPECT_TRUE(sa.empty());
447 }
448 
TEST_P(CordTest,Swap)449 TEST_P(CordTest, Swap) {
450   absl::string_view a("Dexter");
451   absl::string_view b("Mandark");
452   absl::Cord x(a);
453   absl::Cord y(b);
454   swap(x, y);
455   ASSERT_EQ(x, absl::Cord(b));
456   ASSERT_EQ(y, absl::Cord(a));
457   x.swap(y);
458   ASSERT_EQ(x, absl::Cord(a));
459   ASSERT_EQ(y, absl::Cord(b));
460 }
461 
VerifyCopyToString(const absl::Cord & cord)462 static void VerifyCopyToString(const absl::Cord& cord) {
463   std::string initially_empty;
464   absl::CopyCordToString(cord, &initially_empty);
465   EXPECT_EQ(initially_empty, cord);
466 
467   constexpr size_t kInitialLength = 1024;
468   std::string has_initial_contents(kInitialLength, 'x');
469   const char* address_before_copy = has_initial_contents.data();
470   absl::CopyCordToString(cord, &has_initial_contents);
471   EXPECT_EQ(has_initial_contents, cord);
472 
473   if (cord.size() <= kInitialLength) {
474     EXPECT_EQ(has_initial_contents.data(), address_before_copy)
475         << "CopyCordToString allocated new string storage; "
476            "has_initial_contents = \""
477         << has_initial_contents << "\"";
478   }
479 }
480 
TEST_P(CordTest,CopyToString)481 TEST_P(CordTest, CopyToString) {
482   VerifyCopyToString(absl::Cord());
483   VerifyCopyToString(absl::Cord("small cord"));
484   VerifyCopyToString(
485       absl::MakeFragmentedCord({"fragmented ", "cord ", "to ", "test ",
486                                 "copying ", "to ", "a ", "string."}));
487 }
488 
TEST_P(CordTest,TryFlatEmpty)489 TEST_P(CordTest, TryFlatEmpty) {
490   absl::Cord c;
491   EXPECT_EQ(c.TryFlat(), "");
492 }
493 
TEST_P(CordTest,TryFlatFlat)494 TEST_P(CordTest, TryFlatFlat) {
495   absl::Cord c("hello");
496   EXPECT_EQ(c.TryFlat(), "hello");
497 }
498 
TEST_P(CordTest,TryFlatSubstrInlined)499 TEST_P(CordTest, TryFlatSubstrInlined) {
500   absl::Cord c("hello");
501   c.RemovePrefix(1);
502   EXPECT_EQ(c.TryFlat(), "ello");
503 }
504 
TEST_P(CordTest,TryFlatSubstrFlat)505 TEST_P(CordTest, TryFlatSubstrFlat) {
506   absl::Cord c("longer than 15 bytes");
507   absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
508   EXPECT_EQ(sub.TryFlat(), "onger than 15 bytes");
509 }
510 
TEST_P(CordTest,TryFlatConcat)511 TEST_P(CordTest, TryFlatConcat) {
512   absl::Cord c = absl::MakeFragmentedCord({"hel", "lo"});
513   EXPECT_EQ(c.TryFlat(), absl::nullopt);
514 }
515 
TEST_P(CordTest,TryFlatExternal)516 TEST_P(CordTest, TryFlatExternal) {
517   absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
518   EXPECT_EQ(c.TryFlat(), "hell");
519 }
520 
TEST_P(CordTest,TryFlatSubstrExternal)521 TEST_P(CordTest, TryFlatSubstrExternal) {
522   absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
523   absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
524   EXPECT_EQ(sub.TryFlat(), "ell");
525 }
526 
TEST_P(CordTest,TryFlatSubstrConcat)527 TEST_P(CordTest, TryFlatSubstrConcat) {
528   absl::Cord c = absl::MakeFragmentedCord({"hello", " world"});
529   absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
530   EXPECT_EQ(sub.TryFlat(), absl::nullopt);
531   c.RemovePrefix(1);
532   EXPECT_EQ(c.TryFlat(), absl::nullopt);
533 }
534 
TEST_P(CordTest,TryFlatCommonlyAssumedInvariants)535 TEST_P(CordTest, TryFlatCommonlyAssumedInvariants) {
536   // The behavior tested below is not part of the API contract of Cord, but it's
537   // something we intend to be true in our current implementation.  This test
538   // exists to detect and prevent accidental breakage of the implementation.
539   absl::string_view fragments[] = {"A fragmented test",
540                                    " cord",
541                                    " to test subcords",
542                                    " of ",
543                                    "a",
544                                    " cord for",
545                                    " each chunk "
546                                    "returned by the ",
547                                    "iterator"};
548   absl::Cord c = absl::MakeFragmentedCord(fragments);
549   int fragment = 0;
550   int offset = 0;
551   absl::Cord::CharIterator itc = c.char_begin();
552   for (absl::string_view sv : c.Chunks()) {
553     absl::string_view expected = fragments[fragment];
554     absl::Cord subcord1 = c.Subcord(offset, sv.length());
555     absl::Cord subcord2 = absl::Cord::AdvanceAndRead(&itc, sv.size());
556     EXPECT_EQ(subcord1.TryFlat(), expected);
557     EXPECT_EQ(subcord2.TryFlat(), expected);
558     ++fragment;
559     offset += sv.length();
560   }
561 }
562 
IsFlat(const absl::Cord & c)563 static bool IsFlat(const absl::Cord& c) {
564   return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end();
565 }
566 
VerifyFlatten(absl::Cord c)567 static void VerifyFlatten(absl::Cord c) {
568   std::string old_contents(c);
569   absl::string_view old_flat;
570   bool already_flat_and_non_empty = IsFlat(c) && !c.empty();
571   if (already_flat_and_non_empty) {
572     old_flat = *c.chunk_begin();
573   }
574   absl::string_view new_flat = c.Flatten();
575 
576   // Verify that the contents of the flattened Cord are correct.
577   EXPECT_EQ(new_flat, old_contents);
578   EXPECT_EQ(std::string(c), old_contents);
579 
580   // If the Cord contained data and was already flat, verify that the data
581   // wasn't copied.
582   if (already_flat_and_non_empty) {
583     EXPECT_EQ(old_flat.data(), new_flat.data())
584         << "Allocated new memory even though the Cord was already flat.";
585   }
586 
587   // Verify that the flattened Cord is in fact flat.
588   EXPECT_TRUE(IsFlat(c));
589 }
590 
TEST_P(CordTest,Flatten)591 TEST_P(CordTest, Flatten) {
592   VerifyFlatten(absl::Cord());
593   VerifyFlatten(absl::Cord("small cord"));
594   VerifyFlatten(absl::Cord("larger than small buffer optimization"));
595   VerifyFlatten(absl::MakeFragmentedCord({"small ", "fragmented ", "cord"}));
596 
597   // Test with a cord that is longer than the largest flat buffer
598   RandomEngine rng(GTEST_FLAG_GET(random_seed));
599   VerifyFlatten(absl::Cord(RandomLowercaseString(&rng, 8192)));
600 }
601 
602 // Test data
603 namespace {
604 class TestData {
605  private:
606   std::vector<std::string> data_;
607 
608   // Return a std::string of the specified length.
MakeString(int length)609   static std::string MakeString(int length) {
610     std::string result;
611     char buf[30];
612     snprintf(buf, sizeof(buf), "(%d)", length);
613     while (result.size() < length) {
614       result += buf;
615     }
616     result.resize(length);
617     return result;
618   }
619 
620  public:
TestData()621   TestData() {
622     // short strings increasing in length by one
623     for (int i = 0; i < 30; i++) {
624       data_.push_back(MakeString(i));
625     }
626 
627     // strings around half kMaxFlatLength
628     static const int kMaxFlatLength = 4096 - 9;
629     static const int kHalf = kMaxFlatLength / 2;
630 
631     for (int i = -10; i <= +10; i++) {
632       data_.push_back(MakeString(kHalf + i));
633     }
634 
635     for (int i = -10; i <= +10; i++) {
636       data_.push_back(MakeString(kMaxFlatLength + i));
637     }
638   }
639 
size() const640   size_t size() const { return data_.size(); }
data(size_t i) const641   const std::string& data(size_t i) const { return data_[i]; }
642 };
643 }  // namespace
644 
TEST_P(CordTest,MultipleLengths)645 TEST_P(CordTest, MultipleLengths) {
646   TestData d;
647   for (size_t i = 0; i < d.size(); i++) {
648     std::string a = d.data(i);
649 
650     {  // Construct from Cord
651       absl::Cord tmp(a);
652       absl::Cord x(tmp);
653       EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
654     }
655 
656     {  // Construct from absl::string_view
657       absl::Cord x(a);
658       EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
659     }
660 
661     {  // Append cord to self
662       absl::Cord self(a);
663       self.Append(self);
664       EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
665     }
666 
667     {  // Prepend cord to self
668       absl::Cord self(a);
669       self.Prepend(self);
670       EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
671     }
672 
673     // Try to append/prepend others
674     for (size_t j = 0; j < d.size(); j++) {
675       std::string b = d.data(j);
676 
677       {  // CopyFrom Cord
678         absl::Cord x(a);
679         absl::Cord y(b);
680         x = y;
681         EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
682       }
683 
684       {  // CopyFrom absl::string_view
685         absl::Cord x(a);
686         x = b;
687         EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
688       }
689 
690       {  // Cord::Append(Cord)
691         absl::Cord x(a);
692         absl::Cord y(b);
693         x.Append(y);
694         EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
695       }
696 
697       {  // Cord::Append(absl::string_view)
698         absl::Cord x(a);
699         x.Append(b);
700         EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
701       }
702 
703       {  // Cord::Prepend(Cord)
704         absl::Cord x(a);
705         absl::Cord y(b);
706         x.Prepend(y);
707         EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
708       }
709 
710       {  // Cord::Prepend(absl::string_view)
711         absl::Cord x(a);
712         x.Prepend(b);
713         EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
714       }
715     }
716   }
717 }
718 
719 namespace {
720 
TEST_P(CordTest,RemoveSuffixWithExternalOrSubstring)721 TEST_P(CordTest, RemoveSuffixWithExternalOrSubstring) {
722   absl::Cord cord = absl::MakeCordFromExternal(
723       "foo bar baz", [](absl::string_view s) { DoNothing(s, nullptr); });
724 
725   EXPECT_EQ("foo bar baz", std::string(cord));
726 
727   // This RemoveSuffix() will wrap the EXTERNAL node in a SUBSTRING node.
728   cord.RemoveSuffix(4);
729   EXPECT_EQ("foo bar", std::string(cord));
730 
731   // This RemoveSuffix() will adjust the SUBSTRING node in-place.
732   cord.RemoveSuffix(4);
733   EXPECT_EQ("foo", std::string(cord));
734 }
735 
TEST_P(CordTest,RemoveSuffixMakesZeroLengthNode)736 TEST_P(CordTest, RemoveSuffixMakesZeroLengthNode) {
737   absl::Cord c;
738   c.Append(absl::Cord(std::string(100, 'x')));
739   absl::Cord other_ref = c;  // Prevent inplace appends
740   c.Append(absl::Cord(std::string(200, 'y')));
741   c.RemoveSuffix(200);
742   EXPECT_EQ(std::string(100, 'x'), std::string(c));
743 }
744 
745 }  // namespace
746 
747 // CordSpliceTest contributed by hendrie.
748 namespace {
749 
750 // Create a cord with an external memory block filled with 'z'
CordWithZedBlock(size_t size)751 absl::Cord CordWithZedBlock(size_t size) {
752   char* data = new char[size];
753   if (size > 0) {
754     memset(data, 'z', size);
755   }
756   absl::Cord cord = absl::MakeCordFromExternal(
757       absl::string_view(data, size),
758       [](absl::string_view s) { delete[] s.data(); });
759   return cord;
760 }
761 
762 // Establish that ZedBlock does what we think it does.
TEST_P(CordTest,CordSpliceTestZedBlock)763 TEST_P(CordTest, CordSpliceTestZedBlock) {
764   absl::Cord blob = CordWithZedBlock(10);
765   EXPECT_EQ(10, blob.size());
766   std::string s;
767   absl::CopyCordToString(blob, &s);
768   EXPECT_EQ("zzzzzzzzzz", s);
769 }
770 
TEST_P(CordTest,CordSpliceTestZedBlock0)771 TEST_P(CordTest, CordSpliceTestZedBlock0) {
772   absl::Cord blob = CordWithZedBlock(0);
773   EXPECT_EQ(0, blob.size());
774   std::string s;
775   absl::CopyCordToString(blob, &s);
776   EXPECT_EQ("", s);
777 }
778 
TEST_P(CordTest,CordSpliceTestZedBlockSuffix1)779 TEST_P(CordTest, CordSpliceTestZedBlockSuffix1) {
780   absl::Cord blob = CordWithZedBlock(10);
781   EXPECT_EQ(10, blob.size());
782   absl::Cord suffix(blob);
783   suffix.RemovePrefix(9);
784   EXPECT_EQ(1, suffix.size());
785   std::string s;
786   absl::CopyCordToString(suffix, &s);
787   EXPECT_EQ("z", s);
788 }
789 
790 // Remove all of a prefix block
TEST_P(CordTest,CordSpliceTestZedBlockSuffix0)791 TEST_P(CordTest, CordSpliceTestZedBlockSuffix0) {
792   absl::Cord blob = CordWithZedBlock(10);
793   EXPECT_EQ(10, blob.size());
794   absl::Cord suffix(blob);
795   suffix.RemovePrefix(10);
796   EXPECT_EQ(0, suffix.size());
797   std::string s;
798   absl::CopyCordToString(suffix, &s);
799   EXPECT_EQ("", s);
800 }
801 
BigCord(size_t len,char v)802 absl::Cord BigCord(size_t len, char v) {
803   std::string s(len, v);
804   return absl::Cord(s);
805 }
806 
807 // Splice block into cord.
SpliceCord(const absl::Cord & blob,int64_t offset,const absl::Cord & block)808 absl::Cord SpliceCord(const absl::Cord& blob, int64_t offset,
809                       const absl::Cord& block) {
810   ABSL_RAW_CHECK(offset >= 0, "");
811   ABSL_RAW_CHECK(offset + block.size() <= blob.size(), "");
812   absl::Cord result(blob);
813   result.RemoveSuffix(blob.size() - offset);
814   result.Append(block);
815   absl::Cord suffix(blob);
816   suffix.RemovePrefix(offset + block.size());
817   result.Append(suffix);
818   ABSL_RAW_CHECK(blob.size() == result.size(), "");
819   return result;
820 }
821 
822 // Taking an empty suffix of a block breaks appending.
TEST_P(CordTest,CordSpliceTestRemoveEntireBlock1)823 TEST_P(CordTest, CordSpliceTestRemoveEntireBlock1) {
824   absl::Cord zero = CordWithZedBlock(10);
825   absl::Cord suffix(zero);
826   suffix.RemovePrefix(10);
827   absl::Cord result;
828   result.Append(suffix);
829 }
830 
TEST_P(CordTest,CordSpliceTestRemoveEntireBlock2)831 TEST_P(CordTest, CordSpliceTestRemoveEntireBlock2) {
832   absl::Cord zero = CordWithZedBlock(10);
833   absl::Cord prefix(zero);
834   prefix.RemoveSuffix(10);
835   absl::Cord suffix(zero);
836   suffix.RemovePrefix(10);
837   absl::Cord result(prefix);
838   result.Append(suffix);
839 }
840 
TEST_P(CordTest,CordSpliceTestRemoveEntireBlock3)841 TEST_P(CordTest, CordSpliceTestRemoveEntireBlock3) {
842   absl::Cord blob = CordWithZedBlock(10);
843   absl::Cord block = BigCord(10, 'b');
844   blob = SpliceCord(blob, 0, block);
845 }
846 
847 struct CordCompareTestCase {
848   template <typename LHS, typename RHS>
CordCompareTestCase__anon58f243cc0b11::CordCompareTestCase849   CordCompareTestCase(const LHS& lhs, const RHS& rhs)
850       : lhs_cord(lhs), rhs_cord(rhs) {}
851 
852   absl::Cord lhs_cord;
853   absl::Cord rhs_cord;
854 };
855 
__anon58f243cc0d02(int x) 856 const auto sign = [](int x) { return x == 0 ? 0 : (x > 0 ? 1 : -1); };
857 
VerifyComparison(const CordCompareTestCase & test_case)858 void VerifyComparison(const CordCompareTestCase& test_case) {
859   std::string lhs_string(test_case.lhs_cord);
860   std::string rhs_string(test_case.rhs_cord);
861   int expected = sign(lhs_string.compare(rhs_string));
862   EXPECT_EQ(expected, test_case.lhs_cord.Compare(test_case.rhs_cord))
863       << "LHS=" << lhs_string << "; RHS=" << rhs_string;
864   EXPECT_EQ(expected, test_case.lhs_cord.Compare(rhs_string))
865       << "LHS=" << lhs_string << "; RHS=" << rhs_string;
866   EXPECT_EQ(-expected, test_case.rhs_cord.Compare(test_case.lhs_cord))
867       << "LHS=" << rhs_string << "; RHS=" << lhs_string;
868   EXPECT_EQ(-expected, test_case.rhs_cord.Compare(lhs_string))
869       << "LHS=" << rhs_string << "; RHS=" << lhs_string;
870 }
871 
TEST_P(CordTest,Compare)872 TEST_P(CordTest, Compare) {
873   absl::Cord subcord("aaaaaBBBBBcccccDDDDD");
874   subcord = subcord.Subcord(3, 10);
875 
876   absl::Cord tmp("aaaaaaaaaaaaaaaa");
877   tmp.Append("BBBBBBBBBBBBBBBB");
878   absl::Cord concat = absl::Cord("cccccccccccccccc");
879   concat.Append("DDDDDDDDDDDDDDDD");
880   concat.Prepend(tmp);
881 
882   absl::Cord concat2("aaaaaaaaaaaaa");
883   concat2.Append("aaaBBBBBBBBBBBBBBBBccccc");
884   concat2.Append("cccccccccccDDDDDDDDDDDDDD");
885   concat2.Append("DD");
886 
887   std::vector<CordCompareTestCase> test_cases = {{
888       // Inline cords
889       {"abcdef", "abcdef"},
890       {"abcdef", "abcdee"},
891       {"abcdef", "abcdeg"},
892       {"bbcdef", "abcdef"},
893       {"bbcdef", "abcdeg"},
894       {"abcdefa", "abcdef"},
895       {"abcdef", "abcdefa"},
896 
897       // Small flat cords
898       {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDD"},
899       {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBxccccDDDDD"},
900       {"aaaaaBBBBBcxcccDDDDD", "aaaaaBBBBBcccccDDDDD"},
901       {"aaaaaBBBBBxccccDDDDD", "aaaaaBBBBBcccccDDDDX"},
902       {"aaaaaBBBBBcccccDDDDDa", "aaaaaBBBBBcccccDDDDD"},
903       {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDDa"},
904 
905       // Subcords
906       {subcord, subcord},
907       {subcord, "aaBBBBBccc"},
908       {subcord, "aaBBBBBccd"},
909       {subcord, "aaBBBBBccb"},
910       {subcord, "aaBBBBBxcb"},
911       {subcord, "aaBBBBBccca"},
912       {subcord, "aaBBBBBcc"},
913 
914       // Concats
915       {concat, concat},
916       {concat,
917        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDD"},
918       {concat,
919        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBcccccccccccccccxDDDDDDDDDDDDDDDD"},
920       {concat,
921        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBacccccccccccccccDDDDDDDDDDDDDDDD"},
922       {concat,
923        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDD"},
924       {concat,
925        "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDDe"},
926 
927       {concat, concat2},
928   }};
929 
930   for (const auto& tc : test_cases) {
931     VerifyComparison(tc);
932   }
933 }
934 
TEST_P(CordTest,CompareAfterAssign)935 TEST_P(CordTest, CompareAfterAssign) {
936   absl::Cord a("aaaaaa1111111");
937   absl::Cord b("aaaaaa2222222");
938   a = "cccccc";
939   b = "cccccc";
940   EXPECT_EQ(a, b);
941   EXPECT_FALSE(a < b);
942 
943   a = "aaaa";
944   b = "bbbbb";
945   a = "";
946   b = "";
947   EXPECT_EQ(a, b);
948   EXPECT_FALSE(a < b);
949 }
950 
951 // Test CompareTo() and ComparePrefix() against string and substring
952 // comparison methods from basic_string.
TestCompare(const absl::Cord & c,const absl::Cord & d,RandomEngine * rng)953 static void TestCompare(const absl::Cord& c, const absl::Cord& d,
954                         RandomEngine* rng) {
955   typedef std::basic_string<uint8_t> ustring;
956   ustring cs(reinterpret_cast<const uint8_t*>(std::string(c).data()), c.size());
957   ustring ds(reinterpret_cast<const uint8_t*>(std::string(d).data()), d.size());
958   // ustring comparison is ideal because we expect Cord comparisons to be
959   // based on unsigned byte comparisons regardless of whether char is signed.
960   int expected = sign(cs.compare(ds));
961   EXPECT_EQ(expected, sign(c.Compare(d))) << c << ", " << d;
962 }
963 
TEST_P(CordTest,CompareComparisonIsUnsigned)964 TEST_P(CordTest, CompareComparisonIsUnsigned) {
965   RandomEngine rng(GTEST_FLAG_GET(random_seed));
966   std::uniform_int_distribution<uint32_t> uniform_uint8(0, 255);
967   char x = static_cast<char>(uniform_uint8(rng));
968   TestCompare(
969       absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x)),
970       absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x ^ 0x80)), &rng);
971 }
972 
TEST_P(CordTest,CompareRandomComparisons)973 TEST_P(CordTest, CompareRandomComparisons) {
974   const int kIters = 5000;
975   RandomEngine rng(GTEST_FLAG_GET(random_seed));
976 
977   int n = GetUniformRandomUpTo(&rng, 5000);
978   absl::Cord a[] = {MakeExternalCord(n),
979                     absl::Cord("ant"),
980                     absl::Cord("elephant"),
981                     absl::Cord("giraffe"),
982                     absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100),
983                                            GetUniformRandomUpTo(&rng, 100))),
984                     absl::Cord(""),
985                     absl::Cord("x"),
986                     absl::Cord("A"),
987                     absl::Cord("B"),
988                     absl::Cord("C")};
989   for (int i = 0; i < kIters; i++) {
990     absl::Cord c, d;
991     for (int j = 0; j < (i % 7) + 1; j++) {
992       c.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
993       d.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
994     }
995     std::bernoulli_distribution coin_flip(0.5);
996     TestCompare(coin_flip(rng) ? c : absl::Cord(std::string(c)),
997                 coin_flip(rng) ? d : absl::Cord(std::string(d)), &rng);
998   }
999 }
1000 
1001 template <typename T1, typename T2>
CompareOperators()1002 void CompareOperators() {
1003   const T1 a("a");
1004   const T2 b("b");
1005 
1006   EXPECT_TRUE(a == a);
1007   // For pointer type (i.e. `const char*`), operator== compares the address
1008   // instead of the string, so `a == const char*("a")` isn't necessarily true.
1009   EXPECT_TRUE(std::is_pointer<T1>::value || a == T1("a"));
1010   EXPECT_TRUE(std::is_pointer<T2>::value || a == T2("a"));
1011   EXPECT_FALSE(a == b);
1012 
1013   EXPECT_TRUE(a != b);
1014   EXPECT_FALSE(a != a);
1015 
1016   EXPECT_TRUE(a < b);
1017   EXPECT_FALSE(b < a);
1018 
1019   EXPECT_TRUE(b > a);
1020   EXPECT_FALSE(a > b);
1021 
1022   EXPECT_TRUE(a >= a);
1023   EXPECT_TRUE(b >= a);
1024   EXPECT_FALSE(a >= b);
1025 
1026   EXPECT_TRUE(a <= a);
1027   EXPECT_TRUE(a <= b);
1028   EXPECT_FALSE(b <= a);
1029 }
1030 
TEST_P(CordTest,ComparisonOperators_Cord_Cord)1031 TEST_P(CordTest, ComparisonOperators_Cord_Cord) {
1032   CompareOperators<absl::Cord, absl::Cord>();
1033 }
1034 
TEST_P(CordTest,ComparisonOperators_Cord_StringPiece)1035 TEST_P(CordTest, ComparisonOperators_Cord_StringPiece) {
1036   CompareOperators<absl::Cord, absl::string_view>();
1037 }
1038 
TEST_P(CordTest,ComparisonOperators_StringPiece_Cord)1039 TEST_P(CordTest, ComparisonOperators_StringPiece_Cord) {
1040   CompareOperators<absl::string_view, absl::Cord>();
1041 }
1042 
TEST_P(CordTest,ComparisonOperators_Cord_string)1043 TEST_P(CordTest, ComparisonOperators_Cord_string) {
1044   CompareOperators<absl::Cord, std::string>();
1045 }
1046 
TEST_P(CordTest,ComparisonOperators_string_Cord)1047 TEST_P(CordTest, ComparisonOperators_string_Cord) {
1048   CompareOperators<std::string, absl::Cord>();
1049 }
1050 
TEST_P(CordTest,ComparisonOperators_stdstring_Cord)1051 TEST_P(CordTest, ComparisonOperators_stdstring_Cord) {
1052   CompareOperators<std::string, absl::Cord>();
1053 }
1054 
TEST_P(CordTest,ComparisonOperators_Cord_stdstring)1055 TEST_P(CordTest, ComparisonOperators_Cord_stdstring) {
1056   CompareOperators<absl::Cord, std::string>();
1057 }
1058 
TEST_P(CordTest,ComparisonOperators_charstar_Cord)1059 TEST_P(CordTest, ComparisonOperators_charstar_Cord) {
1060   CompareOperators<const char*, absl::Cord>();
1061 }
1062 
TEST_P(CordTest,ComparisonOperators_Cord_charstar)1063 TEST_P(CordTest, ComparisonOperators_Cord_charstar) {
1064   CompareOperators<absl::Cord, const char*>();
1065 }
1066 
TEST_P(CordTest,ConstructFromExternalReleaserInvoked)1067 TEST_P(CordTest, ConstructFromExternalReleaserInvoked) {
1068   // Empty external memory means the releaser should be called immediately.
1069   {
1070     bool invoked = false;
1071     auto releaser = [&invoked](absl::string_view) { invoked = true; };
1072     {
1073       auto c = absl::MakeCordFromExternal("", releaser);
1074       EXPECT_TRUE(invoked);
1075     }
1076   }
1077 
1078   // If the size of the data is small enough, a future constructor
1079   // implementation may copy the bytes and immediately invoke the releaser
1080   // instead of creating an external node. We make a large dummy std::string to
1081   // make this test independent of such an optimization.
1082   std::string large_dummy(2048, 'c');
1083   {
1084     bool invoked = false;
1085     auto releaser = [&invoked](absl::string_view) { invoked = true; };
1086     {
1087       auto c = absl::MakeCordFromExternal(large_dummy, releaser);
1088       EXPECT_FALSE(invoked);
1089     }
1090     EXPECT_TRUE(invoked);
1091   }
1092 
1093   {
1094     bool invoked = false;
1095     auto releaser = [&invoked](absl::string_view) { invoked = true; };
1096     {
1097       absl::Cord copy;
1098       {
1099         auto c = absl::MakeCordFromExternal(large_dummy, releaser);
1100         copy = c;
1101         EXPECT_FALSE(invoked);
1102       }
1103       EXPECT_FALSE(invoked);
1104     }
1105     EXPECT_TRUE(invoked);
1106   }
1107 }
1108 
TEST_P(CordTest,ConstructFromExternalCompareContents)1109 TEST_P(CordTest, ConstructFromExternalCompareContents) {
1110   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1111 
1112   for (int length = 1; length <= 2048; length *= 2) {
1113     std::string data = RandomLowercaseString(&rng, length);
1114     auto* external = new std::string(data);
1115     auto cord =
1116         absl::MakeCordFromExternal(*external, [external](absl::string_view sv) {
1117           EXPECT_EQ(external->data(), sv.data());
1118           EXPECT_EQ(external->size(), sv.size());
1119           delete external;
1120         });
1121     EXPECT_EQ(data, cord);
1122   }
1123 }
1124 
TEST_P(CordTest,ConstructFromExternalLargeReleaser)1125 TEST_P(CordTest, ConstructFromExternalLargeReleaser) {
1126   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1127   constexpr size_t kLength = 256;
1128   std::string data = RandomLowercaseString(&rng, kLength);
1129   std::array<char, kLength> data_array;
1130   for (size_t i = 0; i < kLength; ++i) data_array[i] = data[i];
1131   bool invoked = false;
1132   auto releaser = [data_array, &invoked](absl::string_view data) {
1133     EXPECT_EQ(data, absl::string_view(data_array.data(), data_array.size()));
1134     invoked = true;
1135   };
1136   (void)absl::MakeCordFromExternal(data, releaser);
1137   EXPECT_TRUE(invoked);
1138 }
1139 
TEST_P(CordTest,ConstructFromExternalFunctionPointerReleaser)1140 TEST_P(CordTest, ConstructFromExternalFunctionPointerReleaser) {
1141   static absl::string_view data("hello world");
1142   static bool invoked;
1143   auto* releaser =
1144       static_cast<void (*)(absl::string_view)>([](absl::string_view sv) {
1145         EXPECT_EQ(data, sv);
1146         invoked = true;
1147       });
1148   invoked = false;
1149   (void)absl::MakeCordFromExternal(data, releaser);
1150   EXPECT_TRUE(invoked);
1151 
1152   invoked = false;
1153   (void)absl::MakeCordFromExternal(data, *releaser);
1154   EXPECT_TRUE(invoked);
1155 }
1156 
TEST_P(CordTest,ConstructFromExternalMoveOnlyReleaser)1157 TEST_P(CordTest, ConstructFromExternalMoveOnlyReleaser) {
1158   struct Releaser {
1159     explicit Releaser(bool* invoked) : invoked(invoked) {}
1160     Releaser(Releaser&& other) noexcept : invoked(other.invoked) {}
1161     void operator()(absl::string_view) const { *invoked = true; }
1162 
1163     bool* invoked;
1164   };
1165 
1166   bool invoked = false;
1167   (void)absl::MakeCordFromExternal("dummy", Releaser(&invoked));
1168   EXPECT_TRUE(invoked);
1169 }
1170 
TEST_P(CordTest,ConstructFromExternalNoArgLambda)1171 TEST_P(CordTest, ConstructFromExternalNoArgLambda) {
1172   bool invoked = false;
1173   (void)absl::MakeCordFromExternal("dummy", [&invoked]() { invoked = true; });
1174   EXPECT_TRUE(invoked);
1175 }
1176 
TEST_P(CordTest,ConstructFromExternalStringViewArgLambda)1177 TEST_P(CordTest, ConstructFromExternalStringViewArgLambda) {
1178   bool invoked = false;
1179   (void)absl::MakeCordFromExternal(
1180       "dummy", [&invoked](absl::string_view) { invoked = true; });
1181   EXPECT_TRUE(invoked);
1182 }
1183 
TEST_P(CordTest,ConstructFromExternalNonTrivialReleaserDestructor)1184 TEST_P(CordTest, ConstructFromExternalNonTrivialReleaserDestructor) {
1185   struct Releaser {
1186     explicit Releaser(bool* destroyed) : destroyed(destroyed) {}
1187     ~Releaser() { *destroyed = true; }
1188     void operator()(absl::string_view) const {}
1189 
1190     bool* destroyed;
1191   };
1192 
1193   bool destroyed = false;
1194   Releaser releaser(&destroyed);
1195   (void)absl::MakeCordFromExternal("dummy", releaser);
1196   EXPECT_TRUE(destroyed);
1197 }
1198 
TEST_P(CordTest,ConstructFromExternalReferenceQualifierOverloads)1199 TEST_P(CordTest, ConstructFromExternalReferenceQualifierOverloads) {
1200   struct Releaser {
1201     void operator()(absl::string_view) & { *lvalue_invoked = true; }
1202     void operator()(absl::string_view) && { *rvalue_invoked = true; }
1203 
1204     bool* lvalue_invoked;
1205     bool* rvalue_invoked;
1206   };
1207 
1208   bool lvalue_invoked = false;
1209   bool rvalue_invoked = false;
1210   Releaser releaser = {&lvalue_invoked, &rvalue_invoked};
1211   (void)absl::MakeCordFromExternal("", releaser);
1212   EXPECT_FALSE(lvalue_invoked);
1213   EXPECT_TRUE(rvalue_invoked);
1214   rvalue_invoked = false;
1215 
1216   (void)absl::MakeCordFromExternal("dummy", releaser);
1217   EXPECT_FALSE(lvalue_invoked);
1218   EXPECT_TRUE(rvalue_invoked);
1219   rvalue_invoked = false;
1220 
1221   // NOLINTNEXTLINE: suppress clang-tidy std::move on trivially copyable type.
1222   (void)absl::MakeCordFromExternal("dummy", std::move(releaser));
1223   EXPECT_FALSE(lvalue_invoked);
1224   EXPECT_TRUE(rvalue_invoked);
1225 }
1226 
TEST_P(CordTest,ExternalMemoryBasicUsage)1227 TEST_P(CordTest, ExternalMemoryBasicUsage) {
1228   static const char* strings[] = {"", "hello", "there"};
1229   for (const char* str : strings) {
1230     absl::Cord dst("(prefix)");
1231     AddExternalMemory(str, &dst);
1232     dst.Append("(suffix)");
1233     EXPECT_EQ((std::string("(prefix)") + str + std::string("(suffix)")),
1234               std::string(dst));
1235   }
1236 }
1237 
TEST_P(CordTest,ExternalMemoryRemovePrefixSuffix)1238 TEST_P(CordTest, ExternalMemoryRemovePrefixSuffix) {
1239   // Exhaustively try all sub-strings.
1240   absl::Cord cord = MakeComposite();
1241   std::string s = std::string(cord);
1242   for (int offset = 0; offset <= s.size(); offset++) {
1243     for (int length = 0; length <= s.size() - offset; length++) {
1244       absl::Cord result(cord);
1245       result.RemovePrefix(offset);
1246       result.RemoveSuffix(result.size() - length);
1247       EXPECT_EQ(s.substr(offset, length), std::string(result))
1248           << offset << " " << length;
1249     }
1250   }
1251 }
1252 
TEST_P(CordTest,ExternalMemoryGet)1253 TEST_P(CordTest, ExternalMemoryGet) {
1254   absl::Cord cord("hello");
1255   AddExternalMemory(" world!", &cord);
1256   AddExternalMemory(" how are ", &cord);
1257   cord.Append(" you?");
1258   std::string s = std::string(cord);
1259   for (int i = 0; i < s.size(); i++) {
1260     EXPECT_EQ(s[i], cord[i]);
1261   }
1262 }
1263 
1264 // CordMemoryUsage tests verify the correctness of the EstimatedMemoryUsage()
1265 // These tests take into account that the reported memory usage is approximate
1266 // and non-deterministic. For all tests, We verify that the reported memory
1267 // usage is larger than `size()`, and less than `size() * 1.5` as a cord should
1268 // never reserve more 'extra' capacity than half of its size as it grows.
1269 // Additionally we have some whiteboxed expectations based on our knowledge of
1270 // the layout and size of empty and inlined cords, and flat nodes.
1271 
TEST_P(CordTest,CordMemoryUsageEmpty)1272 TEST_P(CordTest, CordMemoryUsageEmpty) {
1273   EXPECT_EQ(sizeof(absl::Cord), absl::Cord().EstimatedMemoryUsage());
1274 }
1275 
TEST_P(CordTest,CordMemoryUsageEmbedded)1276 TEST_P(CordTest, CordMemoryUsageEmbedded) {
1277   absl::Cord a("hello");
1278   EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
1279 }
1280 
TEST_P(CordTest,CordMemoryUsageEmbeddedAppend)1281 TEST_P(CordTest, CordMemoryUsageEmbeddedAppend) {
1282   absl::Cord a("a");
1283   absl::Cord b("bcd");
1284   EXPECT_EQ(b.EstimatedMemoryUsage(), sizeof(absl::Cord));
1285   a.Append(b);
1286   EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
1287 }
1288 
TEST_P(CordTest,CordMemoryUsageExternalMemory)1289 TEST_P(CordTest, CordMemoryUsageExternalMemory) {
1290   static const int kLength = 1000;
1291   absl::Cord cord;
1292   AddExternalMemory(std::string(kLength, 'x'), &cord);
1293   EXPECT_GT(cord.EstimatedMemoryUsage(), kLength);
1294   EXPECT_LE(cord.EstimatedMemoryUsage(), kLength * 1.5);
1295 }
1296 
TEST_P(CordTest,CordMemoryUsageFlat)1297 TEST_P(CordTest, CordMemoryUsageFlat) {
1298   static const int kLength = 125;
1299   absl::Cord a(std::string(kLength, 'a'));
1300   EXPECT_GT(a.EstimatedMemoryUsage(), kLength);
1301   EXPECT_LE(a.EstimatedMemoryUsage(), kLength * 1.5);
1302 }
1303 
TEST_P(CordTest,CordMemoryUsageAppendFlat)1304 TEST_P(CordTest, CordMemoryUsageAppendFlat) {
1305   using absl::strings_internal::CordTestAccess;
1306   absl::Cord a(std::string(CordTestAccess::MaxFlatLength(), 'a'));
1307   size_t length = a.EstimatedMemoryUsage();
1308   a.Append(std::string(CordTestAccess::MaxFlatLength(), 'b'));
1309   size_t delta = a.EstimatedMemoryUsage() - length;
1310   EXPECT_GT(delta, CordTestAccess::MaxFlatLength());
1311   EXPECT_LE(delta, CordTestAccess::MaxFlatLength() * 1.5);
1312 }
1313 
TEST_P(CordTest,CordMemoryUsageAppendExternal)1314 TEST_P(CordTest, CordMemoryUsageAppendExternal) {
1315   static const int kLength = 1000;
1316   using absl::strings_internal::CordTestAccess;
1317   absl::Cord a(std::string(CordTestAccess::MaxFlatLength(), 'a'));
1318   size_t length = a.EstimatedMemoryUsage();
1319   AddExternalMemory(std::string(kLength, 'b'), &a);
1320   size_t delta = a.EstimatedMemoryUsage() - length;
1321   EXPECT_GT(delta, kLength);
1322   EXPECT_LE(delta, kLength * 1.5);
1323 }
1324 
TEST_P(CordTest,CordMemoryUsageSubString)1325 TEST_P(CordTest, CordMemoryUsageSubString) {
1326   static const int kLength = 2000;
1327   using absl::strings_internal::CordTestAccess;
1328   absl::Cord a(std::string(kLength, 'a'));
1329   size_t length = a.EstimatedMemoryUsage();
1330   AddExternalMemory(std::string(kLength, 'b'), &a);
1331   absl::Cord b = a.Subcord(0, kLength + kLength / 2);
1332   size_t delta = b.EstimatedMemoryUsage() - length;
1333   EXPECT_GT(delta, kLength);
1334   EXPECT_LE(delta, kLength * 1.5);
1335 }
1336 
1337 // Regtest for a change that had to be rolled back because it expanded out
1338 // of the InlineRep too soon, which was observable through MemoryUsage().
TEST_P(CordTest,CordMemoryUsageInlineRep)1339 TEST_P(CordTest, CordMemoryUsageInlineRep) {
1340   constexpr size_t kMaxInline = 15;  // Cord::InlineRep::N
1341   const std::string small_string(kMaxInline, 'x');
1342   absl::Cord c1(small_string);
1343 
1344   absl::Cord c2;
1345   c2.Append(small_string);
1346   EXPECT_EQ(c1, c2);
1347   EXPECT_EQ(c1.EstimatedMemoryUsage(), c2.EstimatedMemoryUsage());
1348 }
1349 
1350 }  // namespace
1351 
1352 // Regtest for 7510292 (fix a bug introduced by 7465150)
TEST_P(CordTest,Concat_Append)1353 TEST_P(CordTest, Concat_Append) {
1354   // Create a rep of type CONCAT
1355   absl::Cord s1("foobarbarbarbarbar");
1356   s1.Append("abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg");
1357   size_t size = s1.size();
1358 
1359   // Create a copy of s1 and append to it.
1360   absl::Cord s2 = s1;
1361   s2.Append("x");
1362 
1363   // 7465150 modifies s1 when it shouldn't.
1364   EXPECT_EQ(s1.size(), size);
1365   EXPECT_EQ(s2.size(), size + 1);
1366 }
1367 
TEST_P(CordTest,DiabolicalGrowth)1368 TEST_P(CordTest, DiabolicalGrowth) {
1369   // This test exercises a diabolical Append(<one char>) on a cord, making the
1370   // cord shared before each Append call resulting in a terribly fragmented
1371   // resulting cord.
1372   // TODO(b/183983616): Apply some minimum compaction when copying a shared
1373   // source cord into a mutable copy for updates in CordRepRing.
1374   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1375   const std::string expected = RandomLowercaseString(&rng, 5000);
1376   absl::Cord cord;
1377   for (char c : expected) {
1378     absl::Cord shared(cord);
1379     cord.Append(absl::string_view(&c, 1));
1380   }
1381   std::string value;
1382   absl::CopyCordToString(cord, &value);
1383   EXPECT_EQ(value, expected);
1384   ABSL_RAW_LOG(INFO, "Diabolical size allocated = %zu",
1385                cord.EstimatedMemoryUsage());
1386 }
1387 
TEST_P(CordTest,MakeFragmentedCordFromInitializerList)1388 TEST_P(CordTest, MakeFragmentedCordFromInitializerList) {
1389   absl::Cord fragmented =
1390       absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
1391 
1392   EXPECT_EQ("A fragmented Cord", fragmented);
1393 
1394   auto chunk_it = fragmented.chunk_begin();
1395 
1396   ASSERT_TRUE(chunk_it != fragmented.chunk_end());
1397   EXPECT_EQ("A ", *chunk_it);
1398 
1399   ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
1400   EXPECT_EQ("fragmented ", *chunk_it);
1401 
1402   ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
1403   EXPECT_EQ("Cord", *chunk_it);
1404 
1405   ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
1406 }
1407 
TEST_P(CordTest,MakeFragmentedCordFromVector)1408 TEST_P(CordTest, MakeFragmentedCordFromVector) {
1409   std::vector<absl::string_view> chunks = {"A ", "fragmented ", "Cord"};
1410   absl::Cord fragmented = absl::MakeFragmentedCord(chunks);
1411 
1412   EXPECT_EQ("A fragmented Cord", fragmented);
1413 
1414   auto chunk_it = fragmented.chunk_begin();
1415 
1416   ASSERT_TRUE(chunk_it != fragmented.chunk_end());
1417   EXPECT_EQ("A ", *chunk_it);
1418 
1419   ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
1420   EXPECT_EQ("fragmented ", *chunk_it);
1421 
1422   ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
1423   EXPECT_EQ("Cord", *chunk_it);
1424 
1425   ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
1426 }
1427 
TEST_P(CordTest,CordChunkIteratorTraits)1428 TEST_P(CordTest, CordChunkIteratorTraits) {
1429   static_assert(std::is_copy_constructible<absl::Cord::ChunkIterator>::value,
1430                 "");
1431   static_assert(std::is_copy_assignable<absl::Cord::ChunkIterator>::value, "");
1432 
1433   // Move semantics to satisfy swappable via std::swap
1434   static_assert(std::is_move_constructible<absl::Cord::ChunkIterator>::value,
1435                 "");
1436   static_assert(std::is_move_assignable<absl::Cord::ChunkIterator>::value, "");
1437 
1438   static_assert(
1439       std::is_same<
1440           std::iterator_traits<absl::Cord::ChunkIterator>::iterator_category,
1441           std::input_iterator_tag>::value,
1442       "");
1443   static_assert(
1444       std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::value_type,
1445                    absl::string_view>::value,
1446       "");
1447   static_assert(
1448       std::is_same<
1449           std::iterator_traits<absl::Cord::ChunkIterator>::difference_type,
1450           ptrdiff_t>::value,
1451       "");
1452   static_assert(
1453       std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::pointer,
1454                    const absl::string_view*>::value,
1455       "");
1456   static_assert(
1457       std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::reference,
1458                    absl::string_view>::value,
1459       "");
1460 }
1461 
VerifyChunkIterator(const absl::Cord & cord,size_t expected_chunks)1462 static void VerifyChunkIterator(const absl::Cord& cord,
1463                                 size_t expected_chunks) {
1464   EXPECT_EQ(cord.chunk_begin() == cord.chunk_end(), cord.empty()) << cord;
1465   EXPECT_EQ(cord.chunk_begin() != cord.chunk_end(), !cord.empty());
1466 
1467   absl::Cord::ChunkRange range = cord.Chunks();
1468   EXPECT_EQ(range.begin() == range.end(), cord.empty());
1469   EXPECT_EQ(range.begin() != range.end(), !cord.empty());
1470 
1471   std::string content(cord);
1472   size_t pos = 0;
1473   auto pre_iter = cord.chunk_begin(), post_iter = cord.chunk_begin();
1474   size_t n_chunks = 0;
1475   while (pre_iter != cord.chunk_end() && post_iter != cord.chunk_end()) {
1476     EXPECT_FALSE(pre_iter == cord.chunk_end());   // NOLINT: explicitly test ==
1477     EXPECT_FALSE(post_iter == cord.chunk_end());  // NOLINT
1478 
1479     EXPECT_EQ(pre_iter, post_iter);
1480     EXPECT_EQ(*pre_iter, *post_iter);
1481 
1482     EXPECT_EQ(pre_iter->data(), (*pre_iter).data());
1483     EXPECT_EQ(pre_iter->size(), (*pre_iter).size());
1484 
1485     absl::string_view chunk = *pre_iter;
1486     EXPECT_FALSE(chunk.empty());
1487     EXPECT_LE(pos + chunk.size(), content.size());
1488     EXPECT_EQ(absl::string_view(content.c_str() + pos, chunk.size()), chunk);
1489 
1490     int n_equal_iterators = 0;
1491     for (absl::Cord::ChunkIterator it = range.begin(); it != range.end();
1492          ++it) {
1493       n_equal_iterators += static_cast<int>(it == pre_iter);
1494     }
1495     EXPECT_EQ(n_equal_iterators, 1);
1496 
1497     ++pre_iter;
1498     EXPECT_EQ(*post_iter++, chunk);
1499 
1500     pos += chunk.size();
1501     ++n_chunks;
1502   }
1503   EXPECT_EQ(expected_chunks, n_chunks);
1504   EXPECT_EQ(pos, content.size());
1505   EXPECT_TRUE(pre_iter == cord.chunk_end());   // NOLINT: explicitly test ==
1506   EXPECT_TRUE(post_iter == cord.chunk_end());  // NOLINT
1507 }
1508 
TEST_P(CordTest,CordChunkIteratorOperations)1509 TEST_P(CordTest, CordChunkIteratorOperations) {
1510   absl::Cord empty_cord;
1511   VerifyChunkIterator(empty_cord, 0);
1512 
1513   absl::Cord small_buffer_cord("small cord");
1514   VerifyChunkIterator(small_buffer_cord, 1);
1515 
1516   absl::Cord flat_node_cord("larger than small buffer optimization");
1517   VerifyChunkIterator(flat_node_cord, 1);
1518 
1519   VerifyChunkIterator(
1520       absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ",
1521                                 "testing ", "chunk ", "iterations."}),
1522       8);
1523 
1524   absl::Cord reused_nodes_cord(std::string(40, 'c'));
1525   reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'b')));
1526   reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'a')));
1527   size_t expected_chunks = 3;
1528   for (int i = 0; i < 8; ++i) {
1529     reused_nodes_cord.Prepend(reused_nodes_cord);
1530     expected_chunks *= 2;
1531     VerifyChunkIterator(reused_nodes_cord, expected_chunks);
1532   }
1533 
1534   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1535   absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
1536   absl::Cord subcords;
1537   for (int i = 0; i < 128; ++i) subcords.Prepend(flat_cord.Subcord(i, 128));
1538   VerifyChunkIterator(subcords, 128);
1539 }
1540 
TEST(CordCharIterator,Traits)1541 TEST(CordCharIterator, Traits) {
1542   static_assert(std::is_copy_constructible<absl::Cord::CharIterator>::value,
1543                 "");
1544   static_assert(std::is_copy_assignable<absl::Cord::CharIterator>::value, "");
1545 
1546   // Move semantics to satisfy swappable via std::swap
1547   static_assert(std::is_move_constructible<absl::Cord::CharIterator>::value,
1548                 "");
1549   static_assert(std::is_move_assignable<absl::Cord::CharIterator>::value, "");
1550 
1551   static_assert(
1552       std::is_same<
1553           std::iterator_traits<absl::Cord::CharIterator>::iterator_category,
1554           std::input_iterator_tag>::value,
1555       "");
1556   static_assert(
1557       std::is_same<std::iterator_traits<absl::Cord::CharIterator>::value_type,
1558                    char>::value,
1559       "");
1560   static_assert(
1561       std::is_same<
1562           std::iterator_traits<absl::Cord::CharIterator>::difference_type,
1563           ptrdiff_t>::value,
1564       "");
1565   static_assert(
1566       std::is_same<std::iterator_traits<absl::Cord::CharIterator>::pointer,
1567                    const char*>::value,
1568       "");
1569   static_assert(
1570       std::is_same<std::iterator_traits<absl::Cord::CharIterator>::reference,
1571                    const char&>::value,
1572       "");
1573 }
1574 
VerifyCharIterator(const absl::Cord & cord)1575 static void VerifyCharIterator(const absl::Cord& cord) {
1576   EXPECT_EQ(cord.char_begin() == cord.char_end(), cord.empty());
1577   EXPECT_EQ(cord.char_begin() != cord.char_end(), !cord.empty());
1578 
1579   absl::Cord::CharRange range = cord.Chars();
1580   EXPECT_EQ(range.begin() == range.end(), cord.empty());
1581   EXPECT_EQ(range.begin() != range.end(), !cord.empty());
1582 
1583   size_t i = 0;
1584   absl::Cord::CharIterator pre_iter = cord.char_begin();
1585   absl::Cord::CharIterator post_iter = cord.char_begin();
1586   std::string content(cord);
1587   while (pre_iter != cord.char_end() && post_iter != cord.char_end()) {
1588     EXPECT_FALSE(pre_iter == cord.char_end());   // NOLINT: explicitly test ==
1589     EXPECT_FALSE(post_iter == cord.char_end());  // NOLINT
1590 
1591     EXPECT_LT(i, cord.size());
1592     EXPECT_EQ(content[i], *pre_iter);
1593 
1594     EXPECT_EQ(pre_iter, post_iter);
1595     EXPECT_EQ(*pre_iter, *post_iter);
1596     EXPECT_EQ(&*pre_iter, &*post_iter);
1597 
1598     EXPECT_EQ(&*pre_iter, pre_iter.operator->());
1599 
1600     const char* character_address = &*pre_iter;
1601     absl::Cord::CharIterator copy = pre_iter;
1602     ++copy;
1603     EXPECT_EQ(character_address, &*pre_iter);
1604 
1605     int n_equal_iterators = 0;
1606     for (absl::Cord::CharIterator it = range.begin(); it != range.end(); ++it) {
1607       n_equal_iterators += static_cast<int>(it == pre_iter);
1608     }
1609     EXPECT_EQ(n_equal_iterators, 1);
1610 
1611     absl::Cord::CharIterator advance_iter = range.begin();
1612     absl::Cord::Advance(&advance_iter, i);
1613     EXPECT_EQ(pre_iter, advance_iter);
1614 
1615     advance_iter = range.begin();
1616     EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, i), cord.Subcord(0, i));
1617     EXPECT_EQ(pre_iter, advance_iter);
1618 
1619     advance_iter = pre_iter;
1620     absl::Cord::Advance(&advance_iter, cord.size() - i);
1621     EXPECT_EQ(range.end(), advance_iter);
1622 
1623     advance_iter = pre_iter;
1624     EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, cord.size() - i),
1625               cord.Subcord(i, cord.size() - i));
1626     EXPECT_EQ(range.end(), advance_iter);
1627 
1628     ++i;
1629     ++pre_iter;
1630     post_iter++;
1631   }
1632   EXPECT_EQ(i, cord.size());
1633   EXPECT_TRUE(pre_iter == cord.char_end());   // NOLINT: explicitly test ==
1634   EXPECT_TRUE(post_iter == cord.char_end());  // NOLINT
1635 
1636   absl::Cord::CharIterator zero_advanced_end = cord.char_end();
1637   absl::Cord::Advance(&zero_advanced_end, 0);
1638   EXPECT_EQ(zero_advanced_end, cord.char_end());
1639 
1640   absl::Cord::CharIterator it = cord.char_begin();
1641   for (absl::string_view chunk : cord.Chunks()) {
1642     while (!chunk.empty()) {
1643       EXPECT_EQ(absl::Cord::ChunkRemaining(it), chunk);
1644       chunk.remove_prefix(1);
1645       ++it;
1646     }
1647   }
1648 }
1649 
TEST(CordCharIterator,Operations)1650 TEST(CordCharIterator, Operations) {
1651   absl::Cord empty_cord;
1652   VerifyCharIterator(empty_cord);
1653 
1654   absl::Cord small_buffer_cord("small cord");
1655   VerifyCharIterator(small_buffer_cord);
1656 
1657   absl::Cord flat_node_cord("larger than small buffer optimization");
1658   VerifyCharIterator(flat_node_cord);
1659 
1660   VerifyCharIterator(
1661       absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ",
1662                                 "testing ", "character ", "iteration."}));
1663 
1664   absl::Cord reused_nodes_cord("ghi");
1665   reused_nodes_cord.Prepend(absl::Cord("def"));
1666   reused_nodes_cord.Prepend(absl::Cord("abc"));
1667   for (int i = 0; i < 4; ++i) {
1668     reused_nodes_cord.Prepend(reused_nodes_cord);
1669     VerifyCharIterator(reused_nodes_cord);
1670   }
1671 
1672   RandomEngine rng(GTEST_FLAG_GET(random_seed));
1673   absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
1674   absl::Cord subcords;
1675   for (int i = 0; i < 4; ++i) subcords.Prepend(flat_cord.Subcord(16 * i, 128));
1676   VerifyCharIterator(subcords);
1677 }
1678 
TEST_P(CordTest,StreamingOutput)1679 TEST_P(CordTest, StreamingOutput) {
1680   absl::Cord c =
1681       absl::MakeFragmentedCord({"A ", "small ", "fragmented ", "Cord", "."});
1682   std::stringstream output;
1683   output << c;
1684   EXPECT_EQ("A small fragmented Cord.", output.str());
1685 }
1686 
TEST_P(CordTest,ForEachChunk)1687 TEST_P(CordTest, ForEachChunk) {
1688   for (int num_elements : {1, 10, 200}) {
1689     SCOPED_TRACE(num_elements);
1690     std::vector<std::string> cord_chunks;
1691     for (int i = 0; i < num_elements; ++i) {
1692       cord_chunks.push_back(absl::StrCat("[", i, "]"));
1693     }
1694     absl::Cord c = absl::MakeFragmentedCord(cord_chunks);
1695 
1696     std::vector<std::string> iterated_chunks;
1697     absl::CordTestPeer::ForEachChunk(c,
1698                                      [&iterated_chunks](absl::string_view sv) {
1699                                        iterated_chunks.emplace_back(sv);
1700                                      });
1701     EXPECT_EQ(iterated_chunks, cord_chunks);
1702   }
1703 }
1704 
TEST_P(CordTest,SmallBufferAssignFromOwnData)1705 TEST_P(CordTest, SmallBufferAssignFromOwnData) {
1706   constexpr size_t kMaxInline = 15;
1707   std::string contents = "small buff cord";
1708   EXPECT_EQ(contents.size(), kMaxInline);
1709   for (size_t pos = 0; pos < contents.size(); ++pos) {
1710     for (size_t count = contents.size() - pos; count > 0; --count) {
1711       absl::Cord c(contents);
1712       absl::string_view flat = c.Flatten();
1713       c = flat.substr(pos, count);
1714       EXPECT_EQ(c, contents.substr(pos, count))
1715           << "pos = " << pos << "; count = " << count;
1716     }
1717   }
1718 }
1719 
TEST_P(CordTest,Format)1720 TEST_P(CordTest, Format) {
1721   absl::Cord c;
1722   absl::Format(&c, "There were %04d little %s.", 3, "pigs");
1723   EXPECT_EQ(c, "There were 0003 little pigs.");
1724   absl::Format(&c, "And %-3llx bad wolf!", 1);
1725   EXPECT_EQ(c, "There were 0003 little pigs.And 1   bad wolf!");
1726 }
1727 
TEST(CordDeathTest,Hardening)1728 TEST(CordDeathTest, Hardening) {
1729   absl::Cord cord("hello");
1730   // These statement should abort the program in all builds modes.
1731   EXPECT_DEATH_IF_SUPPORTED(cord.RemovePrefix(6), "");
1732   EXPECT_DEATH_IF_SUPPORTED(cord.RemoveSuffix(6), "");
1733 
1734   bool test_hardening = false;
1735   ABSL_HARDENING_ASSERT([&]() {
1736     // This only runs when ABSL_HARDENING_ASSERT is active.
1737     test_hardening = true;
1738     return true;
1739   }());
1740   if (!test_hardening) return;
1741 
1742   EXPECT_DEATH_IF_SUPPORTED(cord[5], "");
1743   EXPECT_DEATH_IF_SUPPORTED(*cord.chunk_end(), "");
1744   EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), "");
1745   EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), "");
1746 }
1747 
1748 class AfterExitCordTester {
1749  public:
Set(absl::Cord * cord,absl::string_view expected)1750   bool Set(absl::Cord* cord, absl::string_view expected) {
1751     cord_ = cord;
1752     expected_ = expected;
1753     return true;
1754   }
1755 
~AfterExitCordTester()1756   ~AfterExitCordTester() {
1757     EXPECT_EQ(*cord_, expected_);
1758   }
1759  private:
1760   absl::Cord* cord_;
1761   absl::string_view expected_;
1762 };
1763 
1764 template <typename Str>
TestConstinitConstructor(Str)1765 void TestConstinitConstructor(Str) {
1766   const auto expected = Str::value;
1767   // Defined before `cord` to be destroyed after it.
1768   static AfterExitCordTester exit_tester;  // NOLINT
1769   ABSL_CONST_INIT static absl::Cord cord(Str{});  // NOLINT
1770   static bool init_exit_tester = exit_tester.Set(&cord, expected);
1771   (void)init_exit_tester;
1772 
1773   EXPECT_EQ(cord, expected);
1774   // Copy the object and test the copy, and the original.
1775   {
1776     absl::Cord copy = cord;
1777     EXPECT_EQ(copy, expected);
1778   }
1779   // The original still works
1780   EXPECT_EQ(cord, expected);
1781 
1782   // Try making adding more structure to the tree.
1783   {
1784     absl::Cord copy = cord;
1785     std::string expected_copy(expected);
1786     for (int i = 0; i < 10; ++i) {
1787       copy.Append(cord);
1788       absl::StrAppend(&expected_copy, expected);
1789       EXPECT_EQ(copy, expected_copy);
1790     }
1791   }
1792 
1793   // Make sure we are using the right branch during constant evaluation.
1794   EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16);
1795 
1796   for (int i = 0; i < 10; ++i) {
1797     // Make a few more Cords from the same global rep.
1798     // This tests what happens when the refcount for it gets below 1.
1799     EXPECT_EQ(expected, absl::Cord(Str{}));
1800   }
1801 }
1802 
SimpleStrlen(const char * p)1803 constexpr int SimpleStrlen(const char* p) {
1804   return *p ? 1 + SimpleStrlen(p + 1) : 0;
1805 }
1806 
1807 struct ShortView {
operator ()ShortView1808   constexpr absl::string_view operator()() const {
1809     return absl::string_view("SSO string", SimpleStrlen("SSO string"));
1810   }
1811 };
1812 
1813 struct LongView {
operator ()LongView1814   constexpr absl::string_view operator()() const {
1815     return absl::string_view("String that does not fit SSO.",
1816                              SimpleStrlen("String that does not fit SSO."));
1817   }
1818 };
1819 
1820 
TEST_P(CordTest,ConstinitConstructor)1821 TEST_P(CordTest, ConstinitConstructor) {
1822   TestConstinitConstructor(
1823       absl::strings_internal::MakeStringConstant(ShortView{}));
1824   TestConstinitConstructor(
1825       absl::strings_internal::MakeStringConstant(LongView{}));
1826 }
1827