source: mainline/uspace/lib/cpp/src/internal/test/string.cpp@ d49bae9

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

cpp: added tests for std::string::substr

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