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

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

cpp: improved the testing framework

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