xref: /aosp_15_r20/external/cronet/base/strings/cstring_view_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/strings/cstring_view.h"
6 
7 #include <concepts>
8 #include <limits>
9 #include <sstream>
10 #include <type_traits>
11 
12 #include "base/containers/span.h"
13 #include "base/debug/alias.h"
14 #include "base/strings/strcat.h"
15 #include "base/test/gtest_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace base {
19 namespace {
20 
21 static_assert(std::is_default_constructible_v<cstring_view>);
22 static_assert(std::is_trivially_copy_constructible_v<cstring_view>);
23 static_assert(std::is_trivially_copy_assignable_v<cstring_view>);
24 static_assert(std::is_trivially_move_constructible_v<cstring_view>);
25 static_assert(std::is_trivially_move_assignable_v<cstring_view>);
26 static_assert(std::is_trivially_destructible_v<cstring_view>);
27 
28 static_assert(std::ranges::contiguous_range<cstring_view>);
29 static_assert(std::ranges::borrowed_range<cstring_view>);
30 
31 // The view is the size of 2 pointers (technically, pointer and address).
32 static_assert(sizeof(cstring_view) == sizeof(uintptr_t) + sizeof(size_t));
33 
34 static_assert(cstring_view::npos == std::string_view::npos);
35 static_assert(u16cstring_view::npos == std::u16string_view::npos);
36 static_assert(u16cstring_view::npos == std::u32string_view::npos);
37 #if BUILDFLAG(IS_WIN)
38 static_assert(wcstring_view::npos == std::wstring_view::npos);
39 #endif
40 
TEST(CStringViewTest,DefaultConstructed)41 TEST(CStringViewTest, DefaultConstructed) {
42   constexpr auto c = cstring_view();
43   static_assert(std::same_as<decltype(c), const cstring_view>);
44   static_assert(c.size() == 0u);
45   static_assert(c[c.size()] == '\0');
46 }
47 
TEST(CStringViewTest,LiteralConstructed)48 TEST(CStringViewTest, LiteralConstructed) {
49   constexpr auto empty = cstring_view("");
50   constexpr auto stuff = cstring_view("stuff");
51   constexpr auto other = cstring_view("other");
52   static_assert(std::same_as<decltype(empty), const cstring_view>);
53   static_assert(std::same_as<decltype(stuff), const cstring_view>);
54   static_assert(std::same_as<decltype(other), const cstring_view>);
55 
56   static_assert(empty.size() == 0u);
57   static_assert(stuff.size() == 5u);
58   static_assert(other.size() == 5u);
59 
60   static_assert(empty[empty.size()] == '\0');
61   static_assert(stuff[stuff.size()] == '\0');
62   static_assert(other[other.size()] == '\0');
63 
64   // Implicit construction.
65   {
66     cstring_view s = "stuff";
67     EXPECT_EQ(s, cstring_view("stuff"));
68   }
69 }
70 
TEST(CStringViewTest,PointerSizeConstructed)71 TEST(CStringViewTest, PointerSizeConstructed) {
72   constexpr const char* c_empty = "";
73   constexpr auto empty = UNSAFE_BUFFERS(cstring_view(c_empty, 0u));
74   static_assert(std::same_as<const cstring_view, decltype(empty)>);
75   EXPECT_EQ(empty.data(), c_empty);
76   EXPECT_EQ(empty.size(), 0u);
77 
78   constexpr const char* c_stuff = "stuff";
79   constexpr auto stuff = UNSAFE_BUFFERS(cstring_view(c_stuff, 5u));
80   static_assert(std::same_as<const cstring_view, decltype(stuff)>);
81   EXPECT_EQ(stuff.data(), c_stuff);
82   EXPECT_EQ(stuff.size(), 5u);
83 }
84 
TEST(CStringViewTest,StringConstructed)85 TEST(CStringViewTest, StringConstructed) {
86   std::string empty;
87   {
88     auto c = cstring_view(empty);
89     EXPECT_EQ(c.size(), 0u);
90   }
91   std::string stuff = "stuff";
92   {
93     auto c = cstring_view(stuff);
94     EXPECT_EQ(c.c_str(), stuff.c_str());
95     EXPECT_EQ(c.size(), 5u);
96   }
97   std::u16string stuff16 = u"stuff";
98   {
99     auto c = u16cstring_view(stuff16);
100     EXPECT_EQ(c.c_str(), stuff16.c_str());
101     EXPECT_EQ(c.size(), 5u);
102   }
103   std::u32string stuff32 = U"stuff";
104   {
105     auto c = u32cstring_view(stuff32);
106     EXPECT_EQ(c.c_str(), stuff32.c_str());
107     EXPECT_EQ(c.size(), 5u);
108   }
109 #if BUILDFLAG(IS_WIN)
110   std::wstring stuffw = L"stuff";
111   {
112     auto c = wcstring_view(stuffw);
113     EXPECT_EQ(c.c_str(), stuffw.c_str());
114     EXPECT_EQ(c.size(), 5u);
115   }
116 #endif
117 
118   // Implicit construction.
119   {
120     auto s = std::string("stuff");
121     cstring_view v = s;
122     EXPECT_EQ(v, cstring_view("stuff"));
123   }
124 }
125 
TEST(CStringViewTest,Equality)126 TEST(CStringViewTest, Equality) {
127   constexpr auto stuff = cstring_view("stuff");
128 
129   static_assert(stuff != cstring_view());
130   static_assert(stuff == cstring_view("stuff"));
131   static_assert(stuff != cstring_view("other"));
132 
133   // Implicit conversion to cstring_view from literal in comparison.
134   static_assert(stuff == "stuff");
135 }
136 
TEST(CStringViewTest,Ordering)137 TEST(CStringViewTest, Ordering) {
138   constexpr auto stuff = cstring_view("stuff");
139 
140   static_assert(stuff <=> stuff == std::weak_ordering::equivalent);
141   static_assert(stuff <=> cstring_view() == std::weak_ordering::greater);
142   static_assert(stuff <=> cstring_view("stuff") ==
143                 std::weak_ordering::equivalent);
144   static_assert(stuff <=> cstring_view("zz") == std::weak_ordering::less);
145 
146   // Implicit conversion to cstring_view from literal in ordering compare.
147   static_assert(stuff <=> "stuff" == std::weak_ordering::equivalent);
148 }
149 
TEST(CStringViewTest,Iterate)150 TEST(CStringViewTest, Iterate) {
151   constexpr auto def = cstring_view();
152   static_assert(def.begin() == def.end());
153   static_assert(def.cbegin() == def.cend());
154 
155   constexpr auto stuff = cstring_view("stuff");
156   static_assert(stuff.begin() != stuff.end());
157   static_assert(stuff.cbegin() != stuff.cend());
158   static_assert(std::same_as<const char&, decltype(*stuff.begin())>);
159 
160   {
161     size_t i = 0u;
162     for (auto& c : stuff) {
163       static_assert(std::same_as<const char&, decltype(c)>);
164       EXPECT_EQ(&c, &stuff[i]);
165       ++i;
166     }
167     EXPECT_EQ(i, 5u);
168   }
169 }
170 
TEST(CStringViewTest,IterateReverse)171 TEST(CStringViewTest, IterateReverse) {
172   constexpr auto def = cstring_view();
173   static_assert(def.rbegin() == def.rend());
174   static_assert(def.rcbegin() == def.rcend());
175 
176   constexpr auto stuff = cstring_view("stuff");
177   static_assert(stuff.rbegin() != stuff.rend());
178   static_assert(stuff.rcbegin() != stuff.rcend());
179   static_assert(std::same_as<const char&, decltype(*stuff.rbegin())>);
180 
181   {
182     size_t i = 0u;
183     for (auto it = stuff.rbegin(); it != stuff.rend(); ++it) {
184       static_assert(std::same_as<const char&, decltype(*it)>);
185       EXPECT_EQ(&*it, &stuff[4u - i]);
186       ++i;
187     }
188     EXPECT_EQ(i, 5u);
189   }
190 }
191 
TEST(CStringViewDeathTest,IterateBoundsChecked)192 TEST(CStringViewDeathTest, IterateBoundsChecked) {
193   auto use = [](auto x) { base::debug::Alias(&x); };
194 
195   constexpr auto stuff = cstring_view("stuff");
196 
197   // The NUL terminator is out of bounds for iterating (checked by indexing into
198   // the iterator) since it's not included in the range that the iterator walks
199   // (but is in bounds for indexing on the view).
200   BASE_EXPECT_DEATH(use(*stuff.end()), "");       // Can't deref end.
201   BASE_EXPECT_DEATH(use(stuff.begin()[5]), "");   // Can't index end.
202   BASE_EXPECT_DEATH(use(stuff.begin() + 6), "");  // Can't move past end.
203   BASE_EXPECT_DEATH(use(stuff.begin() - 1), "");  // Can't move past begin.
204 
205   BASE_EXPECT_DEATH(use(*stuff.rend()), "");
206   BASE_EXPECT_DEATH(use(stuff.rbegin()[5]), "");
207   BASE_EXPECT_DEATH(use(stuff.rbegin() + 6), "");
208   BASE_EXPECT_DEATH(use(stuff.rbegin() - 1), "");
209 }
210 
TEST(CStringViewTest,Index)211 TEST(CStringViewTest, Index) {
212   constexpr auto empty = cstring_view();
213   static_assert(empty[0u] == '\0');
214 
215   static_assert(empty.at(0u) == '\0');
216 
217   constexpr auto stuff = cstring_view("stuff");
218   static_assert(stuff[0u] == 's');
219   static_assert(&stuff[0u] == stuff.data());
220   static_assert(stuff[5u] == '\0');
221   static_assert(&stuff[5u] == UNSAFE_BUFFERS(stuff.data() + 5u));
222 
223   static_assert(stuff.at(0u) == 's');
224   static_assert(&stuff.at(0u) == stuff.data());
225   static_assert(stuff.at(5u) == '\0');
226   static_assert(&stuff.at(5u) == UNSAFE_BUFFERS(stuff.data() + 5u));
227 }
228 
TEST(CStringViewDeathTest,IndexChecked)229 TEST(CStringViewDeathTest, IndexChecked) {
230   auto use = [](auto x) { base::debug::Alias(&x); };
231 
232   constexpr auto empty = cstring_view();
233   BASE_EXPECT_DEATH(use(empty[1u]), "");
234   BASE_EXPECT_DEATH(use(empty[std::numeric_limits<size_t>::max()]), "");
235 
236   BASE_EXPECT_DEATH(use(empty.at(1u)), "");
237   BASE_EXPECT_DEATH(use(empty.at(std::numeric_limits<size_t>::max())), "");
238 
239   constexpr auto stuff = cstring_view("stuff");
240   BASE_EXPECT_DEATH(use(stuff[6u]), "");
241   BASE_EXPECT_DEATH(use(stuff[std::numeric_limits<size_t>::max()]), "");
242 
243   BASE_EXPECT_DEATH(use(stuff.at(6u)), "");
244   BASE_EXPECT_DEATH(use(stuff.at(std::numeric_limits<size_t>::max())), "");
245 }
246 
TEST(CStringViewTest,FrontBack)247 TEST(CStringViewTest, FrontBack) {
248   constexpr auto stuff = cstring_view("stuff");
249   static_assert(stuff.front() == 's');
250   static_assert(&stuff.front() == stuff.data());
251   static_assert(stuff.back() == 'f');
252   static_assert(&stuff.back() == UNSAFE_BUFFERS(stuff.data() + 4u));
253 
254   constexpr auto one = cstring_view("1");
255   static_assert(one.front() == '1');
256   static_assert(&one.front() == one.data());
257   static_assert(one.back() == '1');
258   static_assert(&one.back() == one.data());
259 }
260 
TEST(CStringViewDeathTest,FrontBackChecked)261 TEST(CStringViewDeathTest, FrontBackChecked) {
262   auto use = [](auto x) { base::debug::Alias(&x); };
263 
264   constexpr auto empty = cstring_view();
265   BASE_EXPECT_DEATH(use(empty.front()), "");
266   BASE_EXPECT_DEATH(use(empty.back()), "");
267 }
268 
TEST(CStringViewTest,Size)269 TEST(CStringViewTest, Size) {
270   constexpr auto empty = cstring_view();
271   static_assert(empty.size() == 0u);
272   static_assert(empty.size_bytes() == 0u);
273   constexpr auto stuff = cstring_view("stuff");
274   static_assert(stuff.size() == 5u);
275   static_assert(stuff.size_bytes() == 5u);
276 
277   constexpr auto empty16 = u16cstring_view();
278   static_assert(empty16.size() == 0u);
279   static_assert(empty16.size_bytes() == 0u);
280   constexpr auto stuff16 = u16cstring_view(u"stuff");
281   static_assert(stuff16.size() == 5u);
282   static_assert(stuff16.size_bytes() == 10u);
283 
284   constexpr auto empty32 = u32cstring_view();
285   static_assert(empty32.size() == 0u);
286   static_assert(empty32.size_bytes() == 0u);
287   constexpr auto stuff32 = u32cstring_view(U"stuff");
288   static_assert(stuff32.size() == 5u);
289   static_assert(stuff32.size_bytes() == 20u);
290 
291 #if BUILDFLAG(IS_WIN)
292   constexpr auto emptyw = wcstring_view();
293   static_assert(emptyw.size() == 0u);
294   static_assert(emptyw.size_bytes() == 0u);
295   constexpr auto stuffw = wcstring_view(L"stuff");
296   static_assert(stuffw.size() == 5u);
297   static_assert(stuffw.size_bytes() == 10u);
298 #endif
299 }
300 
TEST(CStringViewTest,Empty)301 TEST(CStringViewTest, Empty) {
302   constexpr auto empty = cstring_view();
303   static_assert(empty.empty());
304   constexpr auto one = cstring_view("1");
305   static_assert(!one.empty());
306   constexpr auto stuff = cstring_view("stuff");
307   static_assert(!stuff.empty());
308 
309   constexpr auto empty16 = u16cstring_view();
310   static_assert(empty16.empty());
311   constexpr auto stuff16 = u16cstring_view(u"stuff");
312   static_assert(!stuff16.empty());
313 
314   constexpr auto empty32 = u32cstring_view();
315   static_assert(empty32.empty());
316   constexpr auto stuff32 = u32cstring_view(U"stuff");
317   static_assert(!stuff32.empty());
318 
319 #if BUILDFLAG(IS_WIN)
320   constexpr auto emptyw = wcstring_view();
321   static_assert(emptyw.empty());
322   constexpr auto stuffw = wcstring_view(L"stuff");
323   static_assert(!stuffw.empty());
324 #endif
325 }
326 
TEST(CStringViewTest,MaxSize)327 TEST(CStringViewTest, MaxSize) {
328   static_assert(cstring_view().max_size() ==
329                 std::numeric_limits<size_t>::max());
330   static_assert(u16cstring_view().max_size() ==
331                 std::numeric_limits<size_t>::max() / 2u);
332   static_assert(u32cstring_view().max_size() ==
333                 std::numeric_limits<size_t>::max() / 4u);
334 #if BUILDFLAG(IS_WIN)
335   static_assert(wcstring_view().max_size() ==
336                 std::numeric_limits<size_t>::max() / 2u);
337 #endif
338 }
339 
TEST(CStringViewTest,ToSpan)340 TEST(CStringViewTest, ToSpan) {
341   constexpr auto empty = cstring_view();
342   {
343     auto s = base::span(empty);
344     static_assert(std::same_as<base::span<const char>, decltype(s)>);
345     EXPECT_EQ(s.data(), empty.data());
346     EXPECT_EQ(s.size(), 0u);
347     EXPECT_EQ(s.size_bytes(), 0u);
348   }
349   constexpr auto stuff = cstring_view("stuff");
350   {
351     auto s = base::span(stuff);
352     static_assert(std::same_as<base::span<const char>, decltype(s)>);
353     EXPECT_EQ(s.data(), stuff.data());
354     EXPECT_EQ(s.size(), 5u);
355     EXPECT_EQ(s.size_bytes(), 5u);
356   }
357   constexpr auto stuff16 = u16cstring_view(u"stuff");
358   {
359     auto s = base::span(stuff16);
360     static_assert(std::same_as<base::span<const char16_t>, decltype(s)>);
361     EXPECT_EQ(s.data(), stuff16.data());
362     EXPECT_EQ(s.size(), 5u);
363     EXPECT_EQ(s.size_bytes(), 10u);
364   }
365   constexpr auto stuff32 = u32cstring_view(U"stuff");
366   {
367     auto s = base::span(stuff32);
368     static_assert(std::same_as<base::span<const char32_t>, decltype(s)>);
369     EXPECT_EQ(s.data(), stuff32.data());
370     EXPECT_EQ(s.size(), 5u);
371     EXPECT_EQ(s.size_bytes(), 20u);
372   }
373 }
374 
TEST(CStringViewTest,Cstr)375 TEST(CStringViewTest, Cstr) {
376   constexpr auto empty = cstring_view();
377   constexpr auto stuff = cstring_view("stuff");
378 
379   static_assert(*stuff.c_str() == 's');
380 
381   EXPECT_STREQ(empty.c_str(), "");
382   EXPECT_STREQ(stuff.c_str(), "stuff");
383 }
384 
TEST(CStringViewTest,CopyConstuct)385 TEST(CStringViewTest, CopyConstuct) {
386   static_assert(std::is_trivially_copy_constructible_v<cstring_view>);
387 
388   auto stuff = cstring_view("stuff");
389   auto other = stuff;
390   EXPECT_EQ(other.data(), stuff.data());
391   EXPECT_EQ(other.size(), stuff.size());
392 }
393 
TEST(CStringViewTest,CopyAssign)394 TEST(CStringViewTest, CopyAssign) {
395   static_assert(std::is_trivially_copy_assignable_v<cstring_view>);
396 
397   auto empty = cstring_view();
398   auto stuff = cstring_view("stuff");
399   empty = stuff;
400   EXPECT_EQ(empty.data(), stuff.data());
401   EXPECT_EQ(empty.size(), stuff.size());
402 }
403 
TEST(CStringViewTest,RemovePrefix)404 TEST(CStringViewTest, RemovePrefix) {
405   auto empty = cstring_view();
406   auto mod_empty = empty;
407   mod_empty.remove_prefix(0u);
408   EXPECT_EQ(mod_empty.data(), &empty[0u]);
409   EXPECT_EQ(mod_empty.size(), 0u);
410 
411   auto stuff = cstring_view("stuff");
412   auto mod_stuff = stuff;
413   mod_stuff.remove_prefix(0u);
414   EXPECT_EQ(mod_stuff.data(), &stuff[0u]);
415   EXPECT_EQ(mod_stuff.size(), 5u);
416   mod_stuff.remove_prefix(2u);
417   EXPECT_EQ(mod_stuff.data(), &stuff[2u]);
418   EXPECT_EQ(mod_stuff.size(), 3u);
419   mod_stuff.remove_prefix(1u);
420   EXPECT_EQ(mod_stuff.data(), &stuff[3u]);
421   EXPECT_EQ(mod_stuff.size(), 2u);
422   mod_stuff.remove_prefix(2u);
423   EXPECT_EQ(mod_stuff.data(), &stuff[5u]);
424   EXPECT_EQ(mod_stuff.size(), 0u);
425 
426   static_assert([] {
427     auto stuff = cstring_view("stuff");
428     stuff.remove_prefix(2u);
429     return stuff;
430   }() == "uff");
431 
432   auto stuff16 = u16cstring_view(u"stuff");
433   auto mod_stuff16 = stuff16;
434   mod_stuff16.remove_prefix(2u);
435   EXPECT_EQ(mod_stuff16.data(), &stuff16[2u]);
436   EXPECT_EQ(mod_stuff16.size(), 3u);
437 
438   auto stuff32 = u32cstring_view(U"stuff");
439   auto mod_stuff32 = stuff32;
440   mod_stuff32.remove_prefix(2u);
441   EXPECT_EQ(mod_stuff32.data(), &stuff32[2u]);
442   EXPECT_EQ(mod_stuff32.size(), 3u);
443 
444 #if BUILDFLAG(IS_WIN)
445   auto stuffw = wcstring_view(L"stuff");
446   auto mod_stuffw = stuffw;
447   mod_stuffw.remove_prefix(2u);
448   EXPECT_EQ(mod_stuffw.data(), &stuffw[2u]);
449   EXPECT_EQ(mod_stuffw.size(), 3u);
450 #endif
451 }
452 
TEST(CStringViewDeathTest,RemovePrefixChecked)453 TEST(CStringViewDeathTest, RemovePrefixChecked) {
454   auto empty = cstring_view();
455   BASE_EXPECT_DEATH(empty.remove_prefix(1u), "");
456 
457   auto stuff = cstring_view("stuff");
458   BASE_EXPECT_DEATH(stuff.remove_prefix(6u), "");
459   stuff.remove_prefix(4u);
460   BASE_EXPECT_DEATH(stuff.remove_prefix(2u), "");
461 }
462 
TEST(CStringViewTest,Swap)463 TEST(CStringViewTest, Swap) {
464   auto empty = cstring_view();
465   auto stuff = cstring_view("stuff");
466   empty.swap(stuff);
467   EXPECT_EQ(stuff, cstring_view(""));
468   EXPECT_EQ(empty, cstring_view("stuff"));
469 
470   static_assert([] {
471     auto abc = cstring_view("abc");
472     auto ef = cstring_view("ef");
473     abc.swap(ef);
474     return ef;
475   }() == "abc");
476 
477   auto one16 = u16cstring_view(u"one");
478   auto two16 = u16cstring_view(u"twotwo");
479   one16.swap(two16);
480   EXPECT_EQ(one16, u16cstring_view(u"twotwo"));
481   EXPECT_EQ(two16, u16cstring_view(u"one"));
482 }
483 
TEST(CStringViewTest,Substr)484 TEST(CStringViewTest, Substr) {
485   auto substr = cstring_view("hello").substr(1u);
486   static_assert(std::same_as<std::string_view, decltype(substr)>);
487 
488   static_assert(cstring_view("").substr(0u) == "");
489   static_assert(cstring_view("").substr(0u, 0u) == "");
490   static_assert(cstring_view("stuff").substr(0u) == "stuff");
491   static_assert(cstring_view("stuff").substr(0u, 2u) == "st");
492   static_assert(cstring_view("stuff").substr(2u) == "uff");
493   static_assert(cstring_view("stuff").substr(2u, 3u) == "uff");
494   static_assert(cstring_view("stuff").substr(2u, 1u) == "u");
495   static_assert(cstring_view("stuff").substr(2u, 0u) == "");
496 
497   // `count` going off the end is clamped. Same as for string_view with
498   // hardening.
499   static_assert(cstring_view("stuff").substr(2u, 4u) == "uff");
500   static_assert(std::string_view("stuff").substr(2u, 4u) == "uff");
501 }
502 
TEST(CStringViewDeathTest,SubstrBoundsChecked)503 TEST(CStringViewDeathTest, SubstrBoundsChecked) {
504   auto use = [](auto x) { base::debug::Alias(&x); };
505 
506   auto stuff = cstring_view("stuff");
507 
508   // `pos` going off the end is CHECKed. Same as for string_view with hardening.
509   BASE_EXPECT_DEATH(use(stuff.substr(6u, 0u)), "");
510   BASE_EXPECT_DEATH(use(std::string_view("stuff").substr(6u, 0u)), "");
511   BASE_EXPECT_DEATH(use(stuff.substr(6u, 1u)), "");
512   BASE_EXPECT_DEATH(use(std::string_view("stuff").substr(6u, 1u)), "");
513 }
514 
TEST(CStringViewTest,StartsWith)515 TEST(CStringViewTest, StartsWith) {
516   // Comparison with `const char*`.
517   static_assert(!cstring_view("").starts_with("hello"));
518   static_assert(cstring_view("").starts_with(""));
519   static_assert(cstring_view("hello").starts_with("hello"));
520   static_assert(cstring_view("hello").starts_with(""));
521   static_assert(cstring_view("hello").starts_with("he"));
522   static_assert(!cstring_view("hello").starts_with("ello"));
523   constexpr const char* query = "ello";
524   static_assert(!cstring_view("hello").starts_with(query));
525 
526   static_assert(u16cstring_view(u"hello").starts_with(u"he"));
527   static_assert(u32cstring_view(U"hello").starts_with(U"he"));
528 #if BUILDFLAG(IS_WIN)
529   static_assert(wcstring_view(L"hello").starts_with(L"he"));
530 #endif
531 
532   // Comparison with `string/string_view/cstring_view`.
533   static_assert(cstring_view("hello").starts_with(std::string("he")));
534   static_assert(!cstring_view("hello").starts_with(std::string("el")));
535   static_assert(cstring_view("hello").starts_with(std::string_view("he")));
536   static_assert(!cstring_view("hello").starts_with(std::string_view("el")));
537   static_assert(cstring_view("hello").starts_with(cstring_view("he")));
538   static_assert(!cstring_view("hello").starts_with(cstring_view("el")));
539 
540   static_assert(!cstring_view("hello").starts_with(std::string("hellos")));
541   static_assert(!cstring_view("hello").starts_with(std::string_view("hellos")));
542   static_assert(!cstring_view("hello").starts_with(cstring_view("hellos")));
543 
544   static_assert(u16cstring_view(u"hello").starts_with(std::u16string(u"he")));
545   static_assert(u32cstring_view(U"hello").starts_with(std::u32string(U"he")));
546 #if BUILDFLAG(IS_WIN)
547   static_assert(wcstring_view(L"hello").starts_with(std::wstring(L"he")));
548 #endif
549 
550   // Comparison with a character.
551   static_assert(!cstring_view("").starts_with('h'));
552   static_assert(cstring_view("hello").starts_with('h'));
553   static_assert(!cstring_view("hello").starts_with('e'));
554 
555   static_assert(u16cstring_view(u"hello").starts_with(u'h'));
556   static_assert(u32cstring_view(U"hello").starts_with(U'h'));
557 #if BUILDFLAG(IS_WIN)
558   static_assert(wcstring_view(L"hello").starts_with(L'h'));
559 #endif
560 }
561 
TEST(CStringViewTest,EndsWith)562 TEST(CStringViewTest, EndsWith) {
563   // Comparison with `const char*`.
564   static_assert(!cstring_view("").ends_with("hello"));
565   static_assert(cstring_view("").ends_with(""));
566   static_assert(cstring_view("hello").ends_with("hello"));
567   static_assert(cstring_view("hello").ends_with(""));
568   static_assert(cstring_view("hello").ends_with("lo"));
569   static_assert(!cstring_view("hello").ends_with("hel"));
570   constexpr const char* query = "hel";
571   static_assert(!cstring_view("hello").ends_with(query));
572 
573   static_assert(u16cstring_view(u"hello").ends_with(u"lo"));
574   static_assert(u32cstring_view(U"hello").ends_with(U"lo"));
575 #if BUILDFLAG(IS_WIN)
576   static_assert(wcstring_view(L"hello").ends_with(L"lo"));
577 #endif
578 
579   // Comparison with `string/string_view/cstring_view`.
580   static_assert(cstring_view("hello").ends_with(std::string("lo")));
581   static_assert(!cstring_view("hello").ends_with(std::string("ell")));
582   static_assert(cstring_view("hello").ends_with(std::string_view("lo")));
583   static_assert(!cstring_view("hello").ends_with(std::string_view("ell")));
584   static_assert(cstring_view("hello").ends_with(cstring_view("lo")));
585   static_assert(!cstring_view("hello").ends_with(cstring_view("ell")));
586 
587   static_assert(!cstring_view("hello").ends_with(std::string("shello")));
588   static_assert(!cstring_view("hello").ends_with(std::string_view("shello")));
589   static_assert(!cstring_view("hello").ends_with(cstring_view("shello")));
590 
591   static_assert(u16cstring_view(u"hello").ends_with(std::u16string(u"lo")));
592   static_assert(u32cstring_view(U"hello").ends_with(std::u32string(U"lo")));
593 #if BUILDFLAG(IS_WIN)
594   static_assert(wcstring_view(L"hello").ends_with(std::wstring(L"lo")));
595 #endif
596 
597   // Comparison with a character.
598   static_assert(!cstring_view("").ends_with('h'));
599   static_assert(cstring_view("hello").ends_with('o'));
600   static_assert(!cstring_view("hello").ends_with('l'));
601 
602   static_assert(u16cstring_view(u"hello").ends_with(u'o'));
603   static_assert(u32cstring_view(U"hello").ends_with(U'o'));
604 #if BUILDFLAG(IS_WIN)
605   static_assert(wcstring_view(L"hello").ends_with(L'o'));
606 #endif
607 }
608 
TEST(CStringViewTest,Find)609 TEST(CStringViewTest, Find) {
610   // OOB `pos` will return npos. The NUL is never searched.
611   static_assert(cstring_view("hello").find('h', 1000u) == cstring_view::npos);
612   static_assert(cstring_view("hello").find('\0', 5u) == cstring_view::npos);
613 
614   // Searching for a Char.
615   static_assert(cstring_view("hello").find('e') == 1u);
616   static_assert(cstring_view("hello").find('z') == cstring_view::npos);
617   static_assert(cstring_view("hello").find('l') == 2u);
618   static_assert(cstring_view("hello").find('l', 3u) == 3u);
619 
620   static_assert(u16cstring_view(u"hello").find(u'e') == 1u);
621   static_assert(u16cstring_view(u"hello").find(u'z') == cstring_view::npos);
622   static_assert(u16cstring_view(u"hello").find(u'l') == 2u);
623   static_assert(u16cstring_view(u"hello").find(u'l', 3u) == 3u);
624 
625   static_assert(u32cstring_view(U"hello").find(U'e') == 1u);
626   static_assert(u32cstring_view(U"hello").find(U'z') == cstring_view::npos);
627   static_assert(u32cstring_view(U"hello").find(U'l') == 2u);
628   static_assert(u32cstring_view(U"hello").find(U'l', 3u) == 3u);
629 
630 #if BUILDFLAG(IS_WIN)
631   static_assert(wcstring_view(L"hello").find(L'e') == 1u);
632   static_assert(wcstring_view(L"hello").find(L'z') == cstring_view::npos);
633   static_assert(wcstring_view(L"hello").find(L'l') == 2u);
634   static_assert(wcstring_view(L"hello").find(L'l', 3u) == 3u);
635 #endif
636 
637   // Searching for a string.
638   static_assert(cstring_view("hello hello").find("lo") == 3u);
639   static_assert(cstring_view("hello hello").find("lol") == cstring_view::npos);
640   static_assert(u16cstring_view(u"hello hello").find(u"lo") == 3u);
641   static_assert(u16cstring_view(u"hello hello").find(u"lol") ==
642                 cstring_view::npos);
643   static_assert(u32cstring_view(U"hello hello").find(U"lo") == 3u);
644   static_assert(u32cstring_view(U"hello hello").find(U"lol") ==
645                 cstring_view::npos);
646 #if BUILDFLAG(IS_WIN)
647   static_assert(wcstring_view(L"hello hello").find(L"lo") == 3u);
648   static_assert(wcstring_view(L"hello hello").find(L"lol") ==
649                 cstring_view::npos);
650 #endif
651 }
652 
TEST(CStringViewTest,Rfind)653 TEST(CStringViewTest, Rfind) {
654   // OOB `pos` will clamp to the end of the view. The NUL is never searched.
655   static_assert(cstring_view("hello").rfind('h', 0u) == 0u);
656   static_assert(cstring_view("hello").rfind('h', 1000u) == 0u);
657   static_assert(cstring_view("hello").rfind('\0', 5u) == cstring_view::npos);
658 
659   // Searching for a Char.
660   static_assert(cstring_view("hello").rfind('e') == 1u);
661   static_assert(cstring_view("hello").rfind('z') == cstring_view::npos);
662   static_assert(cstring_view("hello").rfind('l') == 3u);
663   static_assert(cstring_view("hello").rfind('l', 2u) == 2u);
664 
665   static_assert(u16cstring_view(u"hello").rfind(u'e') == 1u);
666   static_assert(u16cstring_view(u"hello").rfind(u'z') == cstring_view::npos);
667   static_assert(u16cstring_view(u"hello").rfind(u'l') == 3u);
668   static_assert(u16cstring_view(u"hello").rfind(u'l', 2u) == 2u);
669 
670   static_assert(u32cstring_view(U"hello").rfind(U'e') == 1u);
671   static_assert(u32cstring_view(U"hello").rfind(U'z') == cstring_view::npos);
672   static_assert(u32cstring_view(U"hello").rfind(U'l') == 3u);
673   static_assert(u32cstring_view(U"hello").rfind(U'l', 2u) == 2u);
674 
675 #if BUILDFLAG(IS_WIN)
676   static_assert(wcstring_view(L"hello").rfind(L'e') == 1u);
677   static_assert(wcstring_view(L"hello").rfind(L'z') == cstring_view::npos);
678   static_assert(wcstring_view(L"hello").rfind(L'l') == 3u);
679   static_assert(wcstring_view(L"hello").rfind(L'l', 2u) == 2u);
680 #endif
681 
682   // Searching for a string.
683   static_assert(cstring_view("hello hello").rfind("lo") == 9u);
684   static_assert(cstring_view("hello hello").rfind("lol") == cstring_view::npos);
685   static_assert(u16cstring_view(u"hello hello").rfind(u"lo") == 9u);
686   static_assert(u16cstring_view(u"hello hello").rfind(u"lol") ==
687                 cstring_view::npos);
688   static_assert(u32cstring_view(U"hello hello").rfind(U"lo") == 9u);
689   static_assert(u32cstring_view(U"hello hello").rfind(U"lol") ==
690                 cstring_view::npos);
691 #if BUILDFLAG(IS_WIN)
692   static_assert(wcstring_view(L"hello hello").rfind(L"lo") == 9u);
693   static_assert(wcstring_view(L"hello hello").rfind(L"lol") ==
694                 cstring_view::npos);
695 #endif
696 }
697 
TEST(CStringViewTest,FindFirstOf)698 TEST(CStringViewTest, FindFirstOf) {
699   // OOB `pos` will return npos. The NUL is never searched.
700   static_assert(cstring_view("hello").find_first_of('h', 1000u) ==
701                 cstring_view::npos);
702   static_assert(cstring_view("hello").find_first_of('\0', 5u) ==
703                 cstring_view::npos);
704 
705   // Searching for a Char.
706   static_assert(cstring_view("hello").find_first_of('e') == 1u);
707   static_assert(cstring_view("hello").find_first_of('z') == cstring_view::npos);
708   static_assert(cstring_view("hello").find_first_of('l') == 2u);
709   static_assert(cstring_view("hello").find_first_of('l', 3u) == 3u);
710 
711   static_assert(u16cstring_view(u"hello").find_first_of(u'e') == 1u);
712   static_assert(u16cstring_view(u"hello").find_first_of(u'z') ==
713                 cstring_view::npos);
714   static_assert(u16cstring_view(u"hello").find_first_of(u'l') == 2u);
715   static_assert(u16cstring_view(u"hello").find_first_of(u'l', 3u) == 3u);
716 
717   static_assert(u32cstring_view(U"hello").find_first_of(U'e') == 1u);
718   static_assert(u32cstring_view(U"hello").find_first_of(U'z') ==
719                 cstring_view::npos);
720   static_assert(u32cstring_view(U"hello").find_first_of(U'l') == 2u);
721   static_assert(u32cstring_view(U"hello").find_first_of(U'l', 3u) == 3u);
722 
723 #if BUILDFLAG(IS_WIN)
724   static_assert(wcstring_view(L"hello").find_first_of(L'e') == 1u);
725   static_assert(wcstring_view(L"hello").find_first_of(L'z') ==
726                 cstring_view::npos);
727   static_assert(wcstring_view(L"hello").find_first_of(L'l') == 2u);
728   static_assert(wcstring_view(L"hello").find_first_of(L'l', 3u) == 3u);
729 #endif
730 
731   // Searching for a string.
732   static_assert(cstring_view("hello hello").find_first_of("ol") == 2u);
733   static_assert(cstring_view("hello hello").find_first_of("zz") ==
734                 cstring_view::npos);
735   static_assert(u16cstring_view(u"hello hello").find_first_of(u"ol") == 2u);
736   static_assert(u16cstring_view(u"hello hello").find_first_of(u"zz") ==
737                 cstring_view::npos);
738   static_assert(u32cstring_view(U"hello hello").find_first_of(U"ol") == 2u);
739   static_assert(u32cstring_view(U"hello hello").find_first_of(U"zz") ==
740                 cstring_view::npos);
741 #if BUILDFLAG(IS_WIN)
742   static_assert(wcstring_view(L"hello hello").find_first_of(L"ol") == 2u);
743   static_assert(wcstring_view(L"hello hello").find_first_of(L"zz") ==
744                 cstring_view::npos);
745 #endif
746 }
747 
TEST(CStringViewTest,FindLastOf)748 TEST(CStringViewTest, FindLastOf) {
749   // OOB `pos` will clamp to the end of the view. The NUL is never searched.
750   static_assert(cstring_view("hello").find_last_of('h', 0u) == 0u);
751   static_assert(cstring_view("hello").find_last_of('h', 1000u) == 0u);
752   static_assert(cstring_view("hello").find_last_of('\0', 5u) ==
753                 cstring_view::npos);
754 
755   // Searching for a Char.
756   static_assert(cstring_view("hello").find_last_of('e') == 1u);
757   static_assert(cstring_view("hello").find_last_of('z') == cstring_view::npos);
758   static_assert(cstring_view("hello").find_last_of('l') == 3u);
759   static_assert(cstring_view("hello").find_last_of('l', 2u) == 2u);
760 
761   static_assert(u16cstring_view(u"hello").find_last_of(u'e') == 1u);
762   static_assert(u16cstring_view(u"hello").find_last_of(u'z') ==
763                 cstring_view::npos);
764   static_assert(u16cstring_view(u"hello").find_last_of(u'l') == 3u);
765   static_assert(u16cstring_view(u"hello").find_last_of(u'l', 2u) == 2u);
766 
767   static_assert(u32cstring_view(U"hello").find_last_of(U'e') == 1u);
768   static_assert(u32cstring_view(U"hello").find_last_of(U'z') ==
769                 cstring_view::npos);
770   static_assert(u32cstring_view(U"hello").find_last_of(U'l') == 3u);
771   static_assert(u32cstring_view(U"hello").find_last_of(U'l', 2u) == 2u);
772 
773 #if BUILDFLAG(IS_WIN)
774   static_assert(wcstring_view(L"hello").find_last_of(L'e') == 1u);
775   static_assert(wcstring_view(L"hello").find_last_of(L'z') ==
776                 cstring_view::npos);
777   static_assert(wcstring_view(L"hello").find_last_of(L'l') == 3u);
778   static_assert(wcstring_view(L"hello").find_last_of(L'l', 2u) == 2u);
779 #endif
780 
781   // Searching for a string.
782   static_assert(cstring_view("hello hello").find_last_of("lo") == 10u);
783   static_assert(cstring_view("hello hello").find_last_of("zz") ==
784                 cstring_view::npos);
785   static_assert(u16cstring_view(u"hello hello").find_last_of(u"lo") == 10u);
786   static_assert(u16cstring_view(u"hello hello").find_last_of(u"zz") ==
787                 cstring_view::npos);
788   static_assert(u32cstring_view(U"hello hello").find_last_of(U"lo") == 10u);
789   static_assert(u32cstring_view(U"hello hello").find_last_of(U"zz") ==
790                 cstring_view::npos);
791 #if BUILDFLAG(IS_WIN)
792   static_assert(wcstring_view(L"hello hello").find_last_of(L"lo") == 10u);
793   static_assert(wcstring_view(L"hello hello").find_last_of(L"zz") ==
794                 cstring_view::npos);
795 #endif
796 }
797 
TEST(CStringViewTest,FindFirstNotOf)798 TEST(CStringViewTest, FindFirstNotOf) {
799   // OOB `pos` will return npos. The NUL is never searched.
800   static_assert(cstring_view("hello").find_first_not_of('a', 1000u) ==
801                 cstring_view::npos);
802   static_assert(cstring_view("hello").find_first_not_of('a', 5u) ==
803                 cstring_view::npos);
804 
805   // Searching for a Char.
806   static_assert(cstring_view("hello").find_first_not_of('h') == 1u);
807   static_assert(cstring_view("hello").find_first_not_of('e') == 0u);
808   static_assert(cstring_view("hello").find_first_not_of("eloh") ==
809                 cstring_view::npos);
810 
811   static_assert(u16cstring_view(u"hello").find_first_not_of(u'h') == 1u);
812   static_assert(u16cstring_view(u"hello").find_first_not_of(u'e') == 0u);
813   static_assert(u16cstring_view(u"hello").find_first_not_of(u"eloh") ==
814                 cstring_view::npos);
815 
816   static_assert(u32cstring_view(U"hello").find_first_not_of(U'h') == 1u);
817   static_assert(u32cstring_view(U"hello").find_first_not_of(U'e') == 0u);
818   static_assert(u32cstring_view(U"hello").find_first_not_of(U"eloh") ==
819                 cstring_view::npos);
820 
821 #if BUILDFLAG(IS_WIN)
822   static_assert(wcstring_view(L"hello").find_first_not_of(L'h') == 1u);
823   static_assert(wcstring_view(L"hello").find_first_not_of(L'e') == 0u);
824   static_assert(wcstring_view(L"hello").find_first_not_of(L"eloh") ==
825                 cstring_view::npos);
826 #endif
827 
828   // Searching for a string.
829   static_assert(cstring_view("hello hello").find_first_not_of("eh") == 2u);
830   static_assert(cstring_view("hello hello").find_first_not_of("hello ") ==
831                 cstring_view::npos);
832   static_assert(u16cstring_view(u"hello hello").find_first_not_of(u"eh") == 2u);
833   static_assert(u16cstring_view(u"hello hello").find_first_not_of(u"hello ") ==
834                 cstring_view::npos);
835   static_assert(u32cstring_view(U"hello hello").find_first_not_of(U"eh") == 2u);
836   static_assert(u32cstring_view(U"hello hello").find_first_not_of(U"hello ") ==
837                 cstring_view::npos);
838 #if BUILDFLAG(IS_WIN)
839   static_assert(wcstring_view(L"hello hello").find_first_not_of(L"eh") == 2u);
840   static_assert(wcstring_view(L"hello hello").find_first_not_of(L"hello ") ==
841                 cstring_view::npos);
842 #endif
843 }
844 
TEST(CStringViewTest,FindLastNotOf)845 TEST(CStringViewTest, FindLastNotOf) {
846   // OOB `pos` will clamp to the end of the view. The NUL is never searched.
847   static_assert(cstring_view("hello").find_last_not_of('a', 1000u) == 4u);
848   static_assert(cstring_view("hello").find_last_not_of('a', 5u) == 4u);
849 
850   // Searching for a Char.
851   static_assert(cstring_view("hello").find_last_not_of('l') == 4u);
852   static_assert(cstring_view("hello").find_last_not_of('o') == 3u);
853   static_assert(cstring_view("hello").find_last_not_of("eloh") ==
854                 cstring_view::npos);
855 
856   static_assert(u16cstring_view(u"hello").find_last_not_of(u'l') == 4u);
857   static_assert(u16cstring_view(u"hello").find_last_not_of(u'o') == 3u);
858   static_assert(u16cstring_view(u"hello").find_last_not_of(u"eloh") ==
859                 cstring_view::npos);
860 
861   static_assert(u32cstring_view(U"hello").find_last_not_of(U'l') == 4u);
862   static_assert(u32cstring_view(U"hello").find_last_not_of(U'o') == 3u);
863   static_assert(u32cstring_view(U"hello").find_last_not_of(U"eloh") ==
864                 cstring_view::npos);
865 
866 #if BUILDFLAG(IS_WIN)
867   static_assert(wcstring_view(L"hello").find_last_not_of(L'l') == 4u);
868   static_assert(wcstring_view(L"hello").find_last_not_of(L'o') == 3u);
869   static_assert(wcstring_view(L"hello").find_last_not_of(L"eloh") ==
870                 cstring_view::npos);
871 #endif
872 
873   // Searching for a string.
874   static_assert(cstring_view("hello hello").find_last_not_of("lo") == 7u);
875   static_assert(cstring_view("hello hello").find_last_not_of("hello ") ==
876                 cstring_view::npos);
877   static_assert(u16cstring_view(u"hello hello").find_last_not_of(u"lo") == 7u);
878   static_assert(u16cstring_view(u"hello hello").find_last_not_of(u"hello ") ==
879                 cstring_view::npos);
880   static_assert(u32cstring_view(U"hello hello").find_last_not_of(U"lo") == 7u);
881   static_assert(u32cstring_view(U"hello hello").find_last_not_of(U"hello ") ==
882                 cstring_view::npos);
883 #if BUILDFLAG(IS_WIN)
884   static_assert(wcstring_view(L"hello hello").find_last_not_of(L"lo") == 7u);
885   static_assert(wcstring_view(L"hello hello").find_last_not_of(L"hello ") ==
886                 cstring_view::npos);
887 #endif
888 }
889 
TEST(CStringViewTest,ToString)890 TEST(CStringViewTest, ToString) {
891   // Streaming support like std::string_view.
892   std::ostringstream s;
893   s << cstring_view("hello");
894   EXPECT_EQ(s.str(), "hello");
895 
896 #if BUILDFLAG(IS_WIN)
897   std::wostringstream sw;
898   sw << wcstring_view(L"hello");
899   EXPECT_EQ(sw.str(), L"hello");
900 #endif
901 
902   // Gtest printing support.
903   EXPECT_EQ(testing::PrintToString(cstring_view("hello")), "hello");
904 }
905 
TEST(CStringViewTest,Hash)906 TEST(CStringViewTest, Hash) {
907   [[maybe_unused]] auto s = std::hash<cstring_view>()(cstring_view("hello"));
908   static_assert(std::same_as<size_t, decltype(s)>);
909 
910   [[maybe_unused]] auto s16 =
911       std::hash<u16cstring_view>()(u16cstring_view(u"hello"));
912   static_assert(std::same_as<size_t, decltype(s)>);
913 
914   [[maybe_unused]] auto s32 =
915       std::hash<u32cstring_view>()(u32cstring_view(U"hello"));
916   static_assert(std::same_as<size_t, decltype(s)>);
917 
918 #if BUILDFLAG(IS_WIN)
919   [[maybe_unused]] auto sw =
920       std::hash<wcstring_view>()(wcstring_view(L"hello"));
921   static_assert(std::same_as<size_t, decltype(s)>);
922 #endif
923 }
924 
TEST(CStringViewTest,IntoStdStringView)925 TEST(CStringViewTest, IntoStdStringView) {
926   // string_view implicitly constructs from const char*, and so also from
927   // cstring_view.
928   std::string_view sc = "hello";
929   std::string_view s = cstring_view("hello");
930   EXPECT_EQ(s, sc);
931 
932   static_assert(std::string_view(cstring_view("hello")) == "hello");
933 }
934 
TEST(CStringViewTest,IntoStdString)935 TEST(CStringViewTest, IntoStdString) {
936   // string implicitly constructs from const char*, but not from
937   // std::string_view or cstring_view.
938   static_assert(std::convertible_to<const char*, std::string>);
939   static_assert(!std::convertible_to<std::string_view, std::string>);
940   static_assert(!std::convertible_to<cstring_view, std::string>);
941 
942   static_assert(std::constructible_from<std::string, const char*>);
943   static_assert(std::constructible_from<std::string, std::string_view>);
944   static_assert(std::constructible_from<std::string, cstring_view>);
945 
946   auto sv = std::string(std::string_view("hello"));
947   auto cs = std::string(cstring_view("hello"));
948   EXPECT_EQ(cs, sv);
949 
950   static_assert(std::string(cstring_view("hello")) == "hello");
951 }
952 
TEST(CStringViewTest,StringPlus)953 TEST(CStringViewTest, StringPlus) {
954   {
955     auto s = cstring_view("hello") + std::string("world");
956     static_assert(std::same_as<std::string, decltype(s)>);
957     EXPECT_EQ(s, "helloworld");
958   }
959   {
960     auto s = std::string("hello") + cstring_view("world");
961     static_assert(std::same_as<std::string, decltype(s)>);
962     EXPECT_EQ(s, "helloworld");
963   }
964   {
965     auto s = std::u16string(u"hello") + u16cstring_view(u"world");
966     static_assert(std::same_as<std::u16string, decltype(s)>);
967     EXPECT_EQ(s, u"helloworld");
968   }
969   {
970     auto s = std::u32string(U"hello") + u32cstring_view(U"world");
971     static_assert(std::same_as<std::u32string, decltype(s)>);
972     EXPECT_EQ(s, U"helloworld");
973   }
974   {
975 #if BUILDFLAG(IS_WIN)
976     auto s = std::wstring(L"hello") + wcstring_view(L"world");
977     static_assert(std::same_as<std::wstring, decltype(s)>);
978     EXPECT_EQ(s, L"helloworld");
979 #endif
980   }
981 
982   // From lvalues.
983   {
984     auto h = cstring_view("hello");
985     auto w = std::string("world");
986     auto s = h + w;
987     static_assert(std::same_as<std::string, decltype(s)>);
988     EXPECT_EQ(s, "helloworld");
989   }
990 
991   static_assert(cstring_view("hello") + std::string("world") == "helloworld");
992   static_assert(std::string("hello") + cstring_view("world") == "helloworld");
993 }
994 
TEST(CStringViewTest,StringAppend)995 TEST(CStringViewTest, StringAppend) {
996   std::string s = "hello";
997   // string::append() can accept cstring_view like const char*.
998   s.append(cstring_view("world"));
999   EXPECT_EQ(s, "helloworld");
1000 }
1001 
TEST(CStringViewTest,StringInsert)1002 TEST(CStringViewTest, StringInsert) {
1003   std::string s = "world";
1004   // string::insert() can accept cstring_view like const char*.
1005   s.insert(0u, cstring_view("hello"));
1006   EXPECT_EQ(s, "helloworld");
1007 }
1008 
TEST(CStringViewTest,StringReplace)1009 TEST(CStringViewTest, StringReplace) {
1010   std::string s = "goodbyeworld";
1011   // string::replace() can accept cstring_view like const char*.
1012   s.replace(0u, 7u, cstring_view("hello"));
1013   EXPECT_EQ(s, "helloworld");
1014 }
1015 
TEST(CStringViewTest,StringFind)1016 TEST(CStringViewTest, StringFind) {
1017   const std::string s = "helloworld";
1018   // string::find() can accept cstring_view like const char*.
1019   EXPECT_EQ(s.find(cstring_view("owo")), 4u);
1020 }
1021 
TEST(CStringViewTest,StringCompare)1022 TEST(CStringViewTest, StringCompare) {
1023   const std::string s = "hello";
1024   // string::compare() can accept cstring_view like const char*.
1025   EXPECT_EQ(s.compare(cstring_view("hello")), 0);
1026   // string::operator== can accept cstring_view like const char*.
1027   EXPECT_EQ(s, cstring_view("hello"));
1028   // string::operator<=> can accept cstring_view like const char*.
1029   EXPECT_EQ(s <=> cstring_view("hello"), std::weak_ordering::equivalent);
1030   // string::operator<= etc can accept cstring_view like const char*. This
1031   // follows from <=> normally but std::string has more overloads.
1032   EXPECT_LE(s, cstring_view("hello"));
1033 }
1034 
TEST(CStringViewTest,StringStartsEndsWith)1035 TEST(CStringViewTest, StringStartsEndsWith) {
1036   const std::string s = "hello";
1037   // string::starts_with() can accept cstring_view like const char*.
1038   EXPECT_EQ(s.starts_with(cstring_view("hel")), true);
1039   EXPECT_EQ(s.starts_with(cstring_view("lo")), false);
1040   // string::ends_with() can accept cstring_view like const char*.
1041   EXPECT_EQ(s.ends_with(cstring_view("hel")), false);
1042   EXPECT_EQ(s.ends_with(cstring_view("lo")), true);
1043 }
1044 
TEST(CStringViewTest,StrCat)1045 TEST(CStringViewTest, StrCat) {
1046   EXPECT_EQ(base::StrCat({cstring_view("hello"), std::string_view("world")}),
1047             "helloworld");
1048 }
1049 
TEST(CStringViewTest,Example_CtorLiteral)1050 TEST(CStringViewTest, Example_CtorLiteral) {
1051   const char kLiteral[] = "hello world";
1052   auto s = base::cstring_view(kLiteral);
1053   CHECK(s == "hello world");
1054   auto s2 = base::cstring_view("this works too");
1055   CHECK(s2 == "this works too");
1056 }
1057 
1058 }  // namespace
1059 }  // namespace base
1060