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