1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/json
8 //
9 
10 // Test that header file is self-contained.
11 #include <boost/json/string.hpp>
12 
13 #include <boost/json/monotonic_resource.hpp>
14 #include <boost/json/parse.hpp>
15 
16 #include <numeric>
17 #include <sstream>
18 #include <string>
19 #include <stdint.h>
20 #include <unordered_set>
21 
22 #include "test.hpp"
23 #include "test_suite.hpp"
24 
25 BOOST_JSON_NS_BEGIN
26 
27 BOOST_STATIC_ASSERT( std::is_nothrow_destructible<string>::value );
28 BOOST_STATIC_ASSERT( std::is_nothrow_move_constructible<string>::value );
29 
30 class string_test
31 {
32 public:
33 
34 #if BOOST_JSON_ARCH == 64
35 # define INIT1 { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n' }
36 # define INIT2 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' }
37 #elif BOOST_JSON_ARCH == 32
38 # define INIT1 { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' }
39 # define INIT2 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K' }
40 #else
41 # error Unknown architecture
42 #endif
43 
44     struct test_vectors
45     {
46         // fit in sbo
47         string_view v1; // "abc...
48 
49         // dynamic alloc
50         string_view v2; // "ABC...
51 
52         std::string const s1;
53         std::string const s2;
54 
test_vectorsstring_test::test_vectors55         test_vectors()
56             : s1([&]
57             {
58                 std::string s;
59                 s.resize(string{}.capacity());
60                 std::iota(s.begin(), s.end(), 'a');
61                 return s;
62             }())
63             , s2([&]
__anon31acec7e0202string_test::test_vectors64             {
65                 std::string s;
66                 s.resize(string{}.capacity() + 1);
67                 std::iota(s.begin(), s.end(), 'A');
68                 return s;
69             }())
70         {
71             v1 = s1;
72             v2 = s2;
73 
74             BOOST_TEST(std::string(INIT1) == s1);
75             BOOST_TEST(std::string(INIT2) == s2);
76         }
77     };
78 
79     static
80     string_view
last_of(string_view s,std::size_t n)81     last_of(
82         string_view s,
83         std::size_t n)
84     {
85         return s.substr(s.size() - n);
86     }
87 
88     void
testConstruction()89     testConstruction()
90     {
91         test_vectors const t;
92 
93         // string()
94         {
95             string s;
96         }
97 
98         // string(storage_ptr)
99         {
100             auto const sp =
101                 make_shared_resource<unique_resource>();
102             string s(sp);
103             BOOST_TEST(s.empty());
104             BOOST_TEST(*s.storage() == *sp.get());
105         }
106 
107         // string(size_type, char, storage_ptr)
108         {
109             fail_loop([&](storage_ptr const& sp)
110             {
111                 string s(t.v1.size(), '*', sp);
112                 BOOST_TEST(s == std::string(t.v1.size(), '*'));
113             });
114 
115             {
116                 string s(t.v2.size(), '*');
117                 BOOST_TEST(s == std::string(t.v2.size(), '*'));
118             }
119         }
120 
121         // string(char const*, storage_ptr)
122         {
123             fail_loop([&](storage_ptr const& sp)
124             {
125                 string s(t.s1.c_str(), sp);
126                 BOOST_TEST(s == t.v1);
127             });
128 
129             fail_loop([&](storage_ptr const& sp)
130             {
131                 string s(t.s2.c_str(), sp);
132                 BOOST_TEST(s == t.v2);
133             });
134 
135             {
136                 string s(t.s1.c_str());
137                 BOOST_TEST(s == t.v1);
138             }
139 
140             {
141                 string s(t.s2.c_str());
142                 BOOST_TEST(s == t.v2);
143             }
144         }
145 
146         // string(char const*, size_type, storage_ptr)
147         {
148             fail_loop([&](storage_ptr const& sp)
149             {
150                 string s(t.s1.c_str(), 3, sp);
151                 BOOST_TEST(s == "abc");
152             });
153 
154             fail_loop([&](storage_ptr const& sp)
155             {
156                 string s(t.s2.c_str(), 3, sp);
157                 BOOST_TEST(s == "ABC");
158             });
159 
160             {
161                 string s(t.s1.c_str(), 3);
162                 BOOST_TEST(s == "abc");
163             }
164 
165             {
166                 string s(t.s2.c_str(), 3);
167                 BOOST_TEST(s == "ABC");
168             }
169         }
170 
171         // string(InputIt, InputIt, storage_ptr)
172         {
173             fail_loop([&](storage_ptr const& sp)
174             {
175                 string s(t.v1.begin(), t.v1.end(), sp);
176                 BOOST_TEST(s == t.v1);
177             });
178 
179             fail_loop([&](storage_ptr const& sp)
180             {
181                 string s(t.v2.begin(), t.v2.end(), sp);
182                 BOOST_TEST(s == t.v2);
183             });
184 
185             fail_loop([&](storage_ptr const& sp)
186             {
187                 string s(
188                     make_input_iterator(t.v1.begin()),
189                     make_input_iterator(t.v1.end()), sp);
190                 BOOST_TEST(s == t.v1);
191             });
192 
193             fail_loop([&](storage_ptr const& sp)
194             {
195                 string s(
196                     make_input_iterator(t.v2.begin()),
197                     make_input_iterator(t.v2.end()), sp);
198                 BOOST_TEST(s == t.v2);
199             });
200 
201             {
202                 string s(t.v1.begin(), t.v1.end());
203                 BOOST_TEST(s == t.v1);
204             }
205 
206             {
207                 string s(t.v2.begin(), t.v2.end());
208                 BOOST_TEST(s == t.v2);
209             }
210 
211             {
212                 string s(
213                     make_input_iterator(t.v1.begin()),
214                     make_input_iterator(t.v1.end()));
215                 BOOST_TEST(s == t.v1);
216             }
217 
218             {
219                 string s(
220                     make_input_iterator(t.v2.begin()),
221                     make_input_iterator(t.v2.end()));
222                 BOOST_TEST(s == t.v2);
223             }
224         }
225 
226         // string(string)
227         {
228             {
229                 string const s0(t.v1);
230                 string s(s0);
231                 BOOST_TEST(s == t.v1);
232             }
233 
234             {
235                 string const s0(t.v2);
236                 string s(s0);
237                 BOOST_TEST(s == t.v2);
238             }
239         }
240 
241         // string(string, storage_ptr)
242         {
243             fail_loop([&](storage_ptr const& sp)
244             {
245                 string const s0(t.v1);
246                 string s(s0, sp);
247                 BOOST_TEST(s == t.v1);
248             });
249 
250             fail_loop([&](storage_ptr const& sp)
251             {
252                 string const s0(t.v2);
253                 string s(s0, sp);
254                 BOOST_TEST(s == t.v2);
255             });
256         }
257 
258         // string(pilfered<string>)
259         {
260             {
261                 string s1(t.v1);
262                 string s2(pilfer(s1));
263                 BOOST_TEST(s2 == t.v1);
264                 BOOST_TEST(s1.empty());
265                 BOOST_TEST(
266                     s1.storage() == storage_ptr());
267             }
268 
269             {
270                 string s1(t.v2);
271                 string s2(pilfer(s1));
272                 BOOST_TEST(s2 == t.v2);
273                 BOOST_TEST(s1.empty());
274                 BOOST_TEST(
275                     s1.storage() == storage_ptr());
276             }
277 
278             // ensure pilfered-from objects
279             // are trivially destructible
280             {
281                 string s1(make_shared_resource<
282                     monotonic_resource>());
283                 string s2(pilfer(s1));
284                 BOOST_TEST(s1.storage().get() ==
285                     storage_ptr().get());
286             }
287         }
288 
289         // string(string&&)
290         {
291             {
292                 string s1(t.v1);
293                 string s2(std::move(s1));
294                 BOOST_TEST(s2 == t.v1);
295                 BOOST_TEST(s1.empty());
296                 BOOST_TEST(
297                     *s1.storage() ==
298                     *s2.storage());
299             }
300 
301             {
302                 string s1(t.v2);
303                 string s2(std::move(s1));
304                 BOOST_TEST(s2 == t.v2);
305                 BOOST_TEST(s1.empty());
306                 BOOST_TEST(
307                     *s1.storage() ==
308                     *s2.storage());
309             }
310         }
311 
312         // string(string&&, storage_ptr)
313         {
314             // same storage
315 
316             fail_loop([&](storage_ptr const& sp)
317             {
318                 string s1(t.v1, sp);
319                 string s2(std::move(s1), sp);
320                 BOOST_TEST(s2 == t.v1);
321                 BOOST_TEST(s1.empty());
322                 BOOST_TEST(
323                     *s1.storage() ==
324                     *s2.storage());
325             });
326 
327             fail_loop([&](storage_ptr const& sp)
328             {
329                 string s1(t.v2, sp);
330                 string s2(std::move(s1));
331                 BOOST_TEST(s2 == t.v2);
332                 BOOST_TEST(s1.empty());
333                 BOOST_TEST(
334                     *s1.storage() ==
335                     *s2.storage());
336             });
337 
338             // different storage
339 
340             fail_loop([&](storage_ptr const& sp)
341             {
342                 string s1(t.v1);
343                 string s2(std::move(s1), sp);
344                 BOOST_TEST(s2 == t.v1);
345                 BOOST_TEST(s1 == t.v1);
346                 BOOST_TEST(
347                     *s1.storage() !=
348                     *s2.storage());
349             });
350 
351             fail_loop([&](storage_ptr const& sp)
352             {
353                 string s1(t.v2);
354                 string s2(std::move(s1), sp);
355                 BOOST_TEST(s2 == t.v2);
356                 BOOST_TEST(s1 == t.v2);
357                 BOOST_TEST(
358                     *s1.storage() !=
359                     *s2.storage());
360             });
361         }
362 
363         // string(string_view, storage_ptr)
364         {
365             fail_loop([&](storage_ptr const& sp)
366             {
367                 string s(t.v1, sp);
368                 BOOST_TEST(s == t.v1);
369             });
370 
371             fail_loop([&](storage_ptr const& sp)
372             {
373                 string s(t.v2, sp);
374                 BOOST_TEST(s == t.v2);
375             });
376 
377             {
378                 string s(t.v1);
379                 BOOST_TEST(s == t.v1);
380             }
381 
382             {
383                 string s(t.v2);
384                 BOOST_TEST(s == t.v2);
385             }
386         }
387     }
388 
389     void
testAssignment()390     testAssignment()
391     {
392         test_vectors const t;
393 
394         // operator=(string)
395         {
396             fail_loop([&](storage_ptr const& sp)
397             {
398                 std::string c(t.v1.size(), '*');
399                 string s(c, sp);
400                 string const s2(t.v1);
401                 s = s2;
402                 BOOST_TEST(s == t.v1);
403             });
404 
405             fail_loop([&](storage_ptr const& sp)
406             {
407                 std::string c(t.v2.size(), '*');
408                 string s(c, sp);
409                 string const s2(t.v1);
410                 s = s2;
411                 BOOST_TEST(s == t.v1);
412             });
413 
414             fail_loop([&](storage_ptr const& sp)
415             {
416                 std::string c(t.v1.size(), '*');
417                 string s(c, sp);
418                 string const s2(t.v2);
419                 s = s2;
420                 BOOST_TEST(s == t.v2);
421             });
422 
423             fail_loop([&](storage_ptr const& sp)
424             {
425                 std::string c(t.v2.size(), '*');
426                 string s(c, sp);
427                 string const s2(t.v2);
428                 s = s2;
429                 BOOST_TEST(s == t.v2);
430             });
431         }
432 
433         // operator=(string&&)
434         {
435             // same storage
436 
437             fail_loop([&](storage_ptr const& sp)
438             {
439                 std::string c(t.v1.size(), '*');
440                 string s(c, sp);
441                 string s2(t.v1, sp);
442                 s = std::move(s2);
443                 BOOST_TEST(s == t.v1);
444                 BOOST_TEST(s2.empty());
445                 BOOST_TEST(
446                     *s.storage() ==
447                     *s2.storage());
448             });
449 
450             fail_loop([&](storage_ptr const& sp)
451             {
452                 std::string c(t.v2.size(), '*');
453                 string s(c, sp);
454                 string s2(t.v1, sp);
455                 s = std::move(s2);
456                 BOOST_TEST(s == t.v1);
457                 BOOST_TEST(s2.empty());
458                 BOOST_TEST(
459                     *s.storage() ==
460                     *s2.storage());
461             });
462 
463             fail_loop([&](storage_ptr const& sp)
464             {
465                 std::string c(t.v1.size(), '*');
466                 string s(c, sp);
467                 string s2(t.v2, sp);
468                 s = std::move(s2);
469                 BOOST_TEST(s == t.v2);
470                 BOOST_TEST(s2.empty());
471                 BOOST_TEST(
472                     *s.storage() ==
473                     *s2.storage());
474             });
475 
476             fail_loop([&](storage_ptr const& sp)
477             {
478                 std::string c(t.v2.size(), '*');
479                 string s(c, sp);
480                 string s2(t.v2, sp);
481                 s = std::move(s2);
482                 BOOST_TEST(s == t.v2);
483                 BOOST_TEST(s2.empty());
484                 BOOST_TEST(
485                     *s.storage() ==
486                     *s2.storage());
487             });
488 
489             // different storage
490 
491             fail_loop([&](storage_ptr const& sp)
492             {
493                 std::string c(t.v1.size(), '*');
494                 string s(c, sp);
495                 string s2(t.v1);
496                 s = std::move(s2);
497                 BOOST_TEST(s == t.v1);
498                 BOOST_TEST(s2 == t.v1);
499                 BOOST_TEST(
500                     *s.storage() !=
501                     *s2.storage());
502             });
503 
504             fail_loop([&](storage_ptr const& sp)
505             {
506                 std::string c(t.v2.size(), '*');
507                 string s(c, sp);
508                 string s2(t.v1);
509                 s = std::move(s2);
510                 BOOST_TEST(s == t.v1);
511                 BOOST_TEST(s2 == t.v1);
512                 BOOST_TEST(
513                     *s.storage() !=
514                     *s2.storage());
515             });
516 
517             fail_loop([&](storage_ptr const& sp)
518             {
519                 std::string c(t.v1.size(), '*');
520                 string s(c, sp);
521                 string s2(t.v2);
522                 s = std::move(s2);
523                 BOOST_TEST(s == t.v2);
524                 BOOST_TEST(s2 == t.v2);
525                 BOOST_TEST(
526                     *s.storage() !=
527                     *s2.storage());
528             });
529 
530             fail_loop([&](storage_ptr const& sp)
531             {
532                 std::string c(t.v2.size(), '*');
533                 string s(c, sp);
534                 string s2(t.v2);
535                 s = std::move(s2);
536                 BOOST_TEST(s == t.v2);
537                 BOOST_TEST(s2 == t.v2);
538                 BOOST_TEST(
539                     *s.storage() !=
540                     *s2.storage());
541             });
542         }
543 
544         // operator=(char const*)
545         {
546             fail_loop([&](storage_ptr const& sp)
547             {
548                 string s(t.v1.size(), '*', sp);
549                 s = t.s1.c_str();
550                 BOOST_TEST(s == t.v1);
551             });
552 
553             fail_loop([&](storage_ptr const& sp)
554             {
555                 string s(t.v2.size(), '*', sp);
556                 s = t.s1.c_str();
557                 BOOST_TEST(s == t.v1);
558             });
559 
560             fail_loop([&](storage_ptr const& sp)
561             {
562                 string s(t.v1.size(), '*', sp);
563                 s = t.s2.c_str();
564                 BOOST_TEST(s == t.v2);
565             });
566 
567             fail_loop([&](storage_ptr const& sp)
568             {
569                 string s(t.v2.size(), '*', sp);
570                 s = t.s2.c_str();
571                 BOOST_TEST(s == t.v2);
572             });
573         }
574 
575         // operator=(string_view)
576         {
577             fail_loop([&](storage_ptr const& sp)
578             {
579                 string s(t.v1.size(), '*', sp);
580                 s = t.v1;
581                 BOOST_TEST(s == t.v1);
582             });
583 
584             fail_loop([&](storage_ptr const& sp)
585             {
586                 string s(t.v2.size(), '*', sp);
587                 s = t.v1;
588                 BOOST_TEST(s == t.v1);
589             });
590 
591             fail_loop([&](storage_ptr const& sp)
592             {
593                 string s(t.v1.size(), '*', sp);
594                 s = t.v2;
595                 BOOST_TEST(s == t.v2);
596             });
597 
598             fail_loop([&](storage_ptr const& sp)
599             {
600                 string s(t.v2.size(), '*', sp);
601                 s = t.v2;
602                 BOOST_TEST(s == t.v2);
603             });
604         }
605     }
606 
607     void
testAssign()608     testAssign()
609     {
610         test_vectors const t;
611 
612         // assign(size_type, char)
613         {
614             fail_loop([&](storage_ptr const& sp)
615             {
616                 string s(t.v1.size(), 'x', sp);
617                 s.assign(t.v1.size(), '*');
618                 BOOST_TEST(
619                     s == std::string(t.v1.size(), '*'));
620             });
621 
622             fail_loop([&](storage_ptr const& sp)
623             {
624                 string s(t.v2.size(), 'x', sp);
625                 s.assign(t.v1.size(), '*');
626                 BOOST_TEST(
627                     s == std::string(t.v1.size(), '*'));
628             });
629 
630             fail_loop([&](storage_ptr const& sp)
631             {
632                 string s(t.v1.size(), 'x', sp);
633                 s.assign(t.v2.size(), '*');
634                 BOOST_TEST(
635                     s == std::string(t.v2.size(), '*'));
636             });
637 
638             fail_loop([&](storage_ptr const& sp)
639             {
640                 string s(t.v2.size(), 'x', sp);
641                 s.assign(t.v2.size(), '*');
642                 BOOST_TEST(
643                     s == std::string(t.v2.size(), '*'));
644             });
645         }
646 
647         // assign(string)
648         {
649             fail_loop([&](storage_ptr const& sp)
650             {
651                 string s(t.v1.size(), 'x', sp);
652                 s.assign(string(t.v1.size(), '*'));
653                 BOOST_TEST(
654                     s == std::string(t.v1.size(), '*'));
655             });
656 
657             fail_loop([&](storage_ptr const& sp)
658             {
659                 string s(t.v2.size(), 'x', sp);
660                 s.assign(string(t.v1.size(), '*'));
661                 BOOST_TEST(
662                     s == std::string(t.v1.size(), '*'));
663             });
664 
665             fail_loop([&](storage_ptr const& sp)
666             {
667                 string s(t.v1.size(), 'x', sp);
668                 s.assign(string(t.v2.size(), '*'));
669                 BOOST_TEST(
670                     s == std::string(t.v2.size(), '*'));
671             });
672 
673             fail_loop([&](storage_ptr const& sp)
674             {
675                 string s(t.v2.size(), 'x', sp);
676                 s.assign(string(t.v2.size(), '*'));
677                 BOOST_TEST(
678                     s == std::string(t.v2.size(), '*'));
679             });
680 
681             // self-assign
682             {
683                 string s(t.v1);
684                 s = static_cast<string const&>(s);
685                 BOOST_TEST(s == t.v1);
686             }
687         }
688 
689         // assign(string&&)
690         {
691             // same storage
692 
693             fail_loop([&](storage_ptr const& sp)
694             {
695                 std::string c(t.v1.size(), '*');
696                 string s(c, sp);
697                 string s2(t.v1, sp);
698                 s.assign(std::move(s2));
699                 BOOST_TEST(s == t.v1);
700                 BOOST_TEST(s2.empty());
701                 BOOST_TEST(
702                     *s.storage() ==
703                     *s2.storage());
704             });
705 
706             fail_loop([&](storage_ptr const& sp)
707             {
708                 std::string c(t.v2.size(), '*');
709                 string s(c, sp);
710                 string s2(t.v1, sp);
711                 s.assign(std::move(s2));
712                 BOOST_TEST(s == t.v1);
713                 BOOST_TEST(s2.empty());
714                 BOOST_TEST(
715                     *s.storage() ==
716                     *s2.storage());
717             });
718 
719             fail_loop([&](storage_ptr const& sp)
720             {
721                 std::string c(t.v1.size(), '*');
722                 string s(c, sp);
723                 string s2(t.v2, sp);
724                 s.assign(std::move(s2));
725                 BOOST_TEST(s == t.v2);
726                 BOOST_TEST(s2.empty());
727                 BOOST_TEST(
728                     *s.storage() ==
729                     *s2.storage());
730             });
731 
732             fail_loop([&](storage_ptr const& sp)
733             {
734                 std::string c(t.v2.size(), '*');
735                 string s(c, sp);
736                 string s2(t.v2, sp);
737                 s.assign(std::move(s2));
738                 BOOST_TEST(s == t.v2);
739                 BOOST_TEST(s2.empty());
740                 BOOST_TEST(
741                     *s.storage() ==
742                     *s2.storage());
743             });
744 
745             // different storage
746 
747             fail_loop([&](storage_ptr const& sp)
748             {
749                 std::string c(t.v1.size(), '*');
750                 string s(c, sp);
751                 string s2(t.v1);
752                 s.assign(std::move(s2));
753                 BOOST_TEST(s == t.v1);
754                 BOOST_TEST(s2 == t.v1);
755                 BOOST_TEST(
756                     *s.storage() !=
757                     *s2.storage());
758             });
759 
760             fail_loop([&](storage_ptr const& sp)
761             {
762                 std::string c(t.v2.size(), '*');
763                 string s(c, sp);
764                 string s2(t.v1);
765                 s.assign(std::move(s2));
766                 BOOST_TEST(s == t.v1);
767                 BOOST_TEST(s2 == t.v1);
768                 BOOST_TEST(
769                     *s.storage() !=
770                     *s2.storage());
771             });
772 
773             fail_loop([&](storage_ptr const& sp)
774             {
775                 std::string c(t.v1.size(), '*');
776                 string s(c, sp);
777                 string s2(t.v2);
778                 s.assign(std::move(s2));
779                 BOOST_TEST(s == t.v2);
780                 BOOST_TEST(s2 == t.v2);
781                 BOOST_TEST(
782                     *s.storage() !=
783                     *s2.storage());
784             });
785 
786             fail_loop([&](storage_ptr const& sp)
787             {
788                 std::string c(t.v2.size(), '*');
789                 string s(c, sp);
790                 string s2(t.v2);
791                 s.assign(std::move(s2));
792                 BOOST_TEST(s == t.v2);
793                 BOOST_TEST(s2 == t.v2);
794                 BOOST_TEST(
795                     *s.storage() !=
796                     *s2.storage());
797             });
798         }
799 
800         // assign(char const*, size_type)
801         {
802             fail_loop([&](storage_ptr const& sp)
803             {
804                 string s(t.v1.size(), '*', sp);
805                 s.assign(t.s1.c_str(), 3);
806                 BOOST_TEST(s == "abc");
807             });
808 
809             fail_loop([&](storage_ptr const& sp)
810             {
811                 string s(t.v2.size(), '*', sp);
812                 s.assign(t.s1.c_str(), 3);
813                 BOOST_TEST(s == "abc");
814             });
815 
816             fail_loop([&](storage_ptr const& sp)
817             {
818                 string s(t.v1.size(), '*', sp);
819                 s.assign(t.s2.c_str(), 3);
820                 BOOST_TEST(s == "ABC");
821             });
822 
823             fail_loop([&](storage_ptr const& sp)
824             {
825                 string s(t.v2.size(), '*', sp);
826                 s.assign(t.s2.c_str(), 3);
827                 BOOST_TEST(s == "ABC");
828             });
829         };
830 
831         // assign(char const* s)
832         {
833             fail_loop([&](storage_ptr const& sp)
834             {
835                 string s(t.v1.size(), '*', sp);
836                 s.assign(t.s1.c_str());
837                 BOOST_TEST(s == t.v1);
838             });
839 
840             fail_loop([&](storage_ptr const& sp)
841             {
842                 string s(t.v2.size(), '*', sp);
843                 s.assign(t.s1.c_str());
844                 BOOST_TEST(s == t.v1);
845             });
846 
847             fail_loop([&](storage_ptr const& sp)
848             {
849                 string s(t.v1.size(), '*', sp);
850                 s.assign(t.s2.c_str());
851                 BOOST_TEST(s == t.v2);
852             });
853 
854             fail_loop([&](storage_ptr const& sp)
855             {
856                 string s(t.v2.size(), '*', sp);
857                 s.assign(t.s2.c_str());
858                 BOOST_TEST(s == t.v2);
859             });
860         }
861 
862         // assign(InputIt, InputIt)
863         {
864             fail_loop([&](storage_ptr const& sp)
865             {
866                 string s(t.v1.size(), '*', sp);
867                 s.assign(t.s1.begin(), t.s1.end());
868                 BOOST_TEST(s == t.v1);
869             });
870 
871             fail_loop([&](storage_ptr const& sp)
872             {
873                 string s(t.v2.size(), '*', sp);
874                 s.assign(t.s1.begin(), t.s1.end());
875                 BOOST_TEST(s == t.v1);
876             });
877 
878             fail_loop([&](storage_ptr const& sp)
879             {
880                 string s(t.v1.size(), '*', sp);
881                 s.assign(
882                     make_input_iterator(t.s1.begin()),
883                     make_input_iterator(t.s1.end()));
884                 BOOST_TEST(s == t.v1);
885             });
886 
887             fail_loop([&](storage_ptr const& sp)
888             {
889                 string s(t.v2.size(), '*', sp);
890                 s.assign(
891                     make_input_iterator(t.s1.begin()),
892                     make_input_iterator(t.s1.end()));
893                 BOOST_TEST(s == t.v1);
894             });
895 
896             fail_loop([&](storage_ptr const& sp)
897             {
898                 string s(t.v1.size(), '*', sp);
899                 s.assign(t.s2.begin(), t.s2.end());
900                 BOOST_TEST(s == t.v2);
901             });
902 
903             fail_loop([&](storage_ptr const& sp)
904             {
905                 string s(t.v2.size(), '*', sp);
906                 s.assign(t.s2.begin(), t.s2.end());
907                 BOOST_TEST(s == t.v2);
908             });
909 
910             fail_loop([&](storage_ptr const& sp)
911             {
912                 string s(t.v1.size(), '*', sp);
913                 s.assign(
914                     make_input_iterator(t.s2.begin()),
915                     make_input_iterator(t.s2.end()));
916                 BOOST_TEST(s == t.v2);
917             });
918 
919             fail_loop([&](storage_ptr const& sp)
920             {
921                 string s(t.v2.size(), '*', sp);
922                 s.assign(
923                     make_input_iterator(t.s2.begin()),
924                     make_input_iterator(t.s2.end()));
925                 BOOST_TEST(s == t.v2);
926             });
927 
928             // empty range
929             {
930                 string s(t.v1);
931                 s.assign(t.s1.begin(), t.s1.begin());
932                 BOOST_TEST(s.empty());
933             }
934 
935             // empty range
936             {
937                 string s(t.v1);
938                 s.assign(
939                     make_input_iterator(t.s1.begin()),
940                     make_input_iterator(t.s1.begin()));
941                 BOOST_TEST(s.empty());
942             }
943         }
944 
945         // assign(string_view)
946         {
947             fail_loop([&](storage_ptr const& sp)
948             {
949                 string s(t.v1.size(), '*', sp);
950                 s.assign(t.v1);
951                 BOOST_TEST(s == t.v1);
952             });
953 
954             fail_loop([&](storage_ptr const& sp)
955             {
956                 string s(t.v2.size(), '*', sp);
957                 s.assign(t.v1);
958                 BOOST_TEST(s == t.v1);
959             });
960 
961             fail_loop([&](storage_ptr const& sp)
962             {
963                 string s(t.v1.size(), '*', sp);
964                 s.assign(t.v2);
965                 BOOST_TEST(s == t.v2);
966             });
967 
968             fail_loop([&](storage_ptr const& sp)
969             {
970                 string s(t.v2.size(), '*', sp);
971                 s.assign(t.v2);
972                 BOOST_TEST(s == t.v2);
973             });
974         }
975     }
976 
977     void
testElementAccess()978     testElementAccess()
979     {
980         test_vectors const t;
981 
982         string s1(t.v1);
983         string s2(t.v2);
984         auto const& cs1(s1);
985         auto const& cs2(s2);
986 
987         // at(size_type)
988         {
989             BOOST_TEST(s1.at(1) == 'b');
990             s1.at(1) = '*';
991             BOOST_TEST(s1.at(1) == '*');
992             s1.at(1) = 'b';
993             BOOST_TEST(s1.at(1) == 'b');
994 
995             BOOST_TEST(s2.at(1) == 'B');
996             s2.at(1) = '*';
997             BOOST_TEST(s2.at(1) == '*');
998             s2.at(1) = 'B';
999             BOOST_TEST(s2.at(1) == 'B');
1000 
1001             BOOST_TEST_THROWS(s1.at(s2.size()),
1002                 std::out_of_range);
1003         }
1004 
1005         // at(size_type) const
1006         {
1007             BOOST_TEST(cs1.at(1) == 'b');
1008             BOOST_TEST(cs2.at(1) == 'B');
1009 
1010             BOOST_TEST_THROWS(cs1.at(cs2.size()),
1011                 std::out_of_range);
1012         }
1013 
1014         // operator[&](size_type)
1015         {
1016             BOOST_TEST(s1[1] == 'b');
1017             s1[1] = '*';
1018             BOOST_TEST(s1[1] == '*');
1019             s1[1] = 'b';
1020             BOOST_TEST(s1[1] == 'b');
1021 
1022             BOOST_TEST(s2[1] == 'B');
1023             s2[1] = '*';
1024             BOOST_TEST(s2[1] == '*');
1025             s2[1] = 'B';
1026             BOOST_TEST(s2[1] == 'B');
1027         }
1028 
1029         // operator[&](size_type) const
1030         {
1031             BOOST_TEST(cs1[1] == 'b');
1032             BOOST_TEST(cs2[1] == 'B');
1033         }
1034 
1035         // front()
1036         {
1037             BOOST_TEST(s1.front() == 'a');
1038             s1.front() = '*';
1039             BOOST_TEST(s1.front() == '*');
1040             s1.front() = 'a';
1041             BOOST_TEST(s1.front() == 'a');
1042 
1043             BOOST_TEST(s2.front() == 'A');
1044             s2.front() = '*';
1045             BOOST_TEST(s2.front() == '*');
1046             s2.front() = 'A';
1047             BOOST_TEST(s2.front() == 'A');
1048         }
1049 
1050         // front() const
1051         {
1052             BOOST_TEST(cs1.front() == 'a');
1053             BOOST_TEST(cs2.front() == 'A');
1054         }
1055 
1056         // back()
1057         {
1058             auto const ch1 = s1.at(s1.size()-1);
1059             auto const ch2 = s2.at(s2.size()-1);
1060 
1061             BOOST_TEST(s1.back() == ch1);
1062             s1.back() = '*';
1063             BOOST_TEST(s1.back() == '*');
1064             s1.back() = ch1;
1065             BOOST_TEST(s1.back() == ch1);
1066 
1067             BOOST_TEST(s2.back() == ch2);
1068             s2.back() = '*';
1069             BOOST_TEST(s2.back() == '*');
1070             s2.back() = ch2;
1071             BOOST_TEST(s2.back() == ch2);
1072         }
1073 
1074         // back() const
1075         {
1076             auto const ch1 = s1.at(s1.size()-1);
1077             auto const ch2 = s2.at(s2.size()-1);
1078 
1079             BOOST_TEST(cs1.back() == ch1);
1080             BOOST_TEST(cs2.back() == ch2);
1081         }
1082 
1083         // data()
1084         {
1085             BOOST_TEST(
1086                 string_view(s1.data()) == t.v1);
1087             BOOST_TEST(
1088                 string_view(s2.data()) == t.v2);
1089         }
1090         // data() const
1091         {
1092             BOOST_TEST(
1093                 string_view(cs1.data()) == t.v1);
1094             BOOST_TEST(
1095                 string_view(cs2.data()) == t.v2);
1096         }
1097 
1098         // c_str()
1099         {
1100             BOOST_TEST(
1101                 string_view(cs1.c_str()) == t.v1);
1102             BOOST_TEST(
1103                 string_view(cs2.c_str()) == t.v2);
1104         }
1105 
1106         // operator string_view()
1107         {
1108             BOOST_TEST(
1109                 string_view(cs1) == t.v1);
1110             BOOST_TEST(
1111                 string_view(cs2) == t.v2);
1112         }
1113     }
1114 
1115     void
testIterators()1116     testIterators()
1117     {
1118         string s = "abc";
1119         auto const& ac(s);
1120 
1121         {
1122             auto it = s.begin();
1123             BOOST_TEST(*it == 'a'); ++it;
1124             BOOST_TEST(*it == 'b');   it++;
1125             BOOST_TEST(*it == 'c'); ++it;
1126             BOOST_TEST(it == s.end());
1127         }
1128         {
1129             auto it = s.cbegin();
1130             BOOST_TEST(*it == 'a'); ++it;
1131             BOOST_TEST(*it == 'b');   it++;
1132             BOOST_TEST(*it == 'c'); ++it;
1133             BOOST_TEST(it == s.cend());
1134         }
1135         {
1136             auto it = ac.begin();
1137             BOOST_TEST(*it == 'a'); ++it;
1138             BOOST_TEST(*it == 'b');   it++;
1139             BOOST_TEST(*it == 'c'); ++it;
1140             BOOST_TEST(it == ac.end());
1141         }
1142         {
1143             auto it = s.end();
1144             --it; BOOST_TEST(*it == 'c');
1145             it--; BOOST_TEST(*it == 'b');
1146             --it; BOOST_TEST(*it == 'a');
1147             BOOST_TEST(it == s.begin());
1148         }
1149         {
1150             auto it = s.cend();
1151             --it; BOOST_TEST(*it == 'c');
1152             it--; BOOST_TEST(*it == 'b');
1153             --it; BOOST_TEST(*it == 'a');
1154             BOOST_TEST(it == s.cbegin());
1155         }
1156         {
1157             auto it = ac.end();
1158             --it; BOOST_TEST(*it == 'c');
1159             it--; BOOST_TEST(*it == 'b');
1160             --it; BOOST_TEST(*it == 'a');
1161             BOOST_TEST(it == ac.begin());
1162         }
1163 
1164         {
1165             auto it = s.rbegin();
1166             BOOST_TEST(*it == 'c'); ++it;
1167             BOOST_TEST(*it == 'b');   it++;
1168             BOOST_TEST(*it == 'a'); ++it;
1169             BOOST_TEST(it == s.rend());
1170         }
1171         {
1172             auto it = s.crbegin();
1173             BOOST_TEST(*it == 'c'); ++it;
1174             BOOST_TEST(*it == 'b');   it++;
1175             BOOST_TEST(*it == 'a'); ++it;
1176             BOOST_TEST(it == s.crend());
1177         }
1178         {
1179             auto it = ac.rbegin();
1180             BOOST_TEST(*it == 'c'); ++it;
1181             BOOST_TEST(*it == 'b');   it++;
1182             BOOST_TEST(*it == 'a'); ++it;
1183             BOOST_TEST(it == ac.rend());
1184         }
1185         {
1186             auto it = s.rend();
1187             --it; BOOST_TEST(*it == 'a');
1188             it--; BOOST_TEST(*it == 'b');
1189             --it; BOOST_TEST(*it == 'c');
1190             BOOST_TEST(it == s.rbegin());
1191         }
1192         {
1193             auto it = s.crend();
1194             --it; BOOST_TEST(*it == 'a');
1195             it--; BOOST_TEST(*it == 'b');
1196             --it; BOOST_TEST(*it == 'c');
1197             BOOST_TEST(it == s.crbegin());
1198         }
1199         {
1200             auto it = ac.rend();
1201             --it; BOOST_TEST(*it == 'a');
1202             it--; BOOST_TEST(*it == 'b');
1203             --it; BOOST_TEST(*it == 'c');
1204             BOOST_TEST(it == ac.rbegin());
1205         }
1206 
1207         {
1208             string s2;
1209             string const& cs2(s2);
1210             BOOST_TEST(std::distance(
1211                 s2.begin(), s2.end()) == 0);
1212             BOOST_TEST(std::distance(
1213                 cs2.begin(), cs2.end()) == 0);
1214             BOOST_TEST(std::distance(
1215                 s2.rbegin(), s2.rend()) == 0);
1216             BOOST_TEST(std::distance(
1217                 cs2.rbegin(), cs2.rend()) == 0);
1218         }
1219     }
1220 
1221     void
testCapacity()1222     testCapacity()
1223     {
1224         test_vectors const t;
1225 
1226         // empty()
1227         {
1228             {
1229                 string s;
1230                 BOOST_TEST(s.empty());
1231             }
1232             {
1233                 string s = "abc";
1234                 BOOST_TEST(! s.empty());
1235             }
1236         }
1237 
1238         // size()
1239         // max_size()
1240         {
1241             string s = "abc";
1242             BOOST_TEST(s.size() == 3);
1243             BOOST_TEST(s.max_size() < string::npos);
1244         }
1245 
1246         // reserve(size_type)
1247         {
1248             fail_loop([&](storage_ptr const& sp)
1249             {
1250                 string s(sp);
1251                 s.append(t.v1);
1252                 s.append(t.v2);
1253 
1254                 s.reserve(0);
1255                 BOOST_TEST(s.size() ==
1256                     t.v1.size() + t.v2.size());
1257 
1258                 s.reserve(t.v1.size() + t.v2.size());
1259                 BOOST_TEST(s.size() ==
1260                     t.v1.size() + t.v2.size());
1261 
1262                 s.reserve(s.size() * 2);
1263                 BOOST_TEST(s.capacity() >
1264                     t.v1.size() + t.v2.size());
1265 
1266                 s.resize(t.v1.size());
1267                 s.reserve(t.v1.size());
1268                 BOOST_TEST(s == t.v1);
1269             });
1270         }
1271 
1272         // capacity()
1273         {
1274             // implied
1275         }
1276 
1277         // shrink_to_fit()
1278         fail_loop([&](storage_ptr const& sp)
1279         {
1280             string s(sp);
1281             string::size_type cap;
1282 
1283             cap = s.capacity();
1284             s.shrink_to_fit();
1285             BOOST_TEST(s.capacity() == cap);
1286 
1287             s.reserve(s.capacity() + 1);
1288             s.shrink_to_fit();
1289             BOOST_TEST(s.capacity() == cap);
1290 
1291             s.resize(cap * 3, '*');
1292             cap = s.capacity();
1293             s.resize(cap - 1);
1294             s.shrink_to_fit();
1295             BOOST_TEST(s.capacity() == cap);
1296 
1297             s.resize(cap / 2);
1298             BOOST_TEST(s.capacity() == cap);
1299 
1300             s.shrink_to_fit();
1301             BOOST_TEST(s.capacity() < cap);
1302         });
1303     }
1304 
1305     void
testClear()1306     testClear()
1307     {
1308         test_vectors const t;
1309 
1310         // clear()
1311         {
1312             {
1313                 string s(t.v1);
1314                 s.clear();
1315                 BOOST_TEST(s.empty());
1316                 BOOST_TEST(s.size() == 0);
1317                 BOOST_TEST(s.capacity() > 0);
1318             }
1319 
1320             {
1321                 string s(t.v2);
1322                 s.clear();
1323                 BOOST_TEST(s.empty());
1324                 BOOST_TEST(s.size() == 0);
1325                 BOOST_TEST(s.capacity() > 0);
1326             }
1327         }
1328     }
1329 
1330     void
testInsert()1331     testInsert()
1332     {
1333         test_vectors const t;
1334 
1335         // insert(size_type, size_type, char)
1336         {
1337             fail_loop([&](storage_ptr const& sp)
1338             {
1339                 string s(t.v1, sp);
1340                 s.insert(1, 3, '*');
1341                 BOOST_TEST(s == std::string(
1342                     t.v1).insert(1, 3, '*'));
1343             });
1344 
1345             fail_loop([&](storage_ptr const& sp)
1346             {
1347                 string s(t.v2, sp);
1348                 s.insert(1, 3, '*');
1349                 BOOST_TEST(s == std::string(
1350                     t.v2).insert(1, 3, '*'));
1351             });
1352 
1353             // pos out of range
1354             {
1355                 string s(t.v1);
1356                 BOOST_TEST_THROWS(
1357                     (s.insert(s.size() + 2, 1, '*')),
1358                     std::out_of_range);
1359             }
1360 
1361             // size > max_size
1362             {
1363                 string s(t.v1);
1364                 BOOST_TEST_THROWS(
1365                     (s.insert(1, s.max_size(), 'a')),
1366                     std::length_error);
1367             }
1368         }
1369 
1370         // insert(size_type, char const*)
1371         {
1372             fail_loop([&](storage_ptr const& sp)
1373             {
1374                 string s(t.v1, sp);
1375                 s.insert(1, "***");
1376                 BOOST_TEST(s == std::string(
1377                     t.v1).insert(1, "***"));
1378             });
1379 
1380             fail_loop([&](storage_ptr const& sp)
1381             {
1382                 string s(t.v2, sp);
1383                 s.insert(1, "***");
1384                 BOOST_TEST(s == std::string(
1385                     t.v2).insert(1, "***"));
1386             });
1387 
1388             // pos out of range
1389             {
1390                 string s(t.v1);
1391                 BOOST_TEST_THROWS(
1392                     (s.insert(s.size() + 2, "*")),
1393                     std::out_of_range);
1394             }
1395         }
1396 
1397         // insert(size_type, char const*, size_type)
1398         {
1399             fail_loop([&](storage_ptr const& sp)
1400             {
1401                 string s(t.v1, sp);
1402                 s.insert(1, "*****");
1403                 BOOST_TEST(s == std::string(
1404                     t.v1).insert(1, "*****"));
1405             });
1406 
1407             fail_loop([&](storage_ptr const& sp)
1408             {
1409                 string s(t.v2, sp);
1410                 s.insert(1, "*****");
1411                 BOOST_TEST(s == std::string(
1412                     t.v2).insert(1, "*****"));
1413             });
1414         }
1415 
1416         // insert(size_type, string const&)
1417         {
1418             fail_loop([&](storage_ptr const& sp)
1419             {
1420                 string s(t.v1, sp);
1421                 s.insert(1, string(t.v2));
1422                 BOOST_TEST(s == std::string(
1423                     t.v1).insert(1, t.s2));
1424             });
1425 
1426             fail_loop([&](storage_ptr const& sp)
1427             {
1428                 string s(t.v2, sp);
1429                 s.insert(1, string(t.v1));
1430                 BOOST_TEST(s == std::string(
1431                     t.v2).insert(1, t.s1));
1432             });
1433         }
1434 
1435         //// KRYSTIAN These tests are superseded by the new string_view overloads
1436         //// insert(size_type, string const&, size_type, size_type)
1437         //{
1438         //    fail_loop([&](storage_ptr const& sp)
1439         //    {
1440         //        string s(t.v1, sp);
1441         //        s.insert(1, string(t.v2), 1, 3);
1442         //        BOOST_TEST(s == std::string(
1443         //            t.v1).insert(1, t.s2, 1, 3));
1444         //    });
1445 
1446         //    fail_loop([&](storage_ptr const& sp)
1447         //    {
1448         //        string s(t.v2, sp);
1449         //        s.insert(1, string(t.v1), 1, 3);
1450         //        BOOST_TEST(s == std::string(
1451         //            t.v2).insert(1, t.s1, 1, 3));
1452         //    });
1453 
1454         //    fail_loop([&](storage_ptr const& sp)
1455         //    {
1456         //        string s(t.v1, sp);
1457         //        s.insert(1, string(t.v2), 1);
1458         //        BOOST_TEST(s == std::string(
1459         //            t.v1).insert(1, t.s2, 1, std::string::npos));
1460         //    });
1461 
1462         //    fail_loop([&](storage_ptr const& sp)
1463         //    {
1464         //        string s(t.v2, sp);
1465         //        s.insert(1, string(t.v1), 1);
1466         //        BOOST_TEST(s == std::string(
1467         //            t.v2).insert(1, t.s1, 1, std::string::npos));
1468         //    });
1469         //}
1470 
1471         // insert(size_type, char)
1472         {
1473             fail_loop([&](storage_ptr const& sp)
1474             {
1475                 string s(t.v1, sp);
1476                 BOOST_TEST(
1477                     s.insert(2, '*')[2] == '*');
1478             });
1479 
1480             fail_loop([&](storage_ptr const& sp)
1481             {
1482                 string s(t.v2, sp);
1483                 BOOST_TEST(
1484                     s.insert(2, '*')[2] == '*');
1485             });
1486         }
1487 
1488         // insert(const_iterator, size_type, char)
1489         {
1490             fail_loop([&](storage_ptr const& sp)
1491             {
1492                 string s(t.v1, sp);
1493                 BOOST_TEST(string_view(
1494                     &(s.insert(2, 3, '*')[2]), 5) ==
1495                         "***cd");
1496             });
1497 
1498             fail_loop([&](storage_ptr const& sp)
1499             {
1500                 string s(t.v2, sp);
1501                 BOOST_TEST(string_view(
1502                     &(s.insert(2, 3, '*')[2]), 5) ==
1503                         "***CD");
1504             });
1505         }
1506 
1507         // insert(const_iterator, InputIt, InputIt)
1508         {
1509             fail_loop([&](storage_ptr const& sp)
1510             {
1511                 string s(t.v1, sp);
1512                 s.insert(2, t.s2.begin(), t.s2.end());
1513                 std::string cs(t.s1);
1514                 cs.insert(2, &t.s2[0], t.s2.size());
1515                 BOOST_TEST(s == cs);
1516             });
1517 
1518             fail_loop([&](storage_ptr const& sp)
1519             {
1520                 string s(t.v2, sp);
1521                 s.insert(2, t.s1.begin(), t.s1.end());
1522                 std::string cs(t.s2);
1523                 cs.insert(2, &t.s1[0], t.s1.size());
1524                 BOOST_TEST(s == cs);
1525             });
1526 
1527             fail_loop([&](storage_ptr const& sp)
1528             {
1529                 string s(t.v1, sp);
1530                 s.insert(2,
1531                     make_input_iterator(t.s2.begin()),
1532                     make_input_iterator(t.s2.end()));
1533                 std::string cs(t.s1);
1534                 cs.insert(2, &t.s2[0], t.s2.size());
1535                 BOOST_TEST(s == cs);
1536             });
1537 
1538             fail_loop([&](storage_ptr const& sp)
1539             {
1540                 string s(t.v2, sp);
1541                 s.insert(2,
1542                     make_input_iterator(t.s1.begin()),
1543                     make_input_iterator(t.s1.end()));
1544                 std::string cs(t.s2);
1545                 cs.insert(2, &t.s1[0], t.s1.size());
1546                 BOOST_TEST(s == cs);
1547             });
1548         }
1549 
1550         // insert(const_iterator, string_view)
1551         {
1552             fail_loop([&](storage_ptr const& sp)
1553             {
1554                 string s(t.v1, sp);
1555                 s.insert(2, string_view(t.v2));
1556                 std::string cs(t.v1);
1557                 cs.insert(2, t.s2);
1558                 BOOST_TEST(s == cs);
1559             });
1560 
1561             fail_loop([&](storage_ptr const& sp)
1562             {
1563                 string s(t.v2, sp);
1564                 s.insert(2, string_view(t.v1));
1565                 std::string cs(t.v2);
1566                 cs.insert(2, t.s1);
1567                 BOOST_TEST(s == cs);
1568             });
1569         }
1570 
1571         // insert(const_iterator, string_view)
1572         {
1573             fail_loop([&](storage_ptr const& sp)
1574             {
1575                 string s(t.v1, sp);
1576                 s.insert(2, string_view(t.v2).substr(2, 3));
1577                 std::string cs(t.v1);
1578                 cs.insert(2, t.s2, 2, 3);
1579                 BOOST_TEST(s == cs);
1580             });
1581 
1582             fail_loop([&](storage_ptr const& sp)
1583             {
1584                 string s(t.v2, sp);
1585                 s.insert(2, string_view(t.v1).substr(2, 3));
1586                 std::string cs(t.v2);
1587                 cs.insert(2, t.s1, 2, 3);
1588                 BOOST_TEST(s == cs);
1589             });
1590         }
1591 
1592         // insert(size_type, char const*)
1593         {
1594             fail_loop([&](storage_ptr const& sp)
1595             {
1596                 string s(t.v1, sp);
1597                 s.insert(1, "***");
1598                 BOOST_TEST(s == std::string(
1599                     t.v1).insert(1, "***"));
1600             });
1601 
1602             fail_loop([&](storage_ptr const& sp)
1603             {
1604                 string s(t.v2, sp);
1605                 s.insert(1, "***");
1606                 BOOST_TEST(s == std::string(
1607                     t.v2).insert(1, "***"));
1608             });
1609 
1610             // pos out of range
1611             {
1612                 string s(t.v1);
1613                 BOOST_TEST_THROWS(
1614                     (s.insert(s.size() + 2, "*")),
1615                     std::out_of_range);
1616             }
1617         }
1618 
1619         // insert tests for when source is within destination
1620         {
1621             // start before splice point
1622             fail_loop([&](storage_ptr const& sp)
1623             {
1624                 string s(t.v1, sp);
1625                 s.reserve(s.size() + 10);
1626                 s.insert(4, s.subview(0, 3));
1627                 std::string cs(t.v1);
1628                 cs.insert(4, cs.substr(0, 3));
1629                 BOOST_TEST(s == cs);
1630             });
1631 
1632             // start after splice point
1633             fail_loop([&](storage_ptr const& sp)
1634             {
1635                 string s(t.v1, sp);
1636                 s.reserve(s.size() + 10);
1637                 s.insert(0, s.subview(3, 3));
1638                 std::string cs(t.v1);
1639                 cs.insert(0, cs.substr(3, 3));
1640                 BOOST_TEST(s == cs);
1641             });
1642 
1643             // insert pos bisects the inserted string
1644             fail_loop([&](storage_ptr const& sp)
1645             {
1646                 string s(t.v1, sp);
1647                 s.reserve(s.size() + 10);
1648                 s.insert(2, s.subview(0, 5));
1649                 std::string cs(t.v1);
1650                 cs.insert(2, cs.substr(0, 5));
1651                 BOOST_TEST(s == cs);
1652             });
1653         }
1654 
1655         // insert reallocation test
1656         {
1657             fail_loop([&](storage_ptr const& sp)
1658             {
1659               string s(t.v2, sp);
1660               std::string cs(t.v2);
1661               const auto view = t.v2.substr(0, 4);
1662               s.append(s);
1663               cs.append(cs);
1664               s.insert(2, view);
1665               cs.insert(2, view.data(), view.size());
1666               BOOST_TEST(s == cs);
1667             });
1668         }
1669     }
1670 
1671     void
testErase()1672     testErase()
1673     {
1674         test_vectors const t;
1675 
1676         // erase(size_type, size_type)
1677         {
1678             {
1679                 string s(t.v1);
1680                 s.erase(1, 3);
1681                 BOOST_TEST(s ==
1682                     std::string(t.v1).erase(1, 3));
1683             }
1684 
1685             {
1686                 string s(t.v2);
1687                 s.erase(1, 3);
1688                 BOOST_TEST(s ==
1689                     std::string(t.v2).erase(1, 3));
1690             }
1691 
1692             {
1693                 string s(t.v1);
1694                 s.erase(3);
1695                 BOOST_TEST(s ==
1696                     std::string(t.v1).erase(3));
1697             }
1698 
1699             {
1700                 string s(t.v2);
1701                 s.erase(3);
1702                 BOOST_TEST(s ==
1703                     std::string(t.v2).erase(3));
1704             }
1705 
1706             {
1707                 string s(t.v1);
1708                 s.erase();
1709                 BOOST_TEST(s ==
1710                     std::string(t.v1).erase());
1711             }
1712 
1713             {
1714                 string s(t.v2);
1715                 s.erase();
1716                 BOOST_TEST(s ==
1717                     std::string(t.v2).erase());
1718             }
1719 
1720             {
1721                 string s(t.v1);
1722                 BOOST_TEST_THROWS(
1723                     (s.erase(t.v1.size() + 1, 1)),
1724                     std::out_of_range);
1725             }
1726         }
1727 
1728         // iterator erase(const_iterator)
1729         {
1730             {
1731                 string s(t.v1);
1732                 std::string s2(t.v1);
1733                 s.erase(s.begin() + 3);
1734                 s2.erase(s2.begin() + 3);
1735                 BOOST_TEST(s == s2);
1736             }
1737 
1738             {
1739                 string s(t.v2);
1740                 std::string s2(t.v2);
1741                 s.erase(s.begin() + 3);
1742                 s2.erase(s2.begin() + 3);
1743                 BOOST_TEST(s == s2);
1744             }
1745         }
1746 
1747         // iterator erase(const_iterator, const_iterator)
1748         {
1749             string s(t.v1);
1750             std::string s2(t.v1);
1751             s.erase(s.begin() + 1, s.begin() + 3);
1752             s2.erase(s2.begin() + 1, s2.begin() + 3);
1753             BOOST_TEST(s == s2);
1754         }
1755     }
1756 
1757     void
testPushPop()1758     testPushPop()
1759     {
1760         test_vectors const t;
1761 
1762         // push_back(char)
1763         {
1764             fail_loop([&](storage_ptr const& sp)
1765             {
1766                 string s(sp);
1767                 for(auto ch : t.v1)
1768                     s.push_back(ch);
1769                 BOOST_TEST(s == t.v1);
1770             });
1771 
1772             fail_loop([&](storage_ptr const& sp)
1773             {
1774                 string s(sp);
1775                 for(auto ch : t.v2)
1776                     s.push_back(ch);
1777                 BOOST_TEST(s == t.v2);
1778             });
1779         }
1780 
1781         // pop_back(char)
1782         {
1783             {
1784                 string s(t.v1);
1785                 while(! s.empty())
1786                     s.pop_back();
1787                 BOOST_TEST(s.empty());
1788                 BOOST_TEST(s.capacity() > 0);
1789             }
1790 
1791             {
1792                 string s(t.v2);
1793                 while(! s.empty())
1794                     s.pop_back();
1795                 BOOST_TEST(s.empty());
1796                 BOOST_TEST(s.capacity() > 0);
1797             }
1798         }
1799     }
1800 
1801     void
testAppend()1802     testAppend()
1803     {
1804         test_vectors const t;
1805 
1806         // append(size_type, char)
1807         {
1808             fail_loop([&](storage_ptr const& sp)
1809             {
1810                 string s(t.v1, sp);
1811                 s.append(t.v2.size(), '*');
1812                 BOOST_TEST(s == t.s1 +
1813                     std::string(t.v2.size(), '*'));
1814             });
1815 
1816             fail_loop([&](storage_ptr const& sp)
1817             {
1818                 string s(t.v2, sp);
1819                 s.append(t.v1.size(), '*');
1820                 BOOST_TEST(s == t.s2 +
1821                     std::string(t.v1.size(), '*'));
1822             });
1823         }
1824 
1825         // append(string_view)
1826         {
1827             fail_loop([&](storage_ptr const& sp)
1828             {
1829                 string s(t.v1, sp);
1830                 s.append(string(t.v2));
1831                 BOOST_TEST(s == t.s1 + t.s2);
1832             });
1833 
1834             fail_loop([&](storage_ptr const& sp)
1835             {
1836                 string s(t.v2, sp);
1837                 s.append(string(t.v1));
1838                 BOOST_TEST(s == t.s2 + t.s1);
1839             });
1840         }
1841 
1842         // append(string_view)
1843         {
1844             fail_loop([&](storage_ptr const& sp)
1845             {
1846                 string s(t.v1, sp);
1847                 s.append(string(t.v2).subview(3));
1848                 BOOST_TEST(s == t.s1 + t.s2.substr(3));
1849             });
1850 
1851             fail_loop([&](storage_ptr const& sp)
1852             {
1853                 string s(t.v2, sp);
1854                 s.append(string(t.v1).subview(3));
1855                 BOOST_TEST(s == t.s2 + t.s1.substr(3));
1856             });
1857 
1858             fail_loop([&](storage_ptr const& sp)
1859             {
1860                 string s(t.v1, sp);
1861                 s.append(string(t.v2).subview(2, 3));
1862                 BOOST_TEST(s == t.s1 + t.s2.substr(2, 3));
1863             });
1864 
1865             fail_loop([&](storage_ptr const& sp)
1866             {
1867                 string s(t.v2, sp);
1868                 s.append(string(t.v1).subview(2, 3));
1869                 BOOST_TEST(s == t.s2 + t.s1.substr(2, 3));
1870             });
1871         }
1872 
1873         // append(char const*)
1874         {
1875             fail_loop([&](storage_ptr const& sp)
1876             {
1877                 string s(t.v1, sp);
1878                 s.append(t.s2.c_str());
1879                 BOOST_TEST(s == t.s1 + t.s2);
1880             });
1881 
1882             fail_loop([&](storage_ptr const& sp)
1883             {
1884                 string s(t.v2, sp);
1885                 s.append(t.s1.c_str());
1886                 BOOST_TEST(s == t.s2 + t.s1);
1887             });
1888         }
1889 
1890         // append(InputIt, InputIt)
1891         {
1892             fail_loop([&](storage_ptr const& sp)
1893             {
1894                 string s(t.v1, sp);
1895                 s.append(t.s2.begin(), t.s2.end());
1896                 BOOST_TEST(s == t.s1 + t.s2);
1897             });
1898 
1899             fail_loop([&](storage_ptr const& sp)
1900             {
1901                 string s(t.v2, sp);
1902                 s.append(t.s1.begin(), t.s1.end());
1903                 BOOST_TEST(s == t.s2 + t.s1);
1904             });
1905 
1906             // Fails on Visual Studio 2017 C++2a Strict
1907             fail_loop([&](storage_ptr const& sp)
1908             {
1909                 string s(t.v1, sp);
1910                 s.append(
1911                     make_input_iterator(t.s2.begin()),
1912                     make_input_iterator(t.s2.end()));
1913                 BOOST_TEST(s == t.s1 + t.s2);
1914             });
1915 
1916             fail_loop([&](storage_ptr const& sp)
1917             {
1918                 string s(t.v2, sp);
1919                 s.append(
1920                     make_input_iterator(t.s1.begin()),
1921                     make_input_iterator(t.s1.end()));
1922                 BOOST_TEST(s == t.s2 + t.s1);
1923             });
1924         }
1925 
1926         // append(string_view)
1927         {
1928             fail_loop([&](storage_ptr const& sp)
1929             {
1930                 string s(t.v1, sp);
1931                 s.append(t.v2);
1932                 BOOST_TEST(s == t.s1 + t.s2);
1933             });
1934 
1935             fail_loop([&](storage_ptr const& sp)
1936             {
1937                 string s(t.v2, sp);
1938                 s.append(t.v1);
1939                 BOOST_TEST(s == t.s2 + t.s1);
1940             });
1941         }
1942 
1943         // append(string_view)
1944         {
1945             fail_loop([&](storage_ptr const& sp)
1946             {
1947                 string s(t.v1, sp);
1948                 s.append(t.v2.substr(2));
1949                 BOOST_TEST(s == t.s1 + t.s2.substr(2));
1950             });
1951 
1952             fail_loop([&](storage_ptr const& sp)
1953             {
1954                 string s(t.v2, sp);
1955                 s.append(t.v1.substr(2));
1956                 BOOST_TEST(s == t.s2 + t.s1.substr(2));
1957             });
1958 
1959             fail_loop([&](storage_ptr const& sp)
1960             {
1961                 string s(t.v1, sp);
1962                 s.append(t.v2.substr(2, 3));
1963                 BOOST_TEST(s == t.s1 + t.s2.substr(2, 3));
1964             });
1965 
1966             fail_loop([&](storage_ptr const& sp)
1967             {
1968                 string s(t.v2, sp);
1969                 s.append(t.v1.substr(2, 3));
1970                 BOOST_TEST(s == t.s2 + t.s1.substr(2, 3));
1971             });
1972         }
1973     }
1974 
1975     void
testPlusEquals()1976     testPlusEquals()
1977     {
1978         test_vectors const t;
1979 
1980         // operator+=(string)
1981         {
1982             fail_loop([&](storage_ptr const& sp)
1983             {
1984                 string s(t.v1, sp);
1985                 s += string(t.v2);
1986                 BOOST_TEST(s == t.s1 + t.s2);
1987             });
1988 
1989             fail_loop([&](storage_ptr const& sp)
1990             {
1991                 string s(t.v2, sp);
1992                 s += string(t.v1);
1993                 BOOST_TEST(s == t.s2 + t.s1);
1994             });
1995         }
1996 
1997         // operator+=(char)
1998         {
1999             fail_loop([&](storage_ptr const& sp)
2000             {
2001                 string s(sp);
2002                 for(auto ch : t.v1)
2003                     s += ch;
2004                 BOOST_TEST(s == t.v1);
2005             });
2006 
2007             fail_loop([&](storage_ptr const& sp)
2008             {
2009                 string s(sp);
2010                 for(auto ch : t.v2)
2011                     s += ch;
2012                 BOOST_TEST(s == t.v2);
2013             });
2014         }
2015 
2016         // operator+=(char const*)
2017         {
2018             fail_loop([&](storage_ptr const& sp)
2019             {
2020                 string s(t.v1, sp);
2021                 s += t.s2.c_str();
2022                 BOOST_TEST(s == t.s1 + t.s2);
2023             });
2024 
2025             fail_loop([&](storage_ptr const& sp)
2026             {
2027                 string s(t.v2, sp);
2028                 s += t.s1.c_str();
2029                 BOOST_TEST(s == t.s2 + t.s1);
2030             });
2031         }
2032 
2033         // operator+=(string_view)
2034         {
2035             fail_loop([&](storage_ptr const& sp)
2036             {
2037                 string s(t.v1, sp);
2038                 s += t.v2;
2039                 BOOST_TEST(s == t.s1 + t.s2);
2040             });
2041 
2042             fail_loop([&](storage_ptr const& sp)
2043             {
2044                 string s(t.v2, sp);
2045                 s += t.v1;
2046                 BOOST_TEST(s == t.s2 + t.s1);
2047             });
2048         }
2049     }
2050 
2051     void
testCompare()2052     testCompare()
2053     {
2054         test_vectors const t;
2055         string const v1 = t.v1;
2056 
2057         // compare(string)
2058         BOOST_TEST(v1.compare(string("aaaaaaa")) > 0);
2059         BOOST_TEST(v1.compare(string(t.v1)) == 0);
2060         BOOST_TEST(v1.compare(string("bbbbbbb")) < 0);
2061 
2062         // compare(char const*)
2063         BOOST_TEST(v1.compare("aaaaaaa") > 0);
2064         BOOST_TEST(v1.compare(t.s1.c_str()) == 0);
2065         BOOST_TEST(v1.compare("bbbbbbb") < 0);
2066 
2067         // compare(string_view s)
2068         BOOST_TEST(v1.compare(string_view("aaaaaaa")) > 0);
2069         BOOST_TEST(v1.compare(t.v1) == 0);
2070         BOOST_TEST(v1.compare(string_view("bbbbbbb")) < 0);
2071     }
2072 
2073     void
testStartEndsWith()2074     testStartEndsWith()
2075     {
2076         test_vectors const t;
2077         string const v1 = t.v1;
2078         string const v2 = t.v2;
2079 
2080         // starts_with(string_view)
2081         {
2082             BOOST_TEST(v1.starts_with(string_view("abc")));
2083             BOOST_TEST(v2.starts_with(string_view("ABC")));
2084             BOOST_TEST(! v1.starts_with(string_view("xyz")));
2085             BOOST_TEST(! v2.starts_with(string_view("XYZ")));
2086         }
2087 
2088         // starts_with(char)
2089         {
2090             BOOST_TEST(v1.starts_with('a'));
2091             BOOST_TEST(v2.starts_with('A'));
2092             BOOST_TEST(! v1.starts_with('x'));
2093             BOOST_TEST(! v2.starts_with('X'));
2094         }
2095 
2096         // starts_with(char const*)
2097         {
2098             BOOST_TEST(v1.starts_with("abc"));
2099             BOOST_TEST(v2.starts_with("ABC"));
2100             BOOST_TEST(! v1.starts_with("xyz"));
2101             BOOST_TEST(! v2.starts_with("XYZ"));
2102         }
2103 
2104         // ends_with(string_view)
2105         {
2106             BOOST_TEST(v1.ends_with(last_of(t.s1,3)));
2107             BOOST_TEST(v2.ends_with(last_of(t.s2,3)));
2108             BOOST_TEST(! v1.ends_with(string_view("abc")));
2109             BOOST_TEST(! v2.ends_with(string_view("ABC")));
2110         }
2111 
2112         // ends_with(char)
2113         {
2114             BOOST_TEST(v1.ends_with(last_of(t.s1, 1)[0]));
2115             BOOST_TEST(v2.ends_with(last_of(t.s2, 1)[0]));
2116             BOOST_TEST(! v1.ends_with('a'));
2117             BOOST_TEST(! v2.ends_with('A'));
2118         }
2119 
2120         // ends_with(char const*)
2121         {
2122             BOOST_TEST(v1.ends_with(last_of(t.s1, 3).data()));
2123             BOOST_TEST(v2.ends_with(last_of(t.s2, 3).data()));
2124             BOOST_TEST(! v1.ends_with("abc"));
2125             BOOST_TEST(! v2.ends_with("ABC"));
2126         }
2127     }
2128 
2129     void
testReplace()2130     testReplace()
2131     {
2132         test_vectors const t;
2133 
2134         // replace(std::size_t, std::size_t, string_view)
2135         {
2136             // pos out of range
2137             fail_loop([&](storage_ptr const& sp)
2138             {
2139                 string s(t.v2, sp);
2140                 BOOST_TEST_THROWS(s.replace(s.size() + 1, 1, t.v2),
2141                     std::out_of_range);
2142             });
2143 
2144             // outside, shrink
2145             fail_loop([&](storage_ptr const& sp)
2146             {
2147                 std::string s1(t.v2.data(), t.v2.size());
2148                 string s2(t.v2, sp);
2149                 BOOST_TEST(s2.replace(0, 4, t.v2.substr(4, 2)) ==
2150                            s1.replace(0, 4, t.v2.data() + 4, 2));
2151             });
2152 
2153             // outside, grow
2154             fail_loop([&](storage_ptr const& sp)
2155             {
2156                 std::string s1(t.v2.data(), t.v2.size());
2157                 string s2(t.v2, sp);
2158                 BOOST_TEST(s2.replace(0, 1, t.v2.substr(0)) ==
2159                            s1.replace(0, 1, t.v2.data(), t.v2.size()));
2160             });
2161 
2162             // outside, grow, reallocate
2163             fail_loop([&](storage_ptr const& sp)
2164             {
2165                 std::string s1(t.v2.data(), t.v2.size());
2166                 string s2(t.v2, sp);
2167                 s1.append(s1);
2168                 s2.append(s2);
2169                 BOOST_TEST(s2.replace(0, 1, t.v2.substr(0)) ==
2170                            s1.replace(0, 1, t.v2.data(), t.v2.size()));
2171             });
2172 
2173             // outside, same
2174             fail_loop([&](storage_ptr const& sp)
2175             {
2176                 std::string s1(t.v2.data(), t.v2.size());
2177                 string s2(t.v2, sp);
2178                 BOOST_TEST(s2.replace(0, 2, t.v2.substr(0, 2)) ==
2179                            s1.replace(0, 2, t.v2.data(), 2));
2180             });
2181 
2182             // replace tests for full coverage
2183 
2184             // inside, no effect
2185             fail_loop([&](storage_ptr const& sp)
2186             {
2187                 std::string s1(t.v2.data(), t.v2.size());
2188                 string s2(t.v2, sp);
2189                 BOOST_TEST(s2.replace(0, 4, s2.subview(0, 4)) ==
2190                            s1.replace(0, 4, s1.data() + 0, 4));
2191             });
2192 
2193             // inside, shrink, split
2194             fail_loop([&](storage_ptr const& sp)
2195             {
2196                 std::string s1(t.v2.data(), t.v2.size());
2197                 string s2(t.v2, sp);
2198                 BOOST_TEST(s2.replace(1, 4, s2.subview(4, 2)) ==
2199                            s1.replace(1, 4, s1.data() + 4, 2));
2200             });
2201 
2202             // inside, grow no reallocate, split
2203             fail_loop([&](storage_ptr const& sp)
2204             {
2205                 std::string s1(t.v2.data(), t.v2.size());
2206                 string s2(t.v2, sp);
2207                 BOOST_TEST(s2.replace(1, 1, s2.subview(0)) ==
2208                            s1.replace(1, 1, s1.data(), s1.size()));
2209             });
2210 
2211             // inside, reallocate, split
2212             fail_loop([&](storage_ptr const& sp)
2213             {
2214                 std::string s1(t.v2.data(), t.v2.size());
2215                 string s2(t.v2, sp);
2216                 s1.append(s1);
2217                 s2.append(s2);
2218                 BOOST_TEST(s2.replace(1, 1, s2.subview(0)) ==
2219                            s1.replace(1, 1, s1.data(), s1.size()));
2220             });
2221 
2222             // inside, same, split
2223             fail_loop([&](storage_ptr const& sp)
2224             {
2225                 std::string s1(t.v2.data(), t.v2.size());
2226                 string s2(t.v2, sp);
2227                 BOOST_TEST(s2.replace(1, 2, s2.subview(0, 2)) ==
2228                            s1.replace(1, 2, s1.data(), 2));
2229             });
2230         }
2231 
2232         // replace(const_iterator, const_iterator, string_view)
2233         {
2234             // outside, shrink
2235             fail_loop([&](storage_ptr const& sp)
2236             {
2237                 std::string s1(t.v2.data(), t.v2.size());
2238                 string s2(t.v2, sp);
2239                 BOOST_TEST(
2240                   s2.replace(
2241                       s2.begin(),
2242                       s2.begin() + 4,
2243                       t.v2.substr(4, 2)) ==
2244                   s1.replace(0,
2245                       4, t.v2.data() + 4,
2246                       2));
2247             });
2248 
2249             // outside, grow
2250             fail_loop([&](storage_ptr const& sp)
2251             {
2252                 std::string s1(t.v2.data(), t.v2.size());
2253                 string s2(t.v2, sp);
2254                 BOOST_TEST(
2255                     s2.replace(
2256                         s2.begin(),
2257                         s2.begin() + 1,
2258                         t.v2.substr(0)) ==
2259                     s1.replace(0,
2260                         1, t.v2.data(),
2261                         t.v2.size()));
2262             });
2263 
2264             // outside, same
2265             fail_loop([&](storage_ptr const& sp)
2266             {
2267                 std::string s1(t.v2.data(), t.v2.size());
2268                 string s2(t.v2, sp);
2269                 BOOST_TEST(
2270                     s2.replace(
2271                         s2.begin(),
2272                         s2.begin() + 2,
2273                         t.v2.substr(0, 2)) ==
2274                     s1.replace(
2275                         0, 2,
2276                         t.v2.data(),
2277                         2));
2278             });
2279 
2280             // inside, shrink
2281             fail_loop([&](storage_ptr const& sp)
2282             {
2283                 std::string s1(t.v2.data(), t.v2.size());
2284                 string s2(t.v2, sp);
2285                 BOOST_TEST(
2286                     s2.replace(
2287                         s2.begin() + 1,
2288                         s2.begin() + 5,
2289                         s2.subview(4, 2)) ==
2290                     s1.replace(
2291                         1, 4,
2292                         s1.data() + 4,
2293                         2));
2294             });
2295 
2296             // inside, grow
2297             fail_loop([&](storage_ptr const& sp)
2298             {
2299                 std::string s1(t.v2.data(), t.v2.size());
2300                 string s2(t.v2, sp);
2301                 BOOST_TEST(
2302                     s2.replace(
2303                         s2.begin() + 1,
2304                         s2.begin() + 2,
2305                         s2.subview(0)) ==
2306                     s1.replace(
2307                         1, 1,
2308                         s1.data(),
2309                         s1.size()));
2310             });
2311 
2312             // inside, same
2313             fail_loop([&](storage_ptr const& sp)
2314             {
2315                 std::string s1(t.v2.data(), t.v2.size());
2316                 string s2(t.v2, sp);
2317                 BOOST_TEST(
2318                     s2.replace(
2319                         s2.begin() + 1,
2320                         s2.begin() + 3,
2321                         s2.subview(0, 2)) ==
2322                     s1.replace(
2323                         1, 2,
2324                         s1.data(),
2325                         2));
2326             });
2327         }
2328 
2329         // replace(std::size_t, std::size_t, std::size_t, char)
2330         {
2331             // grow, no realloc
2332             fail_loop([&](storage_ptr const& sp)
2333             {
2334                 std::string s1(t.v2.data(), t.v2.size());
2335                 string s2(t.v2, sp);
2336                 BOOST_TEST(s2.replace(0, 4, 10, 'a') ==
2337                            s1.replace(0, 4, 10, 'a'));
2338             });
2339 
2340             // grow, realloc
2341             fail_loop([&](storage_ptr const& sp)
2342             {
2343                 std::string s1(t.v2.data(), t.v2.size());
2344                 string s2(t.v2, sp);
2345                 const auto grow = (std::max)(s1.capacity(), s2.capacity());
2346                 BOOST_TEST(s2.replace(0, 4, grow, 'a') ==
2347                            s1.replace(0, 4, grow, 'a'));
2348             });
2349 
2350             // no change in size
2351             fail_loop([&](storage_ptr const& sp)
2352             {
2353                 std::string s1(t.v2.data(), t.v2.size());
2354                 string s2(t.v2, sp);
2355                 BOOST_TEST(s2.replace(0, 1, 1, 'a') ==
2356                            s1.replace(0, 1, 1, 'a'));
2357             });
2358 
2359             // pos out of range
2360             fail_loop([&](storage_ptr const& sp)
2361             {
2362                 string s(t.v2, sp);
2363                 BOOST_TEST_THROWS(s.replace(s.size() + 1, 1, 1, 'a'),
2364                     std::out_of_range);
2365             });
2366         }
2367 
2368         // replace(const_iterator, const_iterator, std::size_t, char)
2369         {
2370             fail_loop([&](storage_ptr const& sp)
2371             {
2372                 std::string s1(t.v2.data(), t.v2.size());
2373                 string s2(t.v2, sp);
2374                 BOOST_TEST(
2375                   s2.replace(s2.begin(), s2.begin() + 4, 10, 'a') ==
2376                   s1.replace(0, 4, 10, 'a'));
2377             });
2378         }
2379     }
2380 
2381     void
testSubStr()2382     testSubStr()
2383     {
2384         test_vectors const t;
2385         string const s1 = t.v1;
2386         string const s2 = t.v2;
2387 
2388         // subview(size_type, size_type)
2389         BOOST_TEST(s1.subview() == t.v1);
2390         BOOST_TEST(s1.subview(1) == t.v1.substr(1));
2391         BOOST_TEST(s1.subview(1, 3) == t.v1.substr(1, 3));
2392         BOOST_TEST(s2.subview() == t.v2);
2393         BOOST_TEST(s2.subview(1) == t.v2.substr(1));
2394         BOOST_TEST(s2.subview(1, 3) == t.v2.substr(1, 3));
2395     }
2396 
2397     void
testCopy()2398     testCopy()
2399     {
2400         test_vectors const t;
2401 
2402         // copy(char*, count, pos)
2403         {
2404             {
2405                 string s(t.v1);
2406                 std::string d;
2407                 d.resize(s.size());
2408                 s.copy(&d[0], d.size(), 0);
2409                 BOOST_TEST(d == t.v1);
2410             }
2411 
2412             {
2413                 string s(t.v1);
2414                 std::string d;
2415                 d.resize(s.size());
2416                 s.copy(&d[0], d.size());
2417                 BOOST_TEST(d == t.v1);
2418             }
2419         }
2420     }
2421 
2422     void
testResize()2423     testResize()
2424     {
2425         test_vectors const t;
2426 
2427         // resize(size_type)
2428         {
2429             fail_loop([&](storage_ptr const& sp)
2430             {
2431                 string s(sp);
2432                 s.resize(t.v1.size());
2433                 BOOST_TEST(s.size() == t.v1.size());
2434                 BOOST_TEST(s == string(t.v1.size(), '\0'));
2435             });
2436 
2437             fail_loop([&](storage_ptr const& sp)
2438             {
2439                 string s(sp);
2440                 s.resize(t.v2.size());
2441                 BOOST_TEST(s.size() == t.v2.size());
2442                 BOOST_TEST(s == string(t.v2.size(), '\0'));
2443             });
2444 
2445             fail_loop([&](storage_ptr const& sp)
2446             {
2447                 string s(sp);
2448                 s.resize(t.v1.size());
2449                 s.resize(t.v2.size());
2450                 BOOST_TEST(s == string(t.v2.size(), '\0'));
2451                 s.resize(t.v1.size());
2452                 BOOST_TEST(s == string(t.v1.size(), '\0'));
2453             });
2454         }
2455 
2456         // resize(size_type, char)
2457         {
2458             fail_loop([&](storage_ptr const& sp)
2459             {
2460                 string s(sp);
2461                 s.resize(t.v1.size(), '*');
2462                 BOOST_TEST(s.size() == t.v1.size());
2463                 BOOST_TEST(s == string(t.v1.size(), '*'));
2464             });
2465 
2466             fail_loop([&](storage_ptr const& sp)
2467             {
2468                 string s(sp);
2469                 s.resize(t.v2.size(), '*');
2470                 BOOST_TEST(s.size() == t.v2.size());
2471                 BOOST_TEST(s == string(t.v2.size(), '*'));
2472             });
2473 
2474             fail_loop([&](storage_ptr const& sp)
2475             {
2476                 string s(sp);
2477                 s.resize(t.v1.size(), '*');
2478                 s.resize(t.v2.size(), '*');
2479                 BOOST_TEST(s == string(t.v2.size(), '*'));
2480                 s.resize(t.v1.size());
2481                 BOOST_TEST(s == string(t.v1.size(), '*'));
2482             });
2483         }
2484     }
2485 
2486     void
testSwap()2487     testSwap()
2488     {
2489         test_vectors const t;
2490 
2491         // swap
2492         {
2493             fail_loop([&](storage_ptr const& sp)
2494             {
2495                 string s1(t.v1, sp);
2496                 string s2(t.v2, sp);
2497                 s1.swap(s2);
2498                 BOOST_TEST(s1 == t.v2);
2499                 BOOST_TEST(s2 == t.v1);
2500             });
2501 
2502             fail_loop([&](storage_ptr const& sp)
2503             {
2504                 string s1(t.v1, sp);
2505                 string s2(t.v2, sp);
2506                 swap(s1, s2);
2507                 BOOST_TEST(s1 == t.v2);
2508                 BOOST_TEST(s2 == t.v1);
2509             });
2510 
2511             fail_loop([&](storage_ptr const& sp)
2512             {
2513                 string s1(t.v1);
2514                 string s2(t.v2, sp);
2515                 s1.swap(s2);
2516                 BOOST_TEST(s1 == t.v2);
2517                 BOOST_TEST(s2 == t.v1);
2518             });
2519         }
2520     }
2521 
2522     void
testFind()2523     testFind()
2524     {
2525         test_vectors const t;
2526         string const s1 = t.v1;
2527 
2528         // find(string_view, size_type)
2529         BOOST_TEST(s1.find("bcd") == 1);
2530         BOOST_TEST(s1.find("cde") == 2);
2531 
2532         BOOST_TEST(s1.find("bcd", 0) == 1);
2533         BOOST_TEST(s1.find("cde", 1) == 2);
2534         BOOST_TEST(s1.find("efg", 5) == string::npos);
2535 
2536         // find(char, size_type)
2537         BOOST_TEST(s1.find('b') == 1);
2538         BOOST_TEST(s1.find('c', 1) == 2);
2539         BOOST_TEST(s1.find('e', 5) == string::npos);
2540     }
2541 
2542     void
testRfind()2543     testRfind()
2544     {
2545         test_vectors const t;
2546         string const s1 = t.v1;
2547 
2548         // rfind(string_view, size_type)
2549         BOOST_TEST(s1.rfind("bcd") == 1);
2550         BOOST_TEST(s1.rfind("cde") == 2);
2551 
2552         BOOST_TEST(s1.rfind("bcd", 1) == 1);
2553         BOOST_TEST(s1.rfind("cde", 2) == 2);
2554         BOOST_TEST(s1.rfind("efg", 3) == string::npos);
2555 
2556         // rfind(char, size_type)
2557         BOOST_TEST(s1.rfind('b') == 1);
2558         BOOST_TEST(s1.rfind('c', 2) == 2);
2559         BOOST_TEST(s1.rfind('e', 3) == string::npos);
2560     }
2561 
2562     void
testFindFirstOf()2563     testFindFirstOf()
2564     {
2565         test_vectors const t;
2566         string const s1 = t.v1;
2567 
2568         // find_first_of(string_view, size_type)
2569         BOOST_TEST(s1.find_first_of("bcd") == 1);
2570         BOOST_TEST(s1.find_first_of("cde") == 2);
2571 
2572         BOOST_TEST(s1.find_first_of("bcd", 0) == 1);
2573         BOOST_TEST(s1.find_first_of("cde", 1) == 2);
2574         BOOST_TEST(s1.find_first_of("efg", 7) == string::npos);
2575     }
2576 
2577     void
testFindFirstNotOf()2578     testFindFirstNotOf()
2579     {
2580         test_vectors const t;
2581         string const s1 = t.v1;
2582 
2583         // find_first_not_of(string_view, size_type)
2584         BOOST_TEST(s1.find_first_not_of("abc") == 3);
2585         BOOST_TEST(s1.find_first_not_of("cde") == 0);
2586 
2587         BOOST_TEST(s1.find_first_not_of("bcd", 0) == 0);
2588         BOOST_TEST(s1.find_first_not_of("cde", 2) == 5);
2589 
2590         // find_first_not_of(char, size_type)
2591         BOOST_TEST(s1.find_first_not_of('b') == 0);
2592         BOOST_TEST(s1.find_first_not_of('a', 0) == 1);
2593         BOOST_TEST(s1.find_first_not_of('e', 4) == 5);
2594     }
2595 
2596     void
testFindLastOf()2597     testFindLastOf()
2598     {
2599         test_vectors const t;
2600         string const s1 = t.v1;
2601 
2602         // find_last_of(string_view, size_type)
2603         BOOST_TEST(s1.find_last_of("bcd") == 3);
2604         BOOST_TEST(s1.find_last_of("cde") == 4);
2605 
2606         BOOST_TEST(s1.find_last_of("bcd", 3) == 3);
2607         BOOST_TEST(s1.find_last_of("cde", 5) == 4);
2608         BOOST_TEST(s1.find_last_of("efg", 3) == string::npos);
2609     }
2610 
2611     void
testFindLastNotOf()2612     testFindLastNotOf()
2613     {
2614         test_vectors const t;
2615         string const s1 = t.v1;
2616 
2617         // find_last_not_of(string_view, size_type)
2618         BOOST_TEST(s1.find_last_not_of("abc", 3) == 3);
2619         BOOST_TEST(s1.find_last_not_of("bcd", 3) == 0);
2620 
2621         BOOST_TEST(s1.find_last_not_of("efg", 4) == 3);
2622         BOOST_TEST(s1.find_last_not_of("abc", 2) == string::npos);
2623 
2624         // find_first_not_of(char, size_type)
2625         BOOST_TEST(s1.find_last_not_of('a', 3) == 3);
2626         BOOST_TEST(s1.find_last_not_of('e', 4) == 3);
2627         BOOST_TEST(s1.find_last_not_of('a', 0) == string::npos);
2628     }
2629 
2630     void
testNonMembers()2631     testNonMembers()
2632     {
2633         test_vectors const t;
2634         string const s1(t.v1);
2635         string const s2(t.v2);
2636         auto const v1(t.v1);
2637         auto const v2(t.v2);
2638         auto const c1 = t.s1.c_str();
2639         auto const c2 = t.s2.c_str();
2640 
2641         BOOST_TEST(! operator< (s1, s2));
2642         BOOST_TEST(! operator< (s1, v2));
2643         BOOST_TEST(! operator< (s1, c2));
2644         BOOST_TEST(! operator<=(s1, s2));
2645         BOOST_TEST(! operator<=(s1, v2));
2646         BOOST_TEST(! operator<=(s1, c2));
2647         BOOST_TEST(! operator==(s1, s2));
2648         BOOST_TEST(! operator==(s1, v2));
2649         BOOST_TEST(! operator==(s1, c2));
2650         BOOST_TEST(  operator!=(s1, s2));
2651         BOOST_TEST(  operator!=(s1, v2));
2652         BOOST_TEST(  operator!=(s1, c2));
2653         BOOST_TEST(  operator>=(s1, s2));
2654         BOOST_TEST(  operator>=(s1, v2));
2655         BOOST_TEST(  operator>=(s1, c2));
2656         BOOST_TEST(  operator> (s1, s2));
2657         BOOST_TEST(  operator> (s1, v2));
2658         BOOST_TEST(  operator> (s1, c2));
2659 
2660         BOOST_TEST(  operator< (s2, s1));
2661         BOOST_TEST(  operator< (s2, v1));
2662         BOOST_TEST(  operator< (s2, c1));
2663         BOOST_TEST(  operator<=(s2, s1));
2664         BOOST_TEST(  operator<=(s2, v1));
2665         BOOST_TEST(  operator<=(s2, c1));
2666         BOOST_TEST(  operator!=(s2, s1));
2667         BOOST_TEST(  operator!=(s2, v1));
2668         BOOST_TEST(  operator!=(s2, c1));
2669         BOOST_TEST(! operator==(s2, s1));
2670         BOOST_TEST(! operator==(s2, v1));
2671         BOOST_TEST(! operator==(s2, c1));
2672         BOOST_TEST(! operator>=(s2, s1));
2673         BOOST_TEST(! operator>=(s2, v1));
2674         BOOST_TEST(! operator>=(s2, c1));
2675         BOOST_TEST(! operator> (s2, s1));
2676         BOOST_TEST(! operator> (s2, v1));
2677         BOOST_TEST(! operator> (s2, c1));
2678 
2679         BOOST_TEST(  operator< (s2, s1));
2680         BOOST_TEST(  operator< (v2, s1));
2681         BOOST_TEST(  operator< (c2, s1));
2682         BOOST_TEST(  operator<=(s2, s1));
2683         BOOST_TEST(  operator<=(v2, s1));
2684         BOOST_TEST(  operator<=(c2, s1));
2685         BOOST_TEST(  operator!=(s2, s1));
2686         BOOST_TEST(  operator!=(v2, s1));
2687         BOOST_TEST(  operator!=(c2, s1));
2688         BOOST_TEST(! operator==(s2, s1));
2689         BOOST_TEST(! operator==(v2, s1));
2690         BOOST_TEST(! operator==(c2, s1));
2691         BOOST_TEST(! operator>=(s2, s1));
2692         BOOST_TEST(! operator>=(v2, s1));
2693         BOOST_TEST(! operator>=(c2, s1));
2694         BOOST_TEST(! operator> (s2, s1));
2695         BOOST_TEST(! operator> (v2, s1));
2696         BOOST_TEST(! operator> (c2, s1));
2697 
2698         BOOST_TEST(! operator< (s1, s2));
2699         BOOST_TEST(! operator< (v1, s2));
2700         BOOST_TEST(! operator< (c1, s2));
2701         BOOST_TEST(! operator<=(s1, s2));
2702         BOOST_TEST(! operator<=(v1, s2));
2703         BOOST_TEST(! operator<=(c1, s2));
2704         BOOST_TEST(! operator==(s1, s2));
2705         BOOST_TEST(! operator==(v1, s2));
2706         BOOST_TEST(! operator==(c1, s2));
2707         BOOST_TEST(  operator!=(s1, s2));
2708         BOOST_TEST(  operator!=(v1, s2));
2709         BOOST_TEST(  operator!=(c1, s2));
2710         BOOST_TEST(  operator>=(s1, s2));
2711         BOOST_TEST(  operator>=(v1, s2));
2712         BOOST_TEST(  operator>=(c1, s2));
2713         BOOST_TEST(  operator> (s1, s2));
2714         BOOST_TEST(  operator> (v1, s2));
2715         BOOST_TEST(  operator> (c1, s2));
2716     }
2717 
2718     void
testHash()2719     testHash()
2720     {
2721         // libstdc++ 4.8 bug
2722 #if !defined(__GNUC__) || (__GNUC__ > 4 || \
2723     (__GNUC__ == 4 && __GNUC_MINOR__ > 8))
2724         {
2725             std::unordered_set<string> us;
2726             us.emplace("first");
2727             us.emplace("second");
2728         }
2729         {
2730             std::unordered_set<string>(
2731                 0,
2732                 std::hash<string>(32));
2733         }
2734 #endif
2735         {
2736             std::hash<string> h1(32);
2737             std::hash<string> h2(h1);
2738             std::hash<string> h3(59);
2739             h1 = h3;
2740             h2 = h3;
2741             (void)h2;
2742         }
2743     }
2744 
2745     void
run()2746     run()
2747     {
2748         testConstruction();
2749         testAssignment();
2750         testAssign();
2751         testElementAccess();
2752         testIterators();
2753         testCapacity();
2754 
2755         testClear();
2756         testInsert();
2757         testErase();
2758         testPushPop();
2759         testAppend();
2760         testPlusEquals();
2761         testCompare();
2762         testStartEndsWith();
2763         testReplace();
2764         testSubStr();
2765         testCopy();
2766         testResize();
2767         testSwap();
2768 
2769         testFind();
2770         testRfind();
2771         testFindFirstOf();
2772         testFindFirstNotOf();
2773         testFindLastOf();
2774         testFindLastNotOf();
2775 
2776         testNonMembers();
2777 
2778         testHash();
2779     }
2780 };
2781 
2782 TEST_SUITE(string_test, "boost.json.string");
2783 
2784 BOOST_JSON_NS_END
2785