2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 // Author: eniebler@fb.com
20 #include <folly/FixedString.h>
21 #include <folly/portability/GTest.h>
23 #define FS(x) ::folly::makeFixedString(x)
24 using namespace folly::string_literals;
26 TEST(FixedStringExamples, Examples) {
27 // Example from the docs:
28 using namespace folly;
29 constexpr auto hello = makeFixedString("hello"); // a FixedString<5>
30 constexpr auto world = makeFixedString("world"); // another FixedString<5>
31 constexpr auto hello_world = hello + ' ' + world + '!';
32 static_assert(hello_world == "hello world!", "w00t");
33 EXPECT_STREQ("hello world!", hello_world.c_str());
35 FixedString<10> test{"****"};
36 test.replace(1, 2, "!!!!");
37 EXPECT_STREQ("*!!!!*", test.c_str());
38 static_assert(makeFixedString("****").creplace(1, 2, "!!!!") == "*!!!!*", "");
41 TEST(FixedStringCtorTest, Default) {
42 constexpr folly::FixedString<42> s{};
43 static_assert(s[0] == '\0', "");
44 static_assert(s.size() == 0u, "");
46 constexpr auto s2 = s;
47 static_assert(s2[0] == '\0', "");
48 static_assert(s2.size() == 0u, "");
51 TEST(FixedStringCtorTest, FromLiterals) {
52 constexpr folly::FixedString<42> s{"hello world"};
53 constexpr folly::FixedString<11> s2{"hello world"};
54 static_assert(s2[0] == 'h', "");
55 static_assert(s2[10] == 'd', "");
56 static_assert(s2[11] == '\0', "");
58 // Does not compile, hurray! :-)
59 // constexpr char a[1] = {'a'};
60 // constexpr folly::FixedString<10> s3(a);
63 TEST(FixedStringCtorTest, FromPtrAndLength) {
64 constexpr folly::FixedString<11> s{"hello world", 11};
65 static_assert(s[0] == 'h', "");
66 static_assert(s[10] == 'd', "");
67 static_assert(s[11] == '\0', "");
68 static_assert(s.size() == 11u, "");
70 constexpr folly::FixedString<5> s2{"hello world", 5};
71 static_assert(s2[0] == 'h', "");
72 static_assert(s2[4] == 'o', "");
73 static_assert(s2[5] == '\0', "");
74 static_assert(s2.size() == 5u, "");
76 constexpr folly::FixedString<20> s3{"hello world", 5};
77 static_assert(s2[0] == 'h', "");
78 static_assert(s2[4] == 'o', "");
79 static_assert(s2[5] == '\0', "");
80 static_assert(s2.size() == 5u, "");
82 static_assert("hello" == s3, "");
83 static_assert(s3 == "hello", "");
84 static_assert(s3 == s2, "");
85 static_assert("hell" != s3, "");
86 static_assert(s3 != "helloooo", "");
87 static_assert(!(s3 != s2), "");
90 TEST(FixedStringCtorTest, FromStringAndOffset) {
91 constexpr folly::FixedString<11> s{"hello world"};
92 constexpr folly::FixedString<5> s2{s, 6u, npos};
93 static_assert(s2 == "world", "");
94 constexpr folly::FixedString<0> s3{s, 11u, npos};
95 static_assert(s3 == "", "");
96 // Out of bounds offset, does not compile
97 // constexpr folly::FixedString<0> s4{s, 12};
100 TEST(FixedStringCtorTest, FromStringOffsetAndCount) {
101 constexpr folly::FixedString<11> s{"hello world"};
102 constexpr folly::FixedString<4> s2{s, 6u, 4u};
103 static_assert(s2 == "worl", "");
104 constexpr folly::FixedString<5> s3{s, 6u, 5u};
105 static_assert(s3 == "world", "");
106 // Out of bounds count, does not compile:
107 // constexpr folly::FixedString<5> s4{s, 6, 6};
110 TEST(FixedStringCtorTest, FromInitializerList) {
111 constexpr folly::FixedString<11> s{
112 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
113 static_assert(s == "hello world", "");
114 // Out of bounds count, does not compile:
115 // constexpr folly::FixedString<10> s{
116 // {'h','e','l','l','o',' ','w','o','r','l','d'}};
119 TEST(FixedStringCtorTest, FromUDL) {
120 using namespace folly::literals;
121 #if defined(__GNUC__)
122 constexpr auto x = "hello"_fs;
124 std::is_same<decltype(x), const folly::FixedString<5>>::value, "");
125 static_assert(x[0] == 'h', "");
126 static_assert(x[1] == 'e', "");
127 static_assert(x[2] == 'l', "");
128 static_assert(x[3] == 'l', "");
129 static_assert(x[4] == 'o', "");
130 static_assert(x[5] == '\0', "");
131 static_assert(x.size() == 5u, "");
134 constexpr auto y = "goodbye"_fs8;
136 std::is_same<decltype(y), const folly::FixedString<8>>::value, "");
137 static_assert(y.size() == 7u, "");
138 static_assert(y == "goodbye", "");
140 constexpr auto z = "now is the time for all good llamas"_fs64;
142 std::is_same<decltype(z), const folly::FixedString<64>>::value, "");
143 static_assert(z.size() == 35u, "");
144 static_assert(z == "now is the time for all good llamas", "");
147 TEST(FixedStringConcatTest, FromStringAndLiteral) {
148 constexpr folly::FixedString<42> s{"hello world"};
149 constexpr auto res = s + "!!!";
150 static_assert(res.size() == 14u, "");
151 static_assert(res == "hello world!!!", "");
154 TEST(FixedStringConcatTest, FromTwoStrings) {
155 constexpr folly::FixedString<42> s{"hello world"};
156 constexpr auto res = s + "!!!";
157 static_assert(res.size() == 14u, "");
158 static_assert(res == "hello world!!!", "");
161 #if FOLLY_USE_CPP14_CONSTEXPR
162 constexpr folly::FixedString<20> constexpr_swap_test() {
163 folly::FixedString<10> tmp1{"hello"}, tmp2{"world!"};
168 TEST(FixedStringSwapTest, ConstexprSwap) {
169 static_assert(constexpr_swap_test() == "world!hello", "");
173 TEST(FixedStringSwapTest, RuntimeSwap) {
174 folly::FixedString<10> tmp1{"hello"}, tmp2{"world!"};
176 EXPECT_STREQ((tmp1 + tmp2).c_str(), "world!hello");
179 #if FOLLY_USE_CPP14_CONSTEXPR
180 constexpr folly::FixedString<10> constexpr_assign_string_test_1() {
181 folly::FixedString<10> tmp1, tmp2{"world!"};
185 constexpr folly::FixedString<10> constexpr_assign_string_test_2() {
186 folly::FixedString<10> tmp{"aaaaaaaaaa"};
187 tmp.assign("hello"_fs8);
190 constexpr folly::FixedString<10> constexpr_assign_string_test_3() {
191 folly::FixedString<10> tmp{"aaaaaaaaaa"};
192 tmp.assign("goodbye"_fs8, 3u, 2u);
195 constexpr folly::FixedString<10> constexpr_assign_string_test_4() {
196 folly::FixedString<10> tmp{"aaaaaaaaaa"};
197 tmp.assign("goodbye"_fs8, 3u, npos);
201 TEST(FixedStringAssignTest, ConstexprAssignString) {
202 static_assert(constexpr_assign_string_test_1() == "world!", "");
203 static_assert(constexpr_assign_string_test_2() == "hello", "");
204 static_assert(constexpr_assign_string_test_3() == "db", "");
205 static_assert(constexpr_assign_string_test_4() == "dbye", "");
209 TEST(FixedStringAssignTest, RuntimeAssignString) {
210 folly::FixedString<10> tmp1, tmp2{"world!"};
212 EXPECT_STREQ(tmp1.c_str(), "world!");
213 tmp1.assign("goodbye"_fs8);
214 EXPECT_STREQ("goodbye", tmp1.c_str());
215 tmp1.assign("goodbye"_fs8, 3u, npos);
216 EXPECT_STREQ("dbye", tmp1.c_str());
217 tmp1.assign("goodbye"_fs8, 3u, 3u);
218 EXPECT_STREQ("dby", tmp1.c_str());
221 #if FOLLY_USE_CPP14_CONSTEXPR
222 constexpr folly::FixedString<10> constexpr_assign_literal_test_1() {
223 folly::FixedString<10> tmp{"aaaaaaaaaa"};
225 // Not null-terminated, does not compile:
226 // using C = const char[1];
230 constexpr folly::FixedString<10> constexpr_assign_literal_test_2() {
231 folly::FixedString<10> tmp{"aaaaaaaaaa"};
235 constexpr folly::FixedString<10> constexpr_assign_literal_test_3() {
236 folly::FixedString<10> tmp{"aaaaaaaaaa"};
237 tmp.assign("goodbye", 4u);
241 TEST(FixedStringAssignTest, ConstexprAssignLiteral) {
242 static_assert(constexpr_assign_literal_test_1() == "hello", "");
243 static_assert(constexpr_assign_literal_test_2() == "hello", "");
244 static_assert(constexpr_assign_literal_test_3() == "good", "");
248 TEST(FixedStringAssignTest, RuntimeAssignLiteral) {
249 folly::FixedString<10> tmp{"aaaaaaaaaa"};
251 EXPECT_STREQ("hello", tmp.c_str());
252 tmp.assign("goodbye");
253 EXPECT_STREQ("goodbye", tmp.c_str());
254 tmp.assign("goodbye", 4u);
255 EXPECT_STREQ("good", tmp.c_str());
258 TEST(FixedStringIndexTest, Index) {
259 constexpr folly::FixedString<11> digits{"0123456789"};
260 static_assert(digits[0] == '0', "");
261 static_assert(digits[1] == '1', "");
262 static_assert(digits[2] == '2', "");
263 static_assert(digits[9] == '9', "");
264 static_assert(digits[10] == '\0', "");
266 // This should be allowed and work in constexpr mode since the internal array
267 // is actually big enough and op[] does no parameter validation:
268 static_assert(digits[11] == '\0', "");
271 static_assert(digits.at(0) == '0', "");
272 static_assert(digits.at(1) == '1', "");
273 static_assert(digits.at(2) == '2', "");
274 static_assert(digits.at(9) == '9', "");
275 static_assert(digits.at(10) == '\0', "");
276 EXPECT_THROW(digits.at(11), std::out_of_range);
279 TEST(FixedStringCompareTest, Compare) {
280 constexpr folly::FixedString<10> tmp1{"aaaaaaaaaa"};
281 constexpr folly::FixedString<12> tmp2{"aaaaaaaaaba"};
282 static_assert(-1 == tmp1.compare(tmp2), "");
283 static_assert(1 == tmp2.compare(tmp1), "");
284 static_assert(0 == tmp2.compare(tmp2), "");
285 static_assert(tmp1 < tmp2, "");
286 static_assert(tmp1 <= tmp2, "");
287 static_assert(tmp2 > tmp1, "");
288 static_assert(tmp2 >= tmp1, "");
289 static_assert(tmp2 == tmp2, ""); // @nolint
290 static_assert(tmp2 <= tmp2, ""); // @nolint
291 static_assert(tmp2 >= tmp2, ""); // @nolint
292 static_assert(!(tmp2 < tmp2), "");
293 static_assert(!(tmp2 > tmp2), "");
295 constexpr folly::FixedString<10> tmp3{"aaa"};
296 constexpr folly::FixedString<12> tmp4{"aaaa"};
297 static_assert(-1 == tmp3.compare(tmp4), "");
298 static_assert(1 == tmp4.compare(tmp3), "");
299 static_assert(tmp3 < tmp4, "");
300 static_assert(tmp3 <= tmp4, "");
301 static_assert(tmp4 > tmp3, "");
302 static_assert(tmp4 >= tmp3, "");
303 static_assert(tmp3 < "aaaa", "");
304 static_assert(tmp3 <= "aaaa", "");
305 static_assert(!(tmp3 == tmp4), "");
306 static_assert(tmp3 != tmp4, "");
307 static_assert("aaaa" > tmp3, "");
308 static_assert("aaaa" >= tmp3, "");
309 static_assert("aaaa" != tmp3, "");
310 static_assert("aaa" == tmp3, "");
311 static_assert(tmp3 != "aaaa", "");
312 static_assert(tmp3 == "aaa", "");
315 #if FOLLY_USE_CPP14_CONSTEXPR
316 constexpr folly::FixedString<20> constexpr_append_string_test() {
317 folly::FixedString<20> a{"hello"}, b{"X world!"};
324 TEST(FixedStringAssignTest, ConstexprAppendString) {
325 static_assert(constexpr_append_string_test() == "hello world!", "");
329 TEST(FixedStringAssignTest, RuntimeAppendString) {
330 folly::FixedString<20> a{"hello"}, b{"X world!"};
334 EXPECT_STREQ("hello world!", a.c_str());
337 #if FOLLY_USE_CPP14_CONSTEXPR
338 constexpr folly::FixedString<20> constexpr_append_literal_test() {
339 folly::FixedString<20> a{"hello"};
341 a.append("X world!" + 2u, 5u);
342 a.append("X world!" + 7u);
346 TEST(FixedStringAssignTest, ConstexprAppendLiteral) {
347 static_assert(constexpr_append_literal_test() == "hello world!", "");
351 TEST(FixedStringAssignTest, RuntimeAppendLiteral) {
352 folly::FixedString<20> a{"hello"};
354 a.append("X world!" + 2u, 5u);
355 a.append("X world!" + 7u);
356 EXPECT_STREQ("hello world!", a.c_str());
359 TEST(FixedStringCAppendTest, CAppendString) {
360 constexpr folly::FixedString<10> a{"hello"}, b{"X world!"};
361 constexpr auto tmp1 = a.cappend(' ');
362 constexpr auto tmp2 = tmp1.cappend(b, 2u, 5u);
363 constexpr auto tmp3 = tmp2.cappend(b, 7u, 1u);
364 static_assert(tmp3 == "hello world!", "");
367 TEST(FixedStringCAppendTest, CAppendLiteral) {
368 constexpr folly::FixedString<10> a{"hello"};
369 constexpr auto tmp1 = a.cappend(' ');
370 constexpr auto tmp2 = tmp1.cappend("X world!", 2u, 5u);
371 constexpr auto tmp3 = tmp2.cappend("X world!", 7u, 1u);
372 static_assert(tmp3 == "hello world!", "");
375 #if FOLLY_USE_CPP14_CONSTEXPR
376 constexpr folly::FixedString<10> constexpr_replace_string_test() {
377 folly::FixedString<10> tmp{"abcdefghij"};
378 tmp.replace(1, 5, FS("XX"));
382 TEST(FixedStringReplaceTest, ConstexprReplaceString) {
383 static_assert(constexpr_replace_string_test().size() == 7u, "");
384 static_assert(constexpr_replace_string_test() == "aXXghij", "");
388 TEST(FixedStringReplaceTest, RuntimeReplaceString) {
389 folly::FixedString<10> tmp{"abcdefghij"};
390 tmp.replace(1, 5, FS("XX"));
391 EXPECT_EQ(7u, tmp.size());
392 EXPECT_STREQ("aXXghij", tmp.c_str());
395 TEST(FixedStringEraseTest, RuntimeEraseTest) {
396 auto x = FS("abcdefghijklmnopqrstuvwxyz"), y = x;
398 EXPECT_EQ(26u, x.size());
399 EXPECT_STREQ(y.c_str(), x.c_str());
400 x.erase(25u).erase(24u);
401 EXPECT_EQ(24u, x.size());
402 EXPECT_STREQ("abcdefghijklmnopqrstuvwx", x.c_str());
403 x.erase(1u, x.size() - 2u);
404 EXPECT_EQ(2u, x.size());
405 EXPECT_STREQ("ax", x.c_str());
408 TEST(FixedStringEraseTest, CEraseTest) {
409 constexpr auto x = FS("abcdefghijklmnopqrstuvwxyz"), y = x;
410 constexpr auto tmp0 = x.cerase(x.size());
411 static_assert(26u == tmp0.size(), "");
412 static_assert(y == tmp0, "");
413 constexpr auto tmp1 = tmp0.cerase(25u).cerase(24u);
414 static_assert(24u == tmp1.size(), "");
415 static_assert("abcdefghijklmnopqrstuvwx" == tmp1, "");
416 constexpr auto tmp2 = tmp1.cerase(1u, tmp1.size() - 2u);
417 static_assert(2u == tmp2.size(), "");
418 static_assert("ax" == tmp2, "");
419 constexpr auto tmp3 = tmp2.cerase();
420 static_assert("" == tmp3, "");
423 TEST(FixedStringFindTest, FindString) {
424 constexpr folly::FixedString<10> tmp{"hijdefghij"};
425 static_assert(tmp.find(FS("hij")) == 0u, "");
426 static_assert(tmp.find(FS("hij"), 1u) == 7u, "");
427 static_assert(tmp.find(FS("hijdefghij")) == 0u, "");
428 static_assert(tmp.find(FS("")) == 0u, "");
431 TEST(FixedStringFindTest, FindLiteral) {
432 constexpr folly::FixedString<10> tmp{"hijdefghij"};
433 static_assert(tmp.find("hij") == 0u, "");
434 static_assert(tmp.find("hij", 1u) == 7u, "");
435 static_assert(tmp.find("hijdefghij") == 0u, "");
438 TEST(FixedStringReverseFindTest, FindChar) {
439 constexpr folly::FixedString<16> tmp{"This is a string"};
440 static_assert(tmp.find('s') == 3u, "");
441 static_assert(tmp.find('s', 9u) == 10u, "");
442 static_assert(tmp.find('s', 10u) == 10u, "");
443 static_assert(tmp.find('s', 11u) == tmp.npos, "");
446 TEST(FixedStringReverseFindTest, ReverseFindString) {
447 constexpr folly::FixedString<16> tmp{"This is a string"};
448 static_assert(tmp.rfind(FS("is")) == 5u, "");
449 static_assert(tmp.rfind(FS("is"), 4u) == 2u, "");
450 static_assert(tmp.rfind(FS("This is a string")) == 0u, "");
451 static_assert(tmp.rfind(FS("This is a string!")) == tmp.npos, "");
452 static_assert(tmp.rfind(FS("")) == 16u, "");
455 TEST(FixedStringReverseFindTest, ReverseFindLiteral) {
456 constexpr folly::FixedString<16> tmp{"This is a string"};
457 static_assert(tmp.rfind("is") == 5u, "");
458 static_assert(tmp.rfind("is", 4u) == 2u, "");
459 static_assert(tmp.rfind("This is a string") == 0u, "");
460 static_assert(tmp.rfind("This is a string!") == tmp.npos, "");
461 static_assert(tmp.rfind("") == 16u, "");
464 TEST(FixedStringReverseFindTest, ReverseFindChar) {
465 constexpr folly::FixedString<16> tmp{"This is a string"};
466 static_assert(tmp.rfind('s') == 10u, "");
467 static_assert(tmp.rfind('s', 5u) == 3u, "");
468 static_assert(tmp.rfind('s', 3u) == 3u, "");
469 static_assert(tmp.rfind('s', 2u) == tmp.npos, "");
472 TEST(FixedStringFindFirstOfTest, FindFirstOfString) {
473 constexpr folly::FixedString<16> tmp{"This is a string"};
474 static_assert(tmp.find_first_of(FS("hi")) == 1u, "");
475 static_assert(tmp.find_first_of(FS("xi")) == 2u, "");
476 static_assert(tmp.find_first_of(FS("xi"), 6u) == 13u, "");
477 static_assert(tmp.find_first_of(FS("xz")) == tmp.npos, "");
478 static_assert(FS("a").find_first_of(FS("cba")) == 0u, "");
479 static_assert(FS("").find_first_of(FS("cba")) == tmp.npos, "");
480 static_assert(FS("a").find_first_of(FS("")) == tmp.npos, "");
481 static_assert(FS("").find_first_of(FS("")) == tmp.npos, "");
484 TEST(FixedStringFindFirstOfTest, FindFirstOfLiteral) {
485 constexpr folly::FixedString<16> tmp{"This is a string"};
486 static_assert(tmp.find_first_of("hi") == 1u, "");
487 static_assert(tmp.find_first_of("xi") == 2u, "");
488 static_assert(tmp.find_first_of("xi", 6u) == 13u, "");
489 static_assert(tmp.find_first_of("xis", 6u, 2u) == 13u, "");
490 static_assert(tmp.find_first_of("xz") == tmp.npos, "");
491 static_assert(FS("a").find_first_of("cba") == 0u, "");
492 static_assert(FS("").find_first_of("cba") == tmp.npos, "");
493 static_assert(FS("a").find_first_of("") == tmp.npos, "");
494 static_assert(FS("").find_first_of("") == tmp.npos, "");
497 TEST(FixedStringFindFirstOfTest, FindFirstOfChar) {
498 constexpr folly::FixedString<16> tmp{"This is a string"};
499 static_assert(tmp.find_first_of('h') == 1u, "");
500 static_assert(tmp.find_first_of('i') == 2u, "");
501 static_assert(tmp.find_first_of('i', 6u) == 13u, "");
502 static_assert(tmp.find_first_of('x') == tmp.npos, "");
503 static_assert(FS("a").find_first_of('a') == 0u, "");
504 static_assert(FS("").find_first_of('a') == tmp.npos, "");
507 TEST(FixedStringFindFirstNotOfTest, FindFirstNotOfString) {
508 constexpr folly::FixedString<16> tmp{"This is a string"};
509 static_assert(tmp.find_first_not_of(FS("Ti")) == 1u, "");
510 static_assert(tmp.find_first_not_of(FS("hT")) == 2u, "");
511 static_assert(tmp.find_first_not_of(FS("s atr"), 6u) == 13u, "");
512 static_assert(tmp.find_first_not_of(FS("This atrng")) == tmp.npos, "");
513 static_assert(FS("a").find_first_not_of(FS("X")) == 0u, "");
514 static_assert(FS("").find_first_not_of(FS("cba")) == tmp.npos, "");
515 static_assert(FS("a").find_first_not_of(FS("")) == 0u, "");
516 static_assert(FS("").find_first_not_of(FS("")) == tmp.npos, "");
519 TEST(FixedStringFindFirstNotOfTest, FindFirstNotOfLiteral) {
520 constexpr folly::FixedString<16> tmp{"This is a string"};
521 static_assert(tmp.find_first_not_of("Ti") == 1u, "");
522 static_assert(tmp.find_first_not_of("hT") == 2u, "");
523 static_assert(tmp.find_first_not_of("s atr", 6u) == 13u, "");
524 static_assert(tmp.find_first_not_of("This atrng") == tmp.npos, "");
525 static_assert(FS("a").find_first_not_of("X") == 0u, "");
526 static_assert(FS("").find_first_not_of("cba") == tmp.npos, "");
527 static_assert(FS("a").find_first_not_of("") == 0u, "");
528 static_assert(FS("").find_first_not_of("") == tmp.npos, "");
531 TEST(FixedStringFindFirstNotOfTest, FindFirstNotOfChar) {
532 constexpr folly::FixedString<16> tmp{"This is a string"};
533 static_assert(tmp.find_first_not_of('T') == 1u, "");
534 static_assert(tmp.find_first_not_of('i') == 0u, "");
535 static_assert(tmp.find_first_not_of('x', 6u) == 6u, "");
536 static_assert(tmp.find_first_not_of('s', 6u) == 7u, "");
537 static_assert(FS("a").find_first_not_of('a') == tmp.npos, "");
538 static_assert(FS("").find_first_not_of('a') == tmp.npos, "");
541 TEST(FixedStringFindLastOfTest, FindLastOfString) {
542 constexpr folly::FixedString<16> tmp{"This is a string"};
543 static_assert(tmp.find_last_of(FS("hi")) == 13u, "");
544 static_assert(tmp.find_last_of(FS("xh")) == 1u, "");
545 static_assert(tmp.find_last_of(FS("xi"), 6u) == 5u, "");
546 static_assert(tmp.find_last_of(FS("xz")) == tmp.npos, "");
547 static_assert(FS("a").find_last_of(FS("cba")) == 0u, "");
548 static_assert(FS("").find_last_of(FS("cba")) == tmp.npos, "");
549 static_assert(FS("a").find_last_of(FS("")) == tmp.npos, "");
550 static_assert(FS("").find_last_of(FS("")) == tmp.npos, "");
553 TEST(FixedStringFindLastOfTest, FindLastOfLiteral) {
554 constexpr folly::FixedString<16> tmp{"This is a string"};
555 static_assert(tmp.find_last_of("hi") == 13u, "");
556 static_assert(tmp.find_last_of("xh") == 1u, "");
557 static_assert(tmp.find_last_of("xi", 6u) == 5u, "");
558 static_assert(tmp.find_last_of("xis", 6u, 2u) == 5u, "");
559 static_assert(tmp.find_last_of("xz") == tmp.npos, "");
560 static_assert(FS("a").find_last_of("cba") == 0u, "");
561 static_assert(FS("").find_last_of("cba") == tmp.npos, "");
562 static_assert(FS("a").find_last_of("") == tmp.npos, "");
563 static_assert(FS("").find_last_of("") == tmp.npos, "");
566 TEST(FixedStringFindLastOfTest, FindLastOfChar) {
567 constexpr folly::FixedString<16> tmp{"This is a string"};
568 static_assert(tmp.find_last_of('h') == 1u, "");
569 static_assert(tmp.find_last_of('i') == 13u, "");
570 static_assert(tmp.find_last_of('i', 6u) == 5u, "");
571 static_assert(tmp.find_last_of('x') == tmp.npos, "");
572 static_assert(FS("a").find_last_of('a') == 0u, "");
573 static_assert(FS("").find_last_of('a') == tmp.npos, "");
576 TEST(FixedStringFindLastNotOfTest, FindLastNotOfString) {
577 constexpr folly::FixedString<16> tmp{"This is a string"};
578 static_assert(tmp.find_last_not_of(FS("gstrin")) == 9u, "");
579 static_assert(tmp.find_last_not_of(FS("hT")) == 15u, "");
580 static_assert(tmp.find_last_not_of(FS("s atr"), 6u) == 5u, "");
581 static_assert(tmp.find_last_not_of(FS("This atrng")) == tmp.npos, "");
582 static_assert(FS("a").find_last_not_of(FS("X")) == 0u, "");
583 static_assert(FS("").find_last_not_of(FS("cba")) == tmp.npos, "");
584 static_assert(FS("a").find_last_not_of(FS("")) == 0u, "");
585 static_assert(FS("").find_last_not_of(FS("")) == tmp.npos, "");
588 TEST(FixedStringFindLastNotOfTest, FindLastNotOfLiteral) {
589 constexpr folly::FixedString<16> tmp{"This is a string"};
590 static_assert(tmp.find_last_not_of("gstrin") == 9u, "");
591 static_assert(tmp.find_last_not_of("hT") == 15u, "");
592 static_assert(tmp.find_last_not_of("s atr", 6u) == 5u, "");
593 static_assert(tmp.find_last_not_of(" atrs", 6u, 4u) == 6u, "");
594 static_assert(tmp.find_last_not_of("This atrng") == tmp.npos, "");
595 static_assert(FS("a").find_last_not_of("X") == 0u, "");
596 static_assert(FS("").find_last_not_of("cba") == tmp.npos, "");
597 static_assert(FS("a").find_last_not_of("") == 0u, "");
598 static_assert(FS("").find_last_not_of("") == tmp.npos, "");
601 TEST(FixedStringFindLastNotOfTest, FindLastNotOfChar) {
602 constexpr folly::FixedString<16> tmp{"This is a string"};
603 static_assert(tmp.find_last_not_of('g') == 14u, "");
604 static_assert(tmp.find_last_not_of('i') == 15u, "");
605 static_assert(tmp.find_last_not_of('x', 6u) == 6u, "");
606 static_assert(tmp.find_last_not_of('s', 6u) == 5u, "");
607 static_assert(FS("a").find_last_not_of('a') == tmp.npos, "");
608 static_assert(FS("").find_last_not_of('a') == tmp.npos, "");
611 TEST(FixedStringConversionTest, ConversionToStdString) {
612 constexpr folly::FixedString<16> tmp{"This is a string"};
613 std::string str = tmp;
614 EXPECT_STREQ("This is a string", str.c_str());
615 str = "another string"_fs16;
616 EXPECT_STREQ("another string", str.c_str());
619 #if FOLLY_USE_CPP14_CONSTEXPR
620 constexpr std::size_t countSpacesReverse(folly::FixedString<50> s) {
621 std::size_t count = 0u;
623 for( ; i != s.rend(); ++i, --i, i++, i--, i+=1, i-=1, i+=1 ) {
630 TEST(FixedStringReverseIteratorTest, Cpp14ConstexprReverseIteration) {
631 static_assert(3 == countSpacesReverse("This is a string"), "");
635 TEST(FixedStringReverseIteratorTest, ConstexprReverseIteration) {
636 static constexpr auto alpha = FS("abcdefghijklmnopqrstuvwxyz");
637 static_assert('a' == alpha.rbegin()[25], "");
638 static_assert('a' == *(alpha.rbegin() + 25), "");
639 static_assert('c' == *(alpha.rbegin() + 25 - 2), "");
640 static_assert((alpha.rend() - 2) == (alpha.rbegin() + 24), "");
644 // FixedString runs afoul of GCC #61971 (spurious -Warray-bounds)
645 // in optimized builds. The following test case triggers it for gcc-4.x.
646 // Test that FixedString suppresses the warning correctly.
647 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61971
648 constexpr auto xyz = folly::makeFixedString("xyz");
649 constexpr auto dot = folly::makeFixedString(".");
651 template <typename T1>
652 constexpr auto concatStuff(const T1& component) noexcept {
653 return xyz + dot + component;
655 constexpr auto co = folly::makeFixedString("co");
658 std::string s{concatStuff(co)};
660 } // namespace GCC61971
662 TEST(FixedStringGCC61971, GCC61971) {
667 #include <folly/Range.h>
669 TEST(FixedStringConversionTest, ConversionToFollyRange) {
670 // The following declaraction is static for compilers that haven't implemented
671 // the resolution of:
672 // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1454
673 static constexpr folly::FixedString<16> tmp{"This is a string"};
674 constexpr folly::StringPiece piece = tmp;
675 static_assert(tmp.begin() == piece.begin(), "");
676 static_assert(tmp.end() == piece.end(), "");