tor-browser

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

str_join_test.cc (18313B)


      1 // Copyright 2017 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 // Unit tests for all join.h functions
     16 
     17 #include "absl/strings/str_join.h"
     18 
     19 #include <cstddef>
     20 #include <cstdint>
     21 #include <cstdio>
     22 #include <functional>
     23 #include <initializer_list>
     24 #include <iterator>
     25 #include <map>
     26 #include <memory>
     27 #include <ostream>
     28 #include <string>
     29 #include <tuple>
     30 #include <utility>
     31 #include <vector>
     32 
     33 #include "gtest/gtest.h"
     34 #include "absl/base/macros.h"
     35 #include "absl/memory/memory.h"
     36 #include "absl/strings/str_cat.h"
     37 #include "absl/strings/str_split.h"
     38 #include "absl/strings/string_view.h"
     39 
     40 namespace {
     41 
     42 TEST(StrJoin, APIExamples) {
     43  {
     44    // Collection of strings
     45    std::vector<std::string> v = {"foo", "bar", "baz"};
     46    EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
     47  }
     48 
     49  {
     50    // Collection of absl::string_view
     51    std::vector<absl::string_view> v = {"foo", "bar", "baz"};
     52    EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
     53  }
     54 
     55  {
     56    // Collection of const char*
     57    std::vector<const char*> v = {"foo", "bar", "baz"};
     58    EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
     59  }
     60 
     61  {
     62    // Collection of non-const char*
     63    std::string a = "foo", b = "bar", c = "baz";
     64    std::vector<char*> v = {&a[0], &b[0], &c[0]};
     65    EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
     66  }
     67 
     68  {
     69    // Collection of ints
     70    std::vector<int> v = {1, 2, 3, -4};
     71    EXPECT_EQ("1-2-3--4", absl::StrJoin(v, "-"));
     72  }
     73 
     74  {
     75    // Literals passed as a std::initializer_list
     76    std::string s = absl::StrJoin({"a", "b", "c"}, "-");
     77    EXPECT_EQ("a-b-c", s);
     78  }
     79  {
     80    // Join a std::tuple<T...>.
     81    std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
     82    EXPECT_EQ("123-abc-0.456", s);
     83  }
     84 
     85  {
     86    // Collection of unique_ptrs
     87    std::vector<std::unique_ptr<int>> v;
     88    v.emplace_back(new int(1));
     89    v.emplace_back(new int(2));
     90    v.emplace_back(new int(3));
     91    EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
     92  }
     93 
     94  {
     95    // Array of ints
     96    const int a[] = {1, 2, 3, -4};
     97    EXPECT_EQ("1-2-3--4", absl::StrJoin(a, a + ABSL_ARRAYSIZE(a), "-"));
     98  }
     99 
    100  {
    101    // Collection of pointers
    102    int x = 1, y = 2, z = 3;
    103    std::vector<int*> v = {&x, &y, &z};
    104    EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
    105  }
    106 
    107  {
    108    // Collection of pointers to pointers
    109    int x = 1, y = 2, z = 3;
    110    int *px = &x, *py = &y, *pz = &z;
    111    std::vector<int**> v = {&px, &py, &pz};
    112    EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
    113  }
    114 
    115  {
    116    // Collection of pointers to std::string
    117    std::string a("a"), b("b");
    118    std::vector<std::string*> v = {&a, &b};
    119    EXPECT_EQ("a-b", absl::StrJoin(v, "-"));
    120  }
    121 
    122  {
    123    // A std::map, which is a collection of std::pair<>s.
    124    std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
    125    EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
    126  }
    127 
    128  {
    129    // Shows absl::StrSplit and absl::StrJoin working together. This example is
    130    // equivalent to s/=/-/g.
    131    const std::string s = "a=b=c=d";
    132    EXPECT_EQ("a-b-c-d", absl::StrJoin(absl::StrSplit(s, "="), "-"));
    133  }
    134 
    135  //
    136  // A few examples of edge cases
    137  //
    138 
    139  {
    140    // Empty range yields an empty string.
    141    std::vector<std::string> v;
    142    EXPECT_EQ("", absl::StrJoin(v, "-"));
    143  }
    144 
    145  {
    146    // A range of 1 element gives a string with that element but no
    147    // separator.
    148    std::vector<std::string> v = {"foo"};
    149    EXPECT_EQ("foo", absl::StrJoin(v, "-"));
    150  }
    151 
    152  {
    153    // A range with a single empty string element
    154    std::vector<std::string> v = {""};
    155    EXPECT_EQ("", absl::StrJoin(v, "-"));
    156  }
    157 
    158  {
    159    // A range with 2 elements, one of which is an empty string
    160    std::vector<std::string> v = {"a", ""};
    161    EXPECT_EQ("a-", absl::StrJoin(v, "-"));
    162  }
    163 
    164  {
    165    // A range with 2 empty elements.
    166    std::vector<std::string> v = {"", ""};
    167    EXPECT_EQ("-", absl::StrJoin(v, "-"));
    168  }
    169 
    170  {
    171    // A std::vector of bool.
    172    std::vector<bool> v = {true, false, true};
    173    EXPECT_EQ("1-0-1", absl::StrJoin(v, "-"));
    174  }
    175 }
    176 
    177 TEST(StrJoin, CustomFormatter) {
    178  std::vector<std::string> v{"One", "Two", "Three"};
    179  {
    180    std::string joined =
    181        absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
    182          absl::StrAppend(out, "(", in, ")");
    183        });
    184    EXPECT_EQ("(One)(Two)(Three)", joined);
    185  }
    186  {
    187    class ImmovableFormatter {
    188     public:
    189      void operator()(std::string* out, const std::string& in) {
    190        absl::StrAppend(out, "(", in, ")");
    191      }
    192      ImmovableFormatter() {}
    193      ImmovableFormatter(const ImmovableFormatter&) = delete;
    194    };
    195    EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", ImmovableFormatter()));
    196  }
    197  {
    198    class OverloadedFormatter {
    199     public:
    200      void operator()(std::string* out, const std::string& in) {
    201        absl::StrAppend(out, "(", in, ")");
    202      }
    203      void operator()(std::string* out, const std::string& in) const {
    204        absl::StrAppend(out, "[", in, "]");
    205      }
    206    };
    207    EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", OverloadedFormatter()));
    208    const OverloadedFormatter fmt = {};
    209    EXPECT_EQ("[One][Two][Three]", absl::StrJoin(v, "", fmt));
    210  }
    211 }
    212 
    213 //
    214 // Tests the Formatters
    215 //
    216 
    217 TEST(AlphaNumFormatter, FormatterAPI) {
    218  // Not an exhaustive test. See strings/strcat_test.h for the exhaustive test
    219  // of what AlphaNum can convert.
    220  auto f = absl::AlphaNumFormatter();
    221  std::string s;
    222  f(&s, "Testing: ");
    223  f(&s, static_cast<int>(1));
    224  f(&s, static_cast<int16_t>(2));
    225  f(&s, static_cast<int64_t>(3));
    226  f(&s, static_cast<float>(4));
    227  f(&s, static_cast<double>(5));
    228  f(&s, static_cast<unsigned>(6));
    229  f(&s, static_cast<size_t>(7));
    230  f(&s, absl::string_view(" OK"));
    231  EXPECT_EQ("Testing: 1234567 OK", s);
    232 }
    233 
    234 // Make sure people who are mistakenly using std::vector<bool> even though
    235 // they're not memory-constrained can use absl::AlphaNumFormatter().
    236 TEST(AlphaNumFormatter, VectorOfBool) {
    237  auto f = absl::AlphaNumFormatter();
    238  std::string s;
    239  std::vector<bool> v = {true, false, true};
    240  f(&s, *v.cbegin());
    241  f(&s, *v.begin());
    242  f(&s, v[1]);
    243  EXPECT_EQ("110", s);
    244 }
    245 
    246 TEST(AlphaNumFormatter, AlphaNum) {
    247  auto f = absl::AlphaNumFormatter();
    248  std::string s;
    249  f(&s, absl::AlphaNum("hello"));
    250  EXPECT_EQ("hello", s);
    251 }
    252 
    253 struct StreamableType {
    254  std::string contents;
    255 };
    256 inline std::ostream& operator<<(std::ostream& os, const StreamableType& t) {
    257  os << "Streamable:" << t.contents;
    258  return os;
    259 }
    260 
    261 TEST(StreamFormatter, FormatterAPI) {
    262  auto f = absl::StreamFormatter();
    263  std::string s;
    264  f(&s, "Testing: ");
    265  f(&s, static_cast<int>(1));
    266  f(&s, static_cast<int16_t>(2));
    267  f(&s, static_cast<int64_t>(3));
    268  f(&s, static_cast<float>(4));
    269  f(&s, static_cast<double>(5));
    270  f(&s, static_cast<unsigned>(6));
    271  f(&s, static_cast<size_t>(7));
    272  f(&s, absl::string_view(" OK "));
    273  StreamableType streamable = {"object"};
    274  f(&s, streamable);
    275  EXPECT_EQ("Testing: 1234567 OK Streamable:object", s);
    276 }
    277 
    278 // A dummy formatter that wraps each element in parens. Used in some tests
    279 // below.
    280 struct TestingParenFormatter {
    281  template <typename T>
    282  void operator()(std::string* s, const T& t) {
    283    absl::StrAppend(s, "(", t, ")");
    284  }
    285 };
    286 
    287 TEST(PairFormatter, FormatterAPI) {
    288  {
    289    // Tests default PairFormatter(sep) that uses AlphaNumFormatter for the
    290    // 'first' and 'second' members.
    291    const auto f = absl::PairFormatter("=");
    292    std::string s;
    293    f(&s, std::make_pair("a", "b"));
    294    f(&s, std::make_pair(1, 2));
    295    EXPECT_EQ("a=b1=2", s);
    296  }
    297 
    298  {
    299    // Tests using a custom formatter for the 'first' and 'second' members.
    300    auto f = absl::PairFormatter(TestingParenFormatter(), "=",
    301                                 TestingParenFormatter());
    302    std::string s;
    303    f(&s, std::make_pair("a", "b"));
    304    f(&s, std::make_pair(1, 2));
    305    EXPECT_EQ("(a)=(b)(1)=(2)", s);
    306  }
    307 }
    308 
    309 TEST(DereferenceFormatter, FormatterAPI) {
    310  {
    311    // Tests wrapping the default AlphaNumFormatter.
    312    const absl::strings_internal::DereferenceFormatterImpl<
    313        absl::strings_internal::AlphaNumFormatterImpl>
    314        f;
    315    int x = 1, y = 2, z = 3;
    316    std::string s;
    317    f(&s, &x);
    318    f(&s, &y);
    319    f(&s, &z);
    320    EXPECT_EQ("123", s);
    321  }
    322 
    323  {
    324    // Tests wrapping std::string's default formatter.
    325    absl::strings_internal::DereferenceFormatterImpl<
    326        absl::strings_internal::DefaultFormatter<std::string>::Type>
    327        f;
    328 
    329    std::string x = "x";
    330    std::string y = "y";
    331    std::string z = "z";
    332    std::string s;
    333    f(&s, &x);
    334    f(&s, &y);
    335    f(&s, &z);
    336    EXPECT_EQ(s, "xyz");
    337  }
    338 
    339  {
    340    // Tests wrapping a custom formatter.
    341    auto f = absl::DereferenceFormatter(TestingParenFormatter());
    342    int x = 1, y = 2, z = 3;
    343    std::string s;
    344    f(&s, &x);
    345    f(&s, &y);
    346    f(&s, &z);
    347    EXPECT_EQ("(1)(2)(3)", s);
    348  }
    349 
    350  {
    351    absl::strings_internal::DereferenceFormatterImpl<
    352        absl::strings_internal::AlphaNumFormatterImpl>
    353        f;
    354    auto x = std::unique_ptr<int>(new int(1));
    355    auto y = std::unique_ptr<int>(new int(2));
    356    auto z = std::unique_ptr<int>(new int(3));
    357    std::string s;
    358    f(&s, x);
    359    f(&s, y);
    360    f(&s, z);
    361    EXPECT_EQ("123", s);
    362  }
    363 }
    364 
    365 //
    366 // Tests the interfaces for the 4 public Join function overloads. The semantics
    367 // of the algorithm is covered in the above APIExamples test.
    368 //
    369 TEST(StrJoin, PublicAPIOverloads) {
    370  std::vector<std::string> v = {"a", "b", "c"};
    371 
    372  // Iterators + formatter
    373  EXPECT_EQ("a-b-c",
    374            absl::StrJoin(v.begin(), v.end(), "-", absl::AlphaNumFormatter()));
    375  // Range + formatter
    376  EXPECT_EQ("a-b-c", absl::StrJoin(v, "-", absl::AlphaNumFormatter()));
    377  // Iterators, no formatter
    378  EXPECT_EQ("a-b-c", absl::StrJoin(v.begin(), v.end(), "-"));
    379  // Range, no formatter
    380  EXPECT_EQ("a-b-c", absl::StrJoin(v, "-"));
    381 }
    382 
    383 TEST(StrJoin, Array) {
    384  const absl::string_view a[] = {"a", "b", "c"};
    385  EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
    386 }
    387 
    388 TEST(StrJoin, InitializerList) {
    389  { EXPECT_EQ("a-b-c", absl::StrJoin({"a", "b", "c"}, "-")); }
    390 
    391  {
    392    auto a = {"a", "b", "c"};
    393    EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
    394  }
    395 
    396  {
    397    std::initializer_list<const char*> a = {"a", "b", "c"};
    398    EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
    399  }
    400 
    401  {
    402    std::initializer_list<std::string> a = {"a", "b", "c"};
    403    EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
    404  }
    405 
    406  {
    407    std::initializer_list<absl::string_view> a = {"a", "b", "c"};
    408    EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
    409  }
    410 
    411  {
    412    // Tests initializer_list with a non-default formatter
    413    auto a = {"a", "b", "c"};
    414    TestingParenFormatter f;
    415    EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin(a, "-", f));
    416  }
    417 
    418  {
    419    // initializer_list of ints
    420    EXPECT_EQ("1-2-3", absl::StrJoin({1, 2, 3}, "-"));
    421  }
    422 
    423  {
    424    // Tests initializer_list of ints with a non-default formatter
    425    auto a = {1, 2, 3};
    426    TestingParenFormatter f;
    427    EXPECT_EQ("(1)-(2)-(3)", absl::StrJoin(a, "-", f));
    428  }
    429 }
    430 
    431 TEST(StrJoin, StringViewInitializerList) {
    432  {
    433    // Tests initializer_list of string_views
    434    std::string b = "b";
    435    EXPECT_EQ("a-b-c", absl::StrJoin({"a", b, "c"}, "-"));
    436  }
    437  {
    438    // Tests initializer_list of string_views with a non-default formatter
    439    TestingParenFormatter f;
    440    std::string b = "b";
    441    EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin({"a", b, "c"}, "-", f));
    442  }
    443 
    444  class NoCopy {
    445   public:
    446    explicit NoCopy(absl::string_view view) : view_(view) {}
    447    NoCopy(const NoCopy&) = delete;
    448    operator absl::string_view() { return view_; }  // NOLINT
    449   private:
    450    absl::string_view view_;
    451  };
    452  {
    453    // Tests initializer_list of string_views preferred over initializer_list<T>
    454    // for T that is implicitly convertible to string_view
    455    EXPECT_EQ("a-b-c",
    456              absl::StrJoin({NoCopy("a"), NoCopy("b"), NoCopy("c")}, "-"));
    457  }
    458  {
    459    // Tests initializer_list of string_views preferred over initializer_list<T>
    460    // for T that is implicitly convertible to string_view
    461    TestingParenFormatter f;
    462    EXPECT_EQ("(a)-(b)-(c)",
    463              absl::StrJoin({NoCopy("a"), NoCopy("b"), NoCopy("c")}, "-", f));
    464  }
    465 }
    466 
    467 TEST(StrJoin, Tuple) {
    468  EXPECT_EQ("", absl::StrJoin(std::make_tuple(), "-"));
    469  EXPECT_EQ("hello", absl::StrJoin(std::make_tuple("hello"), "-"));
    470 
    471  int x(10);
    472  std::string y("hello");
    473  double z(3.14);
    474  EXPECT_EQ("10-hello-3.14", absl::StrJoin(std::make_tuple(x, y, z), "-"));
    475 
    476  // Faster! Faster!!
    477  EXPECT_EQ("10-hello-3.14",
    478            absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-"));
    479 
    480  struct TestFormatter {
    481    char buffer[128];
    482    void operator()(std::string* out, int v) {
    483      snprintf(buffer, sizeof(buffer), "%#.8x", v);
    484      out->append(buffer);
    485    }
    486    void operator()(std::string* out, double v) {
    487      snprintf(buffer, sizeof(buffer), "%#.0f", v);
    488      out->append(buffer);
    489    }
    490    void operator()(std::string* out, const std::string& v) {
    491      snprintf(buffer, sizeof(buffer), "%.4s", v.c_str());
    492      out->append(buffer);
    493    }
    494  };
    495  EXPECT_EQ("0x0000000a-hell-3.",
    496            absl::StrJoin(std::make_tuple(x, y, z), "-", TestFormatter()));
    497  EXPECT_EQ(
    498      "0x0000000a-hell-3.",
    499      absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-", TestFormatter()));
    500  EXPECT_EQ("0x0000000a-hell-3.",
    501            absl::StrJoin(std::make_tuple(&x, &y, &z), "-",
    502                          absl::DereferenceFormatter(TestFormatter())));
    503  EXPECT_EQ("0x0000000a-hell-3.",
    504            absl::StrJoin(std::make_tuple(absl::make_unique<int>(x),
    505                                          absl::make_unique<std::string>(y),
    506                                          absl::make_unique<double>(z)),
    507                          "-", absl::DereferenceFormatter(TestFormatter())));
    508  EXPECT_EQ("0x0000000a-hell-3.",
    509            absl::StrJoin(std::make_tuple(absl::make_unique<int>(x), &y, &z),
    510                          "-", absl::DereferenceFormatter(TestFormatter())));
    511 }
    512 
    513 // A minimal value type for `StrJoin` inputs.
    514 // Used to ensure we do not excessively require more a specific type, such as a
    515 // `string_view`.
    516 //
    517 // Anything that can be  `data()` and `size()` is OK.
    518 class TestValue {
    519 public:
    520  TestValue(const char* data, size_t size) : data_(data), size_(size) {}
    521  const char* data() const { return data_; }
    522  size_t size() const { return size_; }
    523 
    524 private:
    525  const char* data_;
    526  size_t size_;
    527 };
    528 
    529 // A minimal C++20 forward iterator, used to test that we do not impose
    530 // excessive requirements on StrJoin inputs.
    531 //
    532 // The 2 main differences between pre-C++20 LegacyForwardIterator and the
    533 // C++20 ForwardIterator are:
    534 // 1. `operator->` is not required in C++20.
    535 // 2. `operator*` result does not need to be an lvalue (a reference).
    536 //
    537 // The `operator->` requirement was removed on page 17 in:
    538 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1037r0.pdf
    539 //
    540 // See the `[iterator.requirements]` section of the C++ standard.
    541 //
    542 // The value type is a template parameter so that we can test the behaviour
    543 // of `StrJoin` specializations, e.g. the NoFormatter specialization for
    544 // `string_view`.
    545 template <typename ValueT>
    546 class TestIterator {
    547 public:
    548  using iterator_category = std::forward_iterator_tag;
    549  using value_type = ValueT;
    550  using pointer = void;
    551  using reference = const value_type&;
    552  using difference_type = int;
    553 
    554  // `data` must outlive the result.
    555  static TestIterator begin(const std::vector<absl::string_view>& data) {
    556    return TestIterator(&data, 0);
    557  }
    558 
    559  static TestIterator end(const std::vector<absl::string_view>& data) {
    560    return TestIterator(nullptr, data.size());
    561  }
    562 
    563  bool operator==(const TestIterator& other) const {
    564    return pos_ == other.pos_;
    565  }
    566  bool operator!=(const TestIterator& other) const {
    567    return pos_ != other.pos_;
    568  }
    569 
    570  // This deliberately returns a `prvalue`.
    571  // The requirement to return a reference was removed in C++20.
    572  value_type operator*() const {
    573    return ValueT((*data_)[pos_].data(), (*data_)[pos_].size());
    574  }
    575 
    576  // `operator->()` is deliberately omitted.
    577  // The requirement to provide it was removed in C++20.
    578 
    579  TestIterator& operator++() {
    580    ++pos_;
    581    return *this;
    582  }
    583 
    584  TestIterator operator++(int) {
    585    TestIterator result = *this;
    586    ++(*this);
    587    return result;
    588  }
    589 
    590  TestIterator& operator--() {
    591    --pos_;
    592    return *this;
    593  }
    594 
    595  TestIterator operator--(int) {
    596    TestIterator result = *this;
    597    --(*this);
    598    return result;
    599  }
    600 
    601 private:
    602  TestIterator(const std::vector<absl::string_view>* data, size_t pos)
    603      : data_(data), pos_(pos) {}
    604 
    605  const std::vector<absl::string_view>* data_;
    606  size_t pos_;
    607 };
    608 
    609 template <typename ValueT>
    610 class TestIteratorRange {
    611 public:
    612  // `data` must be non-null and must outlive the result.
    613  explicit TestIteratorRange(const std::vector<absl::string_view>& data)
    614      : begin_(TestIterator<ValueT>::begin(data)),
    615        end_(TestIterator<ValueT>::end(data)) {}
    616 
    617  const TestIterator<ValueT>& begin() const { return begin_; }
    618  const TestIterator<ValueT>& end() const { return end_; }
    619 
    620 private:
    621  TestIterator<ValueT> begin_;
    622  TestIterator<ValueT> end_;
    623 };
    624 
    625 TEST(StrJoin, TestIteratorRequirementsNoFormatter) {
    626  const std::vector<absl::string_view> a = {"a", "b", "c"};
    627 
    628  // When the value type is string-like (`std::string` or `string_view`),
    629  // the NoFormatter template specialization is used internally.
    630  EXPECT_EQ("a-b-c",
    631            absl::StrJoin(TestIteratorRange<absl::string_view>(a), "-"));
    632 }
    633 
    634 TEST(StrJoin, TestIteratorRequirementsCustomFormatter) {
    635  const std::vector<absl::string_view> a = {"a", "b", "c"};
    636  EXPECT_EQ("a-b-c",
    637            absl::StrJoin(TestIteratorRange<TestValue>(a), "-",
    638                          [](std::string* out, const TestValue& value) {
    639                            absl::StrAppend(
    640                                out,
    641                                absl::string_view(value.data(), value.size()));
    642                          }));
    643 }
    644 
    645 }  // namespace