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