source: mainline/uspace/lib/cpp/src/__bits/test/string.cpp@ 7bbf91e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7bbf91e was 7bbf91e, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: changed internal to bits to avoid include space pollusion, fixed old std::hel:: bugs in files that weren't touched since

  • Property mode set to 100644
File size: 18.5 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <string>
30#include <initializer_list>
31#include <__bits/test/tests.hpp>
32#include <cstdio>
33
34namespace std::test
35{
36 bool string_test::run(bool report)
37 {
38 report_ = report;
39 start();
40
41 test_construction_and_assignment();
42 test_append();
43 test_insert();
44 test_erase();
45 test_replace();
46 test_copy();
47 test_find();
48 test_substr();
49 test_compare();
50
51 return end();
52 }
53
54 const char* string_test::name()
55 {
56 return "string";
57 }
58
59 void string_test::test_construction_and_assignment()
60 {
61 const char* check1 = "hello";
62
63 std::string str1{"hello"};
64 test_eq(
65 "size of string",
66 str1.size(), 5ul
67 );
68 test_eq(
69 "initialization from a cstring literal",
70 str1.begin(), str1.end(),
71 check1, check1 + 5
72 );
73
74 std::string str2{str1};
75 test_eq(
76 "copy constructor",
77 str1.begin(), str1.end(),
78 str2.begin(), str2.end()
79 );
80
81 std::string str3{std::move(str1)};
82 test_eq(
83 "move constructor equality",
84 str2.begin(), str2.end(),
85 str3.begin(), str3.end()
86 );
87 test_eq(
88 "move constructor source empty",
89 str1.size(), 0ul
90 );
91
92 std::string str4{};
93 test_eq(
94 "default constructor empty",
95 str4.size(), 0ul
96 );
97
98 str4.assign(str3, 2ul, 2ul);
99 test_eq(
100 "assign substring to an empty string",
101 str4.begin(), str4.end(),
102 str3.begin() + 2, str3.begin() + 4
103 );
104
105 std::string str5{str3.begin() + 2, str3.begin() + 4};
106 test_eq(
107 "constructor from a pair of iterators",
108 str5.begin(), str5.end(),
109 str3.begin() + 2, str3.begin() + 4
110 );
111 }
112
113 void string_test::test_append()
114 {
115 std::string check{"hello, world"};
116
117 std::string str1{"hello, "};
118 str1.append("world");
119 test_eq(
120 "append cstring",
121 str1.begin(), str1.end(),
122 check.begin(), check.end()
123 );
124
125 std::string str2{"hello, "};
126 str2.append(std::string{"world"});
127 test_eq(
128 "append rvalue string",
129 str2.begin(), str2.end(),
130 check.begin(), check.end()
131 );
132
133 std::string str3{"hello, "};
134 std::string apendee{"world"};
135 str3.append(apendee);
136 test_eq(
137 "append lvalue string",
138 str3.begin(), str3.end(),
139 check.begin(), check.end()
140 );
141
142 std::string str4{"hello, "};
143 str4.append(apendee.begin(), apendee.end());
144 test_eq(
145 "append iterator range",
146 str4.begin(), str4.end(),
147 check.begin(), check.end()
148 );
149
150 std::string str5{"hello, "};
151 str5.append({'w', 'o', 'r', 'l', 'd'});
152 test_eq(
153 "append initializer list",
154 str5.begin(), str5.end(),
155 check.begin(), check.end()
156 );
157
158 std::string str6{"hello, "};
159 str6 += "world";
160 test_eq(
161 "append using +=",
162 str6.begin(), str6.end(),
163 check.begin(), check.end()
164 );
165 }
166
167 void string_test::test_insert()
168 {
169 std::string check{"hello, world"};
170
171 std::string str1{", world"};
172 str1.insert(0, "hello");
173 test_eq(
174 "insert at the beggining",
175 str1.begin(), str1.end(),
176 check.begin(), check.end()
177 );
178
179 std::string str2{"hello,world"};
180 str2.insert(str2.begin() + 6, ' ');
181 test_eq(
182 "insert char in the middle",
183 str2.begin(), str2.end(),
184 check.begin(), check.end()
185 );
186
187 std::string str3{"heo, world"};
188 str3.insert(str3.begin() + 2, 2ul, 'l');
189 test_eq(
190 "insert n chars",
191 str3.begin(), str3.end(),
192 check.begin(), check.end()
193 );
194
195 std::string str4{"h, world"};
196 std::string insertee{"ello"};
197 str4.insert(str4.begin() + 1, insertee.begin(),
198 insertee.end());
199 test_eq(
200 "insert iterator range",
201 str4.begin(), str4.end(),
202 check.begin(), check.end()
203 );
204
205 std::string str5{"hel, world"};
206 std::initializer_list<char> init{'l', 'o'};
207 str5.insert(str5.begin() + 3, init);
208 test_eq(
209 "insert initializer list",
210 str5.begin(), str5.end(),
211 check.begin(), check.end()
212 );
213 }
214
215 void string_test::test_erase()
216 {
217 std::string check{"hello"};
218
219 std::string str1{"heXllo"};
220 str1.erase(str1.begin() + 2);
221 test_eq(
222 "erase single char in the middle",
223 str1.begin(), str1.end(),
224 check.begin(), check.end()
225 );
226
227 std::string str2{"Xhello"};
228 str2.erase(str2.begin());
229 test_eq(
230 "erase single char at the beginning",
231 str2.begin(), str2.end(),
232 check.begin(), check.end()
233 );
234
235 std::string str3{"helloX"};
236 str3.erase(str3.begin() + 5);
237 test_eq(
238 "erase single char at the end",
239 str3.begin(), str3.end(),
240 check.begin(), check.end()
241 );
242
243 std::string str4{"XXXhello"};
244 str4.erase(0, 3);
245 test_eq(
246 "erase string at the beginning",
247 str4.begin(), str4.end(),
248 check.begin(), check.end()
249 );
250
251 std::string str5{"heXXXllo"};
252 str5.erase(2, 3);
253 test_eq(
254 "erase string in the middle",
255 str5.begin(), str5.end(),
256 check.begin(), check.end()
257 );
258
259 std::string str6{"helloXXX"};
260 str6.erase(5);
261 test_eq(
262 "erase string at the end",
263 str6.begin(), str6.end(),
264 check.begin(), check.end()
265 );
266
267 std::string str7{"hellXXXo"};
268 str7.erase(str7.begin() + 4, str7.begin() + 7);
269 test_eq(
270 "erase iterator range",
271 str7.begin(), str7.end(),
272 check.begin(), check.end()
273 );
274 }
275
276 void string_test::test_replace()
277 {
278 std::string check{"hello, world"};
279
280 std::string str1{"helXXX world"};
281 str1.replace(3, 3, "lo,", 3);
282 test_eq(
283 "replace with full string",
284 str1.begin(), str1.end(),
285 check.begin(), check.end()
286 );
287
288 std::string str2{"helXXX world"};
289 str2.replace(3, 3, "lo,YYY", 3);
290 test_eq(
291 "replace with prefix of a string",
292 str2.begin(), str2.end(),
293 check.begin(), check.end()
294 );
295
296 std::string str3{"helXXX world"};
297 str3.replace(3, 3, "YYlo,YYY", 2, 3);
298 test_eq(
299 "replace with substring of a string",
300 str3.begin(), str3.end(),
301 check.begin(), check.end()
302 );
303
304 std::string str4{"heXXo, world"};
305 str4.replace(2, 2, 2, 'l');
306 test_eq(
307 "replace with repeated characters",
308 str4.begin(), str4.end(),
309 check.begin(), check.end()
310 );
311
312 std::string str5{"heXXXXo, world"};
313 str5.replace(2, 4, 2, 'l');
314 test_eq(
315 "replace with repeated characters (shrinking)",
316 str5.begin(), str5.end(),
317 check.begin(), check.end()
318 );
319
320 std::string str6{"helXXXXX world"};
321 str6.replace(3, 5, "YYlo,YYY", 2, 3);
322 test_eq(
323 "replace with substring of a string (shrinking)",
324 str6.begin(), str6.end(),
325 check.begin(), check.end()
326 );
327
328 std::string str7{"helXXXXX world"};
329 std::string replacer{"YYlo,YYY"};
330 str7.replace(3, 5, replacer, 2, 3);
331 test_eq(
332 "replace with substring of a string (shrinking, std::string)",
333 str7.begin(), str7.end(),
334 check.begin(), check.end()
335 );
336
337 std::string str8{"helXXXXX world"};
338 str8.replace(str8.begin() + 3, str8.begin() + 8, "lo,");
339 test_eq(
340 "replace with a string (iterators)",
341 str8.begin(), str8.end(),
342 check.begin(), check.end()
343 );
344
345 std::string str9{"heXXXXo, world"};
346 str9.replace(str9.begin() + 2, str9.begin() + 6, 2, 'l');
347 test_eq(
348 "replace with repeated characters (shrinking, iterators)",
349 str9.begin(), str9.end(),
350 check.begin(), check.end()
351 );
352
353 std::string str10{"helXXXXX world"};
354 str10.replace(str10.begin() + 3, str10.begin() + 8,
355 replacer.begin() + 2, replacer.begin() + 5);
356 test_eq(
357 "replace with substring of a string (shrinking, iterators x2)",
358 str10.begin(), str10.end(),
359 check.begin(), check.end()
360 );
361
362 std::string str11{"helXXXXX world"};
363 str11.replace(str11.begin() + 3, str11.begin() + 8,
364 {'l', 'o', ','});
365 test_eq(
366 "replace with an initializer list (shrinking, iterators)",
367 str11.begin(), str11.end(),
368 check.begin(), check.end()
369 );
370
371 std::string str12{"helXXX world"};
372 str12.replace(str12.begin() + 3, str12.begin() + 6,
373 {'l', 'o', ','});
374 test_eq(
375 "replace with an initializer list (iterators)",
376 str12.begin(), str12.end(),
377 check.begin(), check.end()
378 );
379 }
380
381 void string_test::test_copy()
382 {
383 std::string check{"CCABB"};
384
385 std::string str1{"ACCCA"};
386 std::string str2{"BBBBB"};
387
388 str1.copy(const_cast<char*>(str2.c_str()), 3, 2);
389 test_eq(
390 "copy",
391 str2.begin(), str2.end(),
392 check.begin(), check.end()
393 );
394 }
395
396 void string_test::test_find()
397 {
398 std::string target{"ABC"};
399 auto miss = std::string::npos;
400
401 std::string str1{"xxABCxx"};
402
403 auto idx = str1.find(target, 0);
404 test_eq(
405 "find from start (success)",
406 idx, 2ul
407 );
408
409 idx = str1.find(target, 3);
410 test_eq(
411 "find from start (fail, late start)",
412 idx, miss
413 );
414
415 idx = str1.rfind(target, miss);
416 test_eq(
417 "rfind from end (success)",
418 idx, 2ul
419 );
420
421 idx = str1.rfind(target, 1);
422 test_eq(
423 "rfind from start (fail, late start)",
424 idx, miss
425 );
426
427 idx = str1.find('B', 2);
428 test_eq(
429 "find char from middle (success)",
430 idx, 3ul
431 );
432
433 idx = str1.rfind('B', 2);
434 test_eq(
435 "rfind char from middle (success)",
436 idx, 3ul
437 );
438
439 std::string str2{"xxABCxxABCxx"};
440
441 idx = str2.find(target, 0);
442 test_eq(
443 "find from start (success, multiple)",
444 idx, 2ul
445 );
446
447 idx = str2.find(target, 5);
448 test_eq(
449 "find from middle (success, multiple)",
450 idx, 7ul
451 );
452
453 idx = str2.rfind(target, miss);
454 test_eq(
455 "rfind from end (success, multiple)",
456 idx, 7ul
457 );
458
459 idx = str2.rfind(target, 6);
460 test_eq(
461 "rfind from mid (success, multiple)",
462 idx, 2ul
463 );
464
465 std::string str3{"xxBxxAxxCxx"};
466
467 idx = str3.find_first_of(target);
468 test_eq(
469 "find first of from start (success)",
470 idx, 2ul
471 );
472
473 idx = str3.find_first_of(target, 6);
474 test_eq(
475 "find first of from middle (success)",
476 idx, 8ul
477 );
478
479 idx = str3.find_first_of("DEF", 3);
480 test_eq(
481 "find first of from middle (fail, not in string)",
482 idx, miss
483 );
484
485 idx = str3.find_first_of(target, 9);
486 test_eq(
487 "find first of from middle (fail, late start)",
488 idx, miss
489 );
490
491 idx = str3.find_first_of("");
492 test_eq(
493 "find first of from start (fail, no target)",
494 idx, miss
495 );
496
497 idx = str3.find_first_of('A', 1);
498 test_eq(
499 "find first of char (success)",
500 idx, 5ul
501 );
502
503 idx = str3.find_first_of('A', 6);
504 test_eq(
505 "find first of char (fail)",
506 idx, miss
507 );
508
509 idx = str3.find_last_of(target);
510 test_eq(
511 "find last of from start (success)",
512 idx, 8ul
513 );
514
515 idx = str3.find_last_of(target, 6);
516 test_eq(
517 "find last of from middle (success)",
518 idx, 5ul
519 );
520
521 idx = str3.find_last_of("DEF", 3);
522 test_eq(
523 "find last of from middle (fail, not in string)",
524 idx, miss
525 );
526
527 idx = str3.find_last_of(target, 1);
528 test_eq(
529 "find last of from middle (fail, late start)",
530 idx, miss
531 );
532
533 idx = str3.find_last_of("");
534 test_eq(
535 "find last of from start (fail, no target)",
536 idx, miss
537 );
538
539 idx = str3.find_last_of('A', str3.size() - 1);
540 test_eq(
541 "find last of char (success)",
542 idx, 5ul
543 );
544
545 idx = str3.find_last_of('A', 3);
546 test_eq(
547 "find last of char (fail)",
548 idx, miss
549 );
550
551 std::string not_target{"xB"};
552
553 idx = str3.find_first_not_of(not_target);
554 test_eq(
555 "find first not of from start (success)",
556 idx, 5ul
557 );
558
559 idx = str3.find_first_not_of(not_target, 6);
560 test_eq(
561 "find first not of from middle (success)",
562 idx, 8ul
563 );
564
565 idx = str3.find_first_not_of("xABC", 3);
566 test_eq(
567 "find first not of from middle (fail, not in string)",
568 idx, miss
569 );
570
571 idx = str3.find_first_not_of(not_target, 9);
572 test_eq(
573 "find first not of from middle (fail, late start)",
574 idx, miss
575 );
576
577 idx = str3.find_first_not_of("");
578 test_eq(
579 "find first not of from start (success, no target)",
580 idx, 0ul
581 );
582
583 idx = str3.find_first_not_of('x', 3);
584 test_eq(
585 "find first not of char (success)",
586 idx, 5ul
587 );
588
589 idx = str3.find_first_of('a', 9);
590 test_eq(
591 "find first not of char (fail)",
592 idx, miss
593 );
594
595 std::string not_last_target{"xC"};
596
597 idx = str3.find_last_not_of(not_last_target);
598 test_eq(
599 "find last not of from start (success)",
600 idx, 5ul
601 );
602
603 idx = str3.find_last_not_of(not_last_target, 4);
604 test_eq(
605 "find last not of from middle (success)",
606 idx, 2ul
607 );
608
609 idx = str3.find_last_not_of("xABC");
610 test_eq(
611 "find last not of from middle (fail, not in string)",
612 idx, miss
613 );
614
615 idx = str3.find_last_not_of(not_last_target, 1);
616 test_eq(
617 "find last not of from middle (fail, late start)",
618 idx, miss
619 );
620
621 idx = str3.find_last_not_of("");
622 test_eq(
623 "find last not of from start (success, no target)",
624 idx, str3.size() - 1
625 );
626
627 idx = str3.find_last_not_of('x', str3.size() - 1);
628 test_eq(
629 "find last not of char (success)",
630 idx, 8ul
631 );
632
633 idx = str3.find_last_not_of('x', 1);
634 test_eq(
635 "find last not of char (fail)",
636 idx, miss
637 );
638 }
639
640 void string_test::test_substr()
641 {
642 std::string check1{"abcd"};
643 std::string check2{"bcd"};
644 std::string check3{"def"};
645
646 std::string str{"abcdef"};
647 auto substr1 = str.substr(0, 4);
648 auto substr2 = str.substr(1, 3);
649 auto substr3 = str.substr(3);
650
651 test_eq(
652 "prefix substring",
653 substr1.begin(), substr1.end(),
654 check1.begin(), check1.end()
655 );
656
657 test_eq(
658 "substring",
659 substr2.begin(), substr2.end(),
660 check2.begin(), check2.end()
661 );
662
663 test_eq(
664 "suffix substring",
665 substr3.begin(), substr3.end(),
666 check3.begin(), check3.end()
667 );
668 }
669
670 void string_test::test_compare()
671 {
672 std::string str1{"aabbb"};
673 std::string str2{"bbbaa"};
674 std::string str3{"bbb"};
675
676 auto res = str1.compare(str1);
677 test_eq(
678 "compare equal",
679 res, 0
680 );
681
682 res = str1.compare(str2.c_str());
683 test_eq(
684 "compare less",
685 res, -1
686 );
687
688 res = str2.compare(str1);
689 test_eq(
690 "compare greater",
691 res, 1
692 );
693
694 res = str1.compare(2, 3, str2);
695 test_eq(
696 "compare substring less",
697 res, -1
698 );
699
700 res = str1.compare(2, 3, str3);
701 test_eq(
702 "compare substring equal",
703 res, 0
704 );
705 }
706}
Note: See TracBrowser for help on using the repository browser.