1 /*
2  *  Copyright (c) 2016, Facebook, Inc.
3  *  All rights reserved.
4  *
5  *  This source code is licensed under the BSD-style license found in the
6  *  LICENSE file in the root directory of this source tree. An additional grant
7  *  of patent rights can be found in the PATENTS file in the same directory.
8  */
9 
10 #include <fatal/string/rope.h>
11 
12 #include <fatal/test/driver.h>
13 
14 #include <fatal/math/numerics.h>
15 #include <fatal/utility/timed_iterations.h>
16 
17 #include <sstream>
18 #include <string>
19 #include <utility>
20 
21 namespace fatal {
22 
23 #define TEST_IMPL_SINGLE_STRING(Fn) \
24   Fn(""); \
25   Fn('1'); \
26   Fn("1"); \
27   Fn(std::string("1")); \
28   Fn("12"); \
29   Fn(std::string("12")); \
30   Fn("123"); \
31   Fn(std::string("123")); \
32   Fn("hello, world! with some extra strings"); \
33   Fn(std::string("hello, world! with some extra strings")); \
34   Fn( \
35     std::string("hello"), ", ", std::string("world"), '!', " with", \
36     ' ', std::string("some"), " extra", " ", 's', std::string("trings") \
37   ) \
38 
39 //////////////////
40 // sanity_check //
41 //////////////////
42 
FATAL_TEST(sanity_check,sanity_check)43 FATAL_TEST(sanity_check, sanity_check) {
44   std::string const world("world");
45   std::string extra(" extra");
46 
47   rope<> s(
48     std::string("hello"), ", ", world, '!',
49     " with", ' ', std::string("some"), extra, " ", 's', std::string("trings")
50   );
51 
52   std::string const expected("hello, world! with some extra strings");
53 
54   FATAL_EXPECT_EQ(expected, s);
55 
56   auto const r = s.to_string();
57   FATAL_EXPECT_EQ(expected, r);
58 
59   std::ostringstream ss;
60   ss << s;
61   FATAL_EXPECT_EQ(expected, ss.str());
62 
63   rope<> unitary;
64   unitary.append(expected);
65 
66   auto const u = unitary.to_string();
67 
68   FATAL_EXPECT_EQ(expected, u);
69   FATAL_EXPECT_EQ(r, u);
70 
71   FATAL_EXPECT_EQ(expected, unitary);
72   FATAL_EXPECT_EQ(s, unitary);
73   FATAL_EXPECT_EQ(unitary, s);
74 
75   rope<>::hasher hasher;
76 
77   auto const hr1 = hasher(s);
78   auto const hu1 = hasher(unitary);
79   auto const hr2 = rope<>::hasher()(s);
80   auto const hu2 = rope<>::hasher()(unitary);
81 
82   FATAL_EXPECT_EQ(hr1, hr2);
83   FATAL_EXPECT_EQ(hu1, hu2);
84 
85   FATAL_EXPECT_EQ(hr1, hu1);
86 }
87 
88 //////////
89 // size //
90 //////////
91 
FATAL_TEST(sanity_check,size)92 FATAL_TEST(sanity_check, size) {
93   rope<> r;
94   FATAL_EXPECT_EQ(0, r.size());
95 
96   r.push_back('0');
97   FATAL_EXPECT_EQ(1, r.size());
98 
99   r.append("12");
100   FATAL_EXPECT_EQ(3, r.size());
101 
102   r.append(std::string("456"));
103   FATAL_EXPECT_EQ(6, r.size());
104 
105   r.clear();
106   FATAL_EXPECT_EQ(0, r.size());
107 }
108 
109 ///////////
110 // empty //
111 ///////////
112 
FATAL_TEST(sanity_check,empty)113 FATAL_TEST(sanity_check, empty) {
114   rope<> r;
115   FATAL_EXPECT_TRUE(r.empty());
116 
117   r.push_back('0');
118   FATAL_EXPECT_FALSE(r.empty());
119 
120   r.clear();
121   FATAL_EXPECT_TRUE(r.empty());
122 
123   r.append("12");
124   FATAL_EXPECT_FALSE(r.empty());
125 
126   r.clear();
127   FATAL_EXPECT_TRUE(r.empty());
128 
129   r.append(std::string("456"));
130   FATAL_EXPECT_FALSE(r.empty());
131 
132   r.clear();
133   FATAL_EXPECT_TRUE(r.empty());
134 }
135 
136 ////////////////
137 // comparison //
138 ////////////////
139 
FATAL_TEST(comparison,equal)140 FATAL_TEST(comparison, equal) {
141 # define TEST_IMPL_COMPARE(r, other) \
142   do { \
143     FATAL_EXPECT_EQ(0, r.compare(other)); \
144     \
145     FATAL_EXPECT_TRUE(r == other); \
146     FATAL_EXPECT_TRUE(other == r); \
147     \
148     FATAL_EXPECT_FALSE(r != other); \
149     FATAL_EXPECT_FALSE(other != r); \
150     \
151     FATAL_EXPECT_FALSE(r < other); \
152     FATAL_EXPECT_FALSE(other < r); \
153     \
154     FATAL_EXPECT_TRUE(r <= other); \
155     FATAL_EXPECT_TRUE(other <= r); \
156     \
157     FATAL_EXPECT_FALSE(r > other); \
158     FATAL_EXPECT_FALSE(other > r); \
159     \
160     FATAL_EXPECT_TRUE(r >= other); \
161     FATAL_EXPECT_TRUE(other >= r); \
162   } while (false)
163 
164 # define TEST_IMPL(...) \
165   do { \
166     auto const str = to_string(__VA_ARGS__); \
167     \
168     { \
169       rope<> r1(__VA_ARGS__); \
170       auto cr1 = r1.mimic(); \
171       rope<> r2(__VA_ARGS__); \
172       auto cr2 = r2.mimic(); \
173       string_view ref(str); \
174       auto cstr = str.c_str(); \
175       std::vector<char> v(str.cbegin(), str.cend()); \
176       v.push_back('\0'); \
177       auto c = v.data(); \
178       std::string s(str); \
179       \
180       TEST_IMPL_COMPARE(r1, r1); \
181       TEST_IMPL_COMPARE(cr1, r1); \
182       TEST_IMPL_COMPARE(r1, cr1); \
183       TEST_IMPL_COMPARE(r1, r2); \
184       TEST_IMPL_COMPARE(cr1, r2); \
185       TEST_IMPL_COMPARE(r1, cr2); \
186       TEST_IMPL_COMPARE(r1, ref); \
187       TEST_IMPL_COMPARE(r1, cstr); \
188       TEST_IMPL_COMPARE(r1, c); \
189       TEST_IMPL_COMPARE(r1, s); \
190       TEST_IMPL_COMPARE(cr1, ref); \
191       TEST_IMPL_COMPARE(cr1, cstr); \
192       TEST_IMPL_COMPARE(cr1, c); \
193       TEST_IMPL_COMPARE(cr1, s); \
194     } \
195     { \
196       rope<> const r1(__VA_ARGS__); \
197       auto const cr1 = r1.mimic(); \
198       rope<> const r2(__VA_ARGS__); \
199       auto const cr2 = r2.mimic(); \
200       string_view const ref(str); \
201       auto const cstr = str.c_str(); \
202       std::vector<char> v(str.cbegin(), str.cend()); \
203       v.push_back('\0'); \
204       auto const c = v.data(); \
205       std::string const s(str); \
206       \
207       TEST_IMPL_COMPARE(r1, r1); \
208       TEST_IMPL_COMPARE(cr1, r1); \
209       TEST_IMPL_COMPARE(r1, cr1); \
210       TEST_IMPL_COMPARE(r1, r2); \
211       TEST_IMPL_COMPARE(cr1, r2); \
212       TEST_IMPL_COMPARE(r1, cr2); \
213       TEST_IMPL_COMPARE(r1, ref); \
214       TEST_IMPL_COMPARE(r1, cstr); \
215       TEST_IMPL_COMPARE(r1, c); \
216       TEST_IMPL_COMPARE(r1, s); \
217       TEST_IMPL_COMPARE(cr1, ref); \
218       TEST_IMPL_COMPARE(cr1, cstr); \
219       TEST_IMPL_COMPARE(cr1, c); \
220       TEST_IMPL_COMPARE(cr1, s); \
221     } \
222     { \
223       rope<> r1(__VA_ARGS__); \
224       auto cr1 = r1.mimic(); \
225       rope<> r2(__VA_ARGS__); \
226       auto cr2 = r2.mimic(); \
227       string_view ref(str); \
228       auto cstr = str.c_str(); \
229       std::vector<char> v(str.cbegin(), str.cend()); \
230       v.push_back('\0'); \
231       auto c = v.data(); \
232       std::string s(str); \
233       \
234       TEST_IMPL_COMPARE(std::move(r1), std::move(r1)); \
235       TEST_IMPL_COMPARE(std::move(cr1), std::move(r1)); \
236       TEST_IMPL_COMPARE(std::move(r1), std::move(cr1)); \
237       TEST_IMPL_COMPARE(std::move(r1), std::move(r2)); \
238       TEST_IMPL_COMPARE(std::move(cr1), std::move(r2)); \
239       TEST_IMPL_COMPARE(std::move(r1), std::move(cr2)); \
240       TEST_IMPL_COMPARE(std::move(r1), std::move(ref)); \
241       TEST_IMPL_COMPARE(std::move(r1), std::move(cstr)); \
242       TEST_IMPL_COMPARE(std::move(r1), std::move(c)); \
243       TEST_IMPL_COMPARE(std::move(r1), std::move(s)); \
244       TEST_IMPL_COMPARE(std::move(cr1), std::move(ref)); \
245       TEST_IMPL_COMPARE(std::move(cr1), std::move(cstr)); \
246       TEST_IMPL_COMPARE(std::move(cr1), std::move(c)); \
247       TEST_IMPL_COMPARE(std::move(cr1), std::move(s)); \
248     } \
249     { \
250       rope<> r1(__VA_ARGS__); \
251       auto cr1 = r1.mimic(); \
252       std::vector<char> v(str.cbegin(), str.cend()); \
253       v.push_back('\0'); \
254       \
255       TEST_IMPL_COMPARE(r1, rope<>(__VA_ARGS__)); \
256       TEST_IMPL_COMPARE(cr1, rope<>(__VA_ARGS__)); \
257       TEST_IMPL_COMPARE(r1, rope<>(__VA_ARGS__).mimic()); \
258       TEST_IMPL_COMPARE(cr1, rope<>(__VA_ARGS__).mimic()); \
259       TEST_IMPL_COMPARE(r1, string_view(str)); \
260       TEST_IMPL_COMPARE(r1, str.c_str()); \
261       TEST_IMPL_COMPARE(r1, v.data()); \
262       TEST_IMPL_COMPARE(r1, std::string(str)); \
263       TEST_IMPL_COMPARE(cr1, string_view(str)); \
264       TEST_IMPL_COMPARE(cr1, str.c_str()); \
265       TEST_IMPL_COMPARE(cr1, v.data()); \
266       TEST_IMPL_COMPARE(cr1, std::string(str)); \
267     } \
268   } while (false)
269 
270   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
271 
272 # undef TEST_IMPL
273 # undef TEST_IMPL_COMPARE
274 }
275 
FATAL_TEST(comparison,not_equal)276 FATAL_TEST(comparison, not_equal) {
277 # define TEST_IMPL_COMPARE(r, other, expected_less) \
278   do { \
279     if (expected_less) { \
280       FATAL_EXPECT_LT(r.compare(other), 0); \
281     } else { \
282       FATAL_EXPECT_GT(r.compare(other), 0); \
283     } \
284     \
285     FATAL_EXPECT_FALSE(r == other); \
286     FATAL_EXPECT_FALSE(other == r); \
287     \
288     FATAL_EXPECT_TRUE(r != other); \
289     FATAL_EXPECT_TRUE(other != r); \
290     \
291     FATAL_EXPECT_EQ(expected_less, r < other); \
292     FATAL_EXPECT_NE(expected_less, other < r); \
293     \
294     FATAL_EXPECT_EQ(expected_less, r <= other); \
295     FATAL_EXPECT_NE(expected_less, other <= r); \
296     \
297     FATAL_EXPECT_NE(expected_less, r > other); \
298     FATAL_EXPECT_EQ(expected_less, other > r); \
299     \
300     FATAL_EXPECT_NE(expected_less, r >= other); \
301     FATAL_EXPECT_EQ(expected_less, other >= r); \
302   } while (false)
303 
304   std::vector<rope<>> v;
305   TEST_IMPL_SINGLE_STRING(v.emplace_back);
306 
307   for (auto l = v.size(); l--; ) {
308     for (auto r = v.size(); r--; ) {
309       auto ls = v[l].to_string();
310       auto rs = v[r].to_string();
311 
312       if (l == r || ls == rs) {
313         continue;
314       }
315 
316       // TODO: ADD MIMICS
317       auto test = [](
318         rope<> &lhs,
319         rope<> &rhs,
320         bool expected_less
321       ) {
322         auto const lstr = lhs.to_string();
323         auto const rstr = rhs.to_string();
324         {
325           auto &r1 = lhs;
326           auto &r2 = rhs;
327           string_view ref(rstr);
328           auto cstr = rstr.c_str();
329           std::vector<char> vc(rstr.cbegin(), rstr.cend());
330           vc.push_back('\0');
331           auto c = vc.data();
332           std::string s(rstr);
333 
334           TEST_IMPL_COMPARE(r1, r2, expected_less);
335           TEST_IMPL_COMPARE(r1, ref, expected_less);
336           TEST_IMPL_COMPARE(r1, cstr, expected_less);
337           TEST_IMPL_COMPARE(r1, c, expected_less);
338           TEST_IMPL_COMPARE(r1, s, expected_less);
339         }
340         {
341           auto const &r1 = lhs;
342           auto const &r2 = rhs;
343           string_view const ref(rstr);
344           auto const cstr = rstr.c_str();
345           std::vector<char> vc(rstr.cbegin(), rstr.cend());
346           vc.push_back('\0');
347           auto const c = vc.data();
348           std::string const s(rstr);
349 
350           TEST_IMPL_COMPARE(r1, r2, expected_less);
351           TEST_IMPL_COMPARE(r1, ref, expected_less);
352           TEST_IMPL_COMPARE(r1, cstr, expected_less);
353           TEST_IMPL_COMPARE(r1, c, expected_less);
354           TEST_IMPL_COMPARE(r1, s, expected_less);
355         }
356         {
357           auto &r1 = lhs;
358           auto &r2 = rhs;
359           string_view ref(rstr);
360           auto cstr = rstr.c_str();
361           std::vector<char> vc(rstr.cbegin(), rstr.cend());
362           vc.push_back('\0');
363           auto c = vc.data();
364           std::string s(rstr);
365 
366           TEST_IMPL_COMPARE(std::move(r1), std::move(r2), expected_less);
367           TEST_IMPL_COMPARE(std::move(r1), std::move(ref), expected_less);
368           TEST_IMPL_COMPARE(std::move(r1), std::move(cstr), expected_less);
369           TEST_IMPL_COMPARE(std::move(r1), std::move(c), expected_less);
370           TEST_IMPL_COMPARE(std::move(r1), std::move(s), expected_less);
371         }
372         {
373           auto &r1 = lhs;
374           std::vector<char> vc(rstr.cbegin(), rstr.cend());
375           vc.push_back('\0');
376 
377           TEST_IMPL_COMPARE(r1, string_view(rstr), expected_less);
378           TEST_IMPL_COMPARE(r1, rstr.c_str(), expected_less);
379           TEST_IMPL_COMPARE(r1, vc.data(), expected_less);
380           TEST_IMPL_COMPARE(r1, std::string(rstr), expected_less);
381         }
382 
383         FATAL_ASSERT_EQ(lhs, lstr);
384         FATAL_ASSERT_EQ(rhs, rstr);
385       };
386 
387       test(v[l], v[r], ls < rs);
388       test(v[r], v[l], rs < ls);
389     }
390   }
391 
392 # undef TEST_IMPL_COMPARE
393 }
394 
395 ///////////////
396 // push_back //
397 ///////////////
398 
FATAL_TEST(push_back,char)399 FATAL_TEST(push_back, char) {
400   rope<> r;
401   FATAL_EXPECT_TRUE(r.empty());
402   FATAL_EXPECT_EQ("", r);
403 
404   r.push_back('1');
405   FATAL_EXPECT_FALSE(r.empty());
406   FATAL_EXPECT_EQ("1", r);
407 
408   char space = ' ';
409   r.push_back(space);
410   FATAL_EXPECT_FALSE(r.empty());
411   FATAL_EXPECT_EQ("1 ", r);
412 
413   char two = '2';
414   r.push_back(std::move(two));
415   FATAL_EXPECT_FALSE(r.empty());
416   FATAL_EXPECT_EQ("1 2", r);
417 
418   r.push_back(char(' '));
419   FATAL_EXPECT_FALSE(r.empty());
420   FATAL_EXPECT_EQ("1 2 ", r);
421 
422   char const three = '3';
423   r.push_back(three);
424   FATAL_EXPECT_FALSE(r.empty());
425   FATAL_EXPECT_EQ("1 2 3", r);
426 
427   auto end = "!";
428   r.push_back(end[0]);
429   FATAL_EXPECT_FALSE(r.empty());
430   FATAL_EXPECT_EQ("1 2 3!", r);
431 }
432 
433 ////////////
434 // append //
435 ////////////
436 
FATAL_TEST(append,append)437 FATAL_TEST(append, append) {
438   rope<> r;
439   FATAL_EXPECT_TRUE(r.empty());
440   FATAL_EXPECT_EQ("", r);
441   FATAL_EXPECT_EQ(0, r.pieces());
442 
443   r.append("");
444   FATAL_EXPECT_TRUE(r.empty());
445   FATAL_EXPECT_EQ("", r);
446   FATAL_EXPECT_EQ(0, r.pieces());
447 
448   r.append("one");
449   FATAL_EXPECT_FALSE(r.empty());
450   FATAL_EXPECT_EQ("one", r);
451   FATAL_EXPECT_EQ(1, r.pieces());
452 
453   r.append(' ');
454   FATAL_EXPECT_FALSE(r.empty());
455   FATAL_EXPECT_EQ("one ", r);
456   FATAL_EXPECT_EQ(2, r.pieces());
457 
458   r.append(std::string("two"));
459   FATAL_EXPECT_FALSE(r.empty());
460   FATAL_EXPECT_EQ("one two", r);
461   FATAL_EXPECT_EQ(3, r.pieces());
462 
463   r.append(string_view(" "));
464   FATAL_EXPECT_FALSE(r.empty());
465   FATAL_EXPECT_EQ("one two ", r);
466   FATAL_EXPECT_EQ(4, r.pieces());
467 
468   std::string three("three");
469   r.append(three);
470   FATAL_EXPECT_FALSE(r.empty());
471   FATAL_EXPECT_EQ("one two three", r);
472   FATAL_EXPECT_EQ(5, r.pieces());
473 
474   std::string f(" f");
475   r.append(std::move(f));
476   FATAL_EXPECT_FALSE(r.empty());
477   FATAL_EXPECT_EQ("one two three f", r);
478   FATAL_EXPECT_EQ(6, r.pieces());
479 
480   std::string const o("o");
481   r.append(o);
482   FATAL_EXPECT_FALSE(r.empty());
483   FATAL_EXPECT_EQ("one two three fo", r);
484   FATAL_EXPECT_EQ(7, r.pieces());
485 
486   string_view const ur("ur");
487   r.append(ur);
488   FATAL_EXPECT_FALSE(r.empty());
489   FATAL_EXPECT_EQ("one two three four", r);
490   FATAL_EXPECT_EQ(8, r.pieces());
491 
492   string_view end("!");
493   r.append(end);
494   FATAL_EXPECT_FALSE(r.empty());
495   FATAL_EXPECT_EQ("one two three four!", r);
496   FATAL_EXPECT_EQ(9, r.pieces());
497 }
498 
499 //////////////////
500 // multi_append //
501 //////////////////
502 
FATAL_TEST(multi_append,none)503 FATAL_TEST(multi_append, none) {
504   rope<> r;
505 
506   FATAL_EXPECT_TRUE(r.empty());
507   FATAL_EXPECT_EQ("", r);
508   FATAL_EXPECT_EQ(0, r.pieces());
509 
510   r.multi_append();
511   FATAL_EXPECT_TRUE(r.empty());
512   FATAL_EXPECT_EQ("", r);
513   FATAL_EXPECT_EQ(0, r.pieces());
514 
515   r.multi_append("");
516   FATAL_EXPECT_TRUE(r.empty());
517   FATAL_EXPECT_EQ("", r);
518   FATAL_EXPECT_EQ(0, r.pieces());
519 }
520 
FATAL_TEST(multi_append,one)521 FATAL_TEST(multi_append, one) {
522   rope<> r;
523   FATAL_EXPECT_TRUE(r.empty());
524   FATAL_EXPECT_EQ("", r);
525   FATAL_EXPECT_EQ(0, r.pieces());
526 
527   r.multi_append("one");
528   FATAL_EXPECT_FALSE(r.empty());
529   FATAL_EXPECT_EQ("one", r);
530   FATAL_EXPECT_EQ(1, r.pieces());
531 
532   r.multi_append(' ');
533   FATAL_EXPECT_FALSE(r.empty());
534   FATAL_EXPECT_EQ("one ", r);
535   FATAL_EXPECT_EQ(2, r.pieces());
536 
537   r.multi_append(std::string("two"));
538   FATAL_EXPECT_FALSE(r.empty());
539   FATAL_EXPECT_EQ("one two", r);
540   FATAL_EXPECT_EQ(3, r.pieces());
541 
542   r.multi_append(string_view(" "));
543   FATAL_EXPECT_FALSE(r.empty());
544   FATAL_EXPECT_EQ("one two ", r);
545   FATAL_EXPECT_EQ(4, r.pieces());
546 
547   std::string three("three");
548   r.multi_append(three);
549   FATAL_EXPECT_FALSE(r.empty());
550   FATAL_EXPECT_EQ("one two three", r);
551   FATAL_EXPECT_EQ(5, r.pieces());
552 
553   std::string f(" f");
554   r.multi_append(std::move(f));
555   FATAL_EXPECT_FALSE(r.empty());
556   FATAL_EXPECT_EQ("one two three f", r);
557   FATAL_EXPECT_EQ(6, r.pieces());
558 
559   std::string const o("o");
560   r.multi_append(o);
561   FATAL_EXPECT_FALSE(r.empty());
562   FATAL_EXPECT_EQ("one two three fo", r);
563   FATAL_EXPECT_EQ(7, r.pieces());
564 
565   string_view const ur("ur");
566   r.multi_append(ur);
567   FATAL_EXPECT_FALSE(r.empty());
568   FATAL_EXPECT_EQ("one two three four", r);
569   FATAL_EXPECT_EQ(8, r.pieces());
570 
571   string_view end("!");
572   r.multi_append(end);
573   FATAL_EXPECT_FALSE(r.empty());
574   FATAL_EXPECT_EQ("one two three four!", r);
575   FATAL_EXPECT_EQ(9, r.pieces());
576 }
577 
FATAL_TEST(multi_append,two)578 FATAL_TEST(multi_append, two) {
579   rope<> r;
580   FATAL_EXPECT_TRUE(r.empty());
581   FATAL_EXPECT_EQ("", r);
582   FATAL_EXPECT_EQ(0, r.pieces());
583 
584   r.multi_append("one", ' ');
585   FATAL_EXPECT_FALSE(r.empty());
586   FATAL_EXPECT_EQ("one ", r);
587   FATAL_EXPECT_EQ(2, r.pieces());
588 
589   r.multi_append(std::string("two"), string_view(" "));
590   FATAL_EXPECT_FALSE(r.empty());
591   FATAL_EXPECT_EQ("one two ", r);
592   FATAL_EXPECT_EQ(4, r.pieces());
593 
594   std::string three("three");
595   string_view space(" ");
596   r.multi_append(three, space);
597   FATAL_EXPECT_FALSE(r.empty());
598   FATAL_EXPECT_EQ("one two three ", r);
599   FATAL_EXPECT_EQ(6, r.pieces());
600 
601   std::string f("f");
602   std::string const o("o");
603   r.multi_append(std::move(f), o);
604   FATAL_EXPECT_FALSE(r.empty());
605   FATAL_EXPECT_EQ("one two three fo", r);
606   FATAL_EXPECT_EQ(8, r.pieces());
607 
608   string_view const ur("ur");
609   string_view end("!");
610   r.multi_append(ur, end);
611   FATAL_EXPECT_FALSE(r.empty());
612   FATAL_EXPECT_EQ("one two three four!", r);
613   FATAL_EXPECT_EQ(10, r.pieces());
614 }
615 
FATAL_TEST(multi_append,three)616 FATAL_TEST(multi_append, three) {
617   rope<> r;
618   FATAL_EXPECT_TRUE(r.empty());
619   FATAL_EXPECT_EQ("", r);
620   FATAL_EXPECT_EQ(0, r.pieces());
621 
622   r.multi_append("one", ' ', std::string("two"));
623   FATAL_EXPECT_FALSE(r.empty());
624   FATAL_EXPECT_EQ("one two", r);
625   FATAL_EXPECT_EQ(3, r.pieces());
626 
627   std::string three("three");
628   std::string f(" f");
629 
630   r.multi_append(string_view(" "), three, std::move(f));
631   FATAL_EXPECT_FALSE(r.empty());
632   FATAL_EXPECT_EQ("one two three f", r);
633   FATAL_EXPECT_EQ(6, r.pieces());
634 
635   std::string const o("o");
636   string_view const ur("ur");
637   string_view end("!");
638 
639   r.multi_append(o, ur, end);
640   FATAL_EXPECT_FALSE(r.empty());
641   FATAL_EXPECT_EQ("one two three four!", r);
642   FATAL_EXPECT_EQ(9, r.pieces());
643 }
644 
FATAL_TEST(multi_append,many)645 FATAL_TEST(multi_append, many) {
646   rope<> r;
647   FATAL_EXPECT_TRUE(r.empty());
648   FATAL_EXPECT_EQ("", r);
649   FATAL_EXPECT_EQ(0, r.pieces());
650 
651   r.multi_append("one", ' ', std::string("two"), string_view(" "));
652   FATAL_EXPECT_FALSE(r.empty());
653   FATAL_EXPECT_EQ("one two ", r);
654   FATAL_EXPECT_EQ(4, r.pieces());
655 
656   std::string three("three");
657   std::string const ou("ou");
658   string_view end("!");
659 
660   r.multi_append(three, " ", 'f', ou, std::string("r"), end);
661   FATAL_EXPECT_FALSE(r.empty());
662   FATAL_EXPECT_EQ("one two three four!", r);
663   FATAL_EXPECT_EQ(10, r.pieces());
664 }
665 
666 ////////////
667 // concat //
668 ////////////
669 
FATAL_TEST(concat,empty)670 FATAL_TEST(concat, empty) {
671   rope<> r;
672   FATAL_EXPECT_TRUE(r.empty());
673 
674   rope<> other;
675   r.concat(other);
676   FATAL_EXPECT_TRUE(r.empty());
677 
678   r.concat(rope<>());
679   FATAL_EXPECT_TRUE(r.empty());
680 
681   r.concat(r);
682   FATAL_EXPECT_TRUE(r.empty());
683 }
684 
FATAL_TEST(concat,one_piece)685 FATAL_TEST(concat, one_piece) {
686   rope<> r;
687   FATAL_EXPECT_TRUE(r.empty());
688 
689   std::string const s1("hello");
690   rope<> r1((std::string(s1)));
691   FATAL_EXPECT_FALSE(r1.empty());
692   r.concat(std::move(r1));
693   FATAL_EXPECT_TRUE(r1.empty());
694   FATAL_EXPECT_EQ(s1, r.to_string());
695   FATAL_EXPECT_EQ(s1, r);
696 
697   std::string const s2(", ");
698   rope<> r2(s2);
699   r.concat(r2);
700   FATAL_EXPECT_EQ(s1 + s2, r.to_string());
701   FATAL_EXPECT_EQ(s1 + s2, r);
702 
703   std::string const s3("world");
704   r.concat(rope<>(s3));
705   FATAL_EXPECT_EQ(s1 + s2 + s3, r.to_string());
706   FATAL_EXPECT_EQ(s1 + s2 + s3, r);
707 
708   std::string const s4("!");
709   rope<> const r4(s4);
710   r.concat(r4);
711   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4, r.to_string());
712   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4, r);
713 
714   std::string const s5(" test");
715   rope<> const r5(s5);
716   r.concat(r5);
717   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5, r.to_string());
718   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5, r);
719 
720   std::string const s6(" string");
721   rope<> const r6(s6);
722   r.concat(r6);
723   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5 + s6, r.to_string());
724   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5 + s6, r);
725 
726   r.concat(r);
727   FATAL_EXPECT_EQ(
728     s1 + s2 + s3 + s4 + s5 + s6
729       + s1 + s2 + s3 + s4 + s5 + s6,
730     r.to_string()
731   );
732   FATAL_EXPECT_EQ(
733     s1 + s2 + s3 + s4 + s5 + s6
734       + s1 + s2 + s3 + s4 + s5 + s6,
735     r
736   );
737 
738   FATAL_EXPECT_THROW(std::invalid_argument) { r.concat(std::move(r)); };
739 }
740 
FATAL_TEST(concat,two_pieces)741 FATAL_TEST(concat, two_pieces) {
742   rope<> r;
743   FATAL_EXPECT_TRUE(r.empty());
744 
745   std::string const s1("hello");
746   std::string const s2(", ");
747 
748   rope<> r1(std::string(s1), s2);
749   FATAL_EXPECT_FALSE(r1.empty());
750   r.concat(std::move(r1));
751   FATAL_EXPECT_TRUE(r1.empty());
752   FATAL_EXPECT_EQ(s1 + s2, r.to_string());
753   FATAL_EXPECT_EQ(s1 + s2, r);
754 
755   std::string const s3("world");
756   std::string const s4("!");
757 
758   rope<> const r2(s3, s4);
759   r.concat(r2);
760   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4, r.to_string());
761   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4, r);
762 
763   std::string const s5(" test");
764   std::string const s6(" string");
765 
766   rope<> const r3(s5, s6);
767   r.concat(r3);
768   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5 + s6, r.to_string());
769   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5 + s6, r);
770 
771   r.concat(r);
772   FATAL_EXPECT_EQ(
773     s1 + s2 + s3 + s4 + s5 + s6
774       + s1 + s2 + s3 + s4 + s5 + s6,
775     r.to_string()
776   );
777   FATAL_EXPECT_EQ(
778     s1 + s2 + s3 + s4 + s5 + s6
779       + s1 + s2 + s3 + s4 + s5 + s6,
780     r
781   );
782 
783   FATAL_EXPECT_THROW(std::invalid_argument) { r.concat(std::move(r)); };
784 }
785 
FATAL_TEST(concat,three_pieces)786 FATAL_TEST(concat, three_pieces) {
787   rope<> r;
788   FATAL_EXPECT_TRUE(r.empty());
789 
790   std::string const s1("hello");
791   std::string const s2(", ");
792   std::string const s3("world");
793 
794   rope<> r1(std::string(s1), s2, s3);
795   FATAL_EXPECT_FALSE(r1.empty());
796   r.concat(std::move(r1));
797   FATAL_EXPECT_TRUE(r1.empty());
798   FATAL_EXPECT_EQ(s1 + s2 + s3, r.to_string());
799   FATAL_EXPECT_EQ(s1 + s2 + s3, r);
800 
801   std::string const s4("!");
802   std::string const s5(" test");
803   std::string const s6(" string");
804 
805   rope<> const r2(s4, s5, s6);
806   r.concat(r2);
807   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5 + s6, r.to_string());
808   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5 + s6, r);
809 
810   r.concat(r);
811   FATAL_EXPECT_EQ(
812     s1 + s2 + s3 + s4 + s5 + s6
813       + s1 + s2 + s3 + s4 + s5 + s6,
814     r.to_string()
815   );
816   FATAL_EXPECT_EQ(
817     s1 + s2 + s3 + s4 + s5 + s6
818       + s1 + s2 + s3 + s4 + s5 + s6,
819     r
820   );
821 
822   FATAL_EXPECT_THROW(std::invalid_argument) { r.concat(std::move(r)); };
823 }
824 
FATAL_TEST(concat,many_pieces)825 FATAL_TEST(concat, many_pieces) {
826   rope<> r;
827   FATAL_EXPECT_TRUE(r.empty());
828 
829   std::string const s1("hello");
830   std::string const s2(", ");
831   std::string const s3("world");
832   std::string const s4("!");
833   std::string const s5(" test");
834   std::string const s6(" string");
835 
836   rope<> r1(std::string(s1), s2, s3, s4, s5, s6);
837   FATAL_EXPECT_FALSE(r1.empty());
838   r.concat(std::move(r1));
839   FATAL_EXPECT_TRUE(r1.empty());
840   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5 + s6, r.to_string());
841   FATAL_EXPECT_EQ(s1 + s2 + s3 + s4 + s5 + s6, r);
842 
843   rope<> r2(std::string(s1), s2, s3, s4, s5, s6);
844   r.concat(r2);
845   FATAL_EXPECT_EQ(
846     s1 + s2 + s3 + s4 + s5 + s6
847       + s1 + s2 + s3 + s4 + s5 + s6,
848     r.to_string()
849   );
850   FATAL_EXPECT_EQ(
851     s1 + s2 + s3 + s4 + s5 + s6
852       + s1 + s2 + s3 + s4 + s5 + s6,
853     r
854   );
855 
856   r.concat(r);
857   FATAL_EXPECT_EQ(
858     s1 + s2 + s3 + s4 + s5 + s6
859       + s1 + s2 + s3 + s4 + s5 + s6
860       + s1 + s2 + s3 + s4 + s5 + s6
861       + s1 + s2 + s3 + s4 + s5 + s6,
862     r.to_string()
863   );
864   FATAL_EXPECT_EQ(
865     s1 + s2 + s3 + s4 + s5 + s6
866       + s1 + s2 + s3 + s4 + s5 + s6
867       + s1 + s2 + s3 + s4 + s5 + s6
868       + s1 + s2 + s3 + s4 + s5 + s6,
869     r
870   );
871 
872   FATAL_EXPECT_THROW(std::invalid_argument) { r.concat(std::move(r)); };
873 }
874 
875 ///////////////
876 // accessors //
877 ///////////////
878 
FATAL_TEST(accessors,front_back)879 FATAL_TEST(accessors, front_back) {
880   rope<> r;
881 
882   r.append('a');
883   FATAL_EXPECT_EQ('a', r.front());
884   FATAL_EXPECT_EQ('a', r.back());
885 
886   r.append("_b_c_d_e");
887   FATAL_EXPECT_EQ('a', r.front());
888   FATAL_EXPECT_EQ('e', r.back());
889 
890   std::string f_g_h_i("_f_g_h_i");
891   r.append(f_g_h_i);
892   FATAL_EXPECT_EQ('a', r.front());
893   FATAL_EXPECT_EQ('i', r.back());
894 
895   char const underscore = '_';
896   r.append(underscore);
897   FATAL_EXPECT_EQ('a', r.front());
898   FATAL_EXPECT_EQ('_', r.back());
899 
900   r.append(std::string("j_k_l_m"));
901   FATAL_EXPECT_EQ('a', r.front());
902   FATAL_EXPECT_EQ('m', r.back());
903 }
904 
905 //////////////////////
906 // at / operator [] //
907 //////////////////////
908 
FATAL_TEST(accessors,at)909 FATAL_TEST(accessors, at) {
910   rope<> r;
911   FATAL_EXPECT_THROW(std::out_of_range) { r.at(0); };
912   FATAL_EXPECT_THROW(std::out_of_range) { r.at(2); };
913   FATAL_EXPECT_THROW(std::out_of_range) { r.at(4); };
914   FATAL_EXPECT_THROW(std::out_of_range) { r.at(14); };
915   FATAL_EXPECT_THROW(std::out_of_range) { r.at(17); };
916   FATAL_EXPECT_THROW(std::out_of_range) { r.at(18); };
917   FATAL_EXPECT_THROW(std::out_of_range) { r.at(r.size() - 1); };
918   FATAL_EXPECT_THROW(std::out_of_range) { r.at(r.size()); };
919 
920   r.append('a');
921   FATAL_EXPECT_EQ('a', r.at(0));
922   FATAL_EXPECT_THROW(std::out_of_range) { r.at(2); };
923   FATAL_EXPECT_THROW(std::out_of_range) { r.at(4); };
924   FATAL_EXPECT_THROW(std::out_of_range) { r.at(14); };
925   FATAL_EXPECT_THROW(std::out_of_range) { r.at(17); };
926   FATAL_EXPECT_THROW(std::out_of_range) { r.at(18); };
927   FATAL_EXPECT_EQ('a', r.at(r.size() - 1));
928   FATAL_EXPECT_THROW(std::out_of_range) { r.at(r.size()); };
929 
930   r.append("_b_c_d_e");
931   FATAL_EXPECT_EQ('a', r.at(0));
932   FATAL_EXPECT_EQ('b', r.at(2));
933   FATAL_EXPECT_EQ('c', r.at(4));
934   FATAL_EXPECT_THROW(std::out_of_range) { r.at(14); };
935   FATAL_EXPECT_THROW(std::out_of_range) { r.at(17); };
936   FATAL_EXPECT_THROW(std::out_of_range) { r.at(18); };
937   FATAL_EXPECT_EQ('e', r.at(r.size() - 1));
938   FATAL_EXPECT_THROW(std::out_of_range) { r.at(r.size()); };
939 
940   std::string f_g_h_i("_f_g_h_i");
941   r.append(f_g_h_i);
942   FATAL_EXPECT_EQ('a', r.at(0));
943   FATAL_EXPECT_EQ('b', r.at(2));
944   FATAL_EXPECT_EQ('c', r.at(4));
945   FATAL_EXPECT_EQ('h', r.at(14));
946   FATAL_EXPECT_THROW(std::out_of_range) { r.at(17); };
947   FATAL_EXPECT_THROW(std::out_of_range) { r.at(18); };
948   FATAL_EXPECT_EQ('i', r.at(r.size() - 1));
949   FATAL_EXPECT_THROW(std::out_of_range) { r.at(r.size()); };
950 
951   char const underscore = '_';
952   r.append(underscore);
953   FATAL_EXPECT_EQ('a', r.at(0));
954   FATAL_EXPECT_EQ('b', r.at(2));
955   FATAL_EXPECT_EQ('c', r.at(4));
956   FATAL_EXPECT_EQ('h', r.at(14));
957   FATAL_EXPECT_EQ('_', r.at(17));
958   FATAL_EXPECT_THROW(std::out_of_range) { r.at(18); };
959   FATAL_EXPECT_EQ('_', r.at(r.size() - 1));
960   FATAL_EXPECT_THROW(std::out_of_range) { r.at(r.size()); };
961 
962   r.append(std::string("j_k_l_m"));
963   FATAL_EXPECT_EQ('a', r.at(0));
964   FATAL_EXPECT_EQ('b', r.at(2));
965   FATAL_EXPECT_EQ('c', r.at(4));
966   FATAL_EXPECT_EQ('h', r.at(14));
967   FATAL_EXPECT_EQ('_', r.at(17));
968   FATAL_EXPECT_EQ('j', r.at(18));
969   FATAL_EXPECT_EQ('m', r.at(r.size() - 1));
970   FATAL_EXPECT_THROW(std::out_of_range) { r.at(r.size()); };
971 }
972 
FATAL_TEST(accessors,operator[])973 FATAL_TEST(accessors, operator []) {
974   rope<> r;
975 
976   r.append('a');
977   FATAL_EXPECT_EQ('a', r[0]);
978   FATAL_EXPECT_EQ('a', r[r.size() - 1]);
979 
980   r.append("_b_c_d_e");
981   FATAL_EXPECT_EQ('a', r[0]);
982   FATAL_EXPECT_EQ('b', r[2]);
983   FATAL_EXPECT_EQ('c', r[4]);
984   FATAL_EXPECT_EQ('e', r[r.size() - 1]);
985 
986   std::string f_g_h_i("_f_g_h_i");
987   r.append(f_g_h_i);
988   FATAL_EXPECT_EQ('a', r[0]);
989   FATAL_EXPECT_EQ('b', r[2]);
990   FATAL_EXPECT_EQ('c', r[4]);
991   FATAL_EXPECT_EQ('h', r[14]);
992   FATAL_EXPECT_EQ('i', r[r.size() - 1]);
993 
994   char const underscore = '_';
995   r.append(underscore);
996   FATAL_EXPECT_EQ('a', r[0]);
997   FATAL_EXPECT_EQ('b', r[2]);
998   FATAL_EXPECT_EQ('c', r[4]);
999   FATAL_EXPECT_EQ('h', r[14]);
1000   FATAL_EXPECT_EQ('_', r[17]);
1001   FATAL_EXPECT_EQ('_', r[r.size() - 1]);
1002 
1003   r.append(std::string("j_k_l_m"));
1004   FATAL_EXPECT_EQ('a', r[0]);
1005   FATAL_EXPECT_EQ('b', r[2]);
1006   FATAL_EXPECT_EQ('c', r[4]);
1007   FATAL_EXPECT_EQ('h', r[14]);
1008   FATAL_EXPECT_EQ('_', r[17]);
1009   FATAL_EXPECT_EQ('j', r[18]);
1010   FATAL_EXPECT_EQ('m', r[r.size() - 1]);
1011 }
1012 
1013 //////////
1014 // copy //
1015 //////////
1016 
1017 // TODO: TEST COPY WITH OFFSET
1018 
FATAL_TEST(copy,copy)1019 FATAL_TEST(copy, copy) {
1020 # define TEST_IMPL(...) \
1021   do { \
1022     rope<> r(__VA_ARGS__); \
1023     \
1024     std::vector<char> buffer(r.size()); \
1025     \
1026     auto const end = r.copy( \
1027       buffer.data(), \
1028       std::next(buffer.data(), signed_cast(buffer.size())) \
1029     ); \
1030     \
1031     FATAL_EXPECT_EQ( \
1032       r.size(), \
1033       unsigned_cast(std::distance(buffer.data(), end)) \
1034     ); \
1035     FATAL_EXPECT_EQ( \
1036       buffer.size(), \
1037       unsigned_cast(std::distance(buffer.data(), end)) \
1038     ); \
1039     \
1040     FATAL_EXPECT_EQ(r, buffer); \
1041   } while (false)
1042 
1043   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1044 
1045 # undef TEST_IMPL
1046 }
1047 
1048 ///////////////
1049 // to_string //
1050 ///////////////
1051 
FATAL_TEST(string,to_string)1052 FATAL_TEST(string, to_string) {
1053 # define TEST_IMPL(...) \
1054   do { \
1055     rope<> r(__VA_ARGS__); \
1056     FATAL_EXPECT_EQ(to_string(__VA_ARGS__), r.to_string()); \
1057   } while (false)
1058 
1059   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1060 
1061 # undef TEST_IMPL
1062 }
1063 
1064 ///////////////
1065 // append_to //
1066 ///////////////
1067 
FATAL_TEST(string,append_to)1068 FATAL_TEST(string, append_to) {
1069 # define TEST_IMPL(...) \
1070   do { \
1071     rope<> r(__VA_ARGS__); \
1072     std::string s; \
1073     FATAL_EXPECT_EQ(to_string(__VA_ARGS__), r.append_to(s)); \
1074   } while (false)
1075 
1076   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1077 
1078 # undef TEST_IMPL
1079 }
1080 
1081 //////////////
1082 // capacity //
1083 //////////////
1084 
FATAL_TEST(capacity,empty)1085 FATAL_TEST(capacity, empty) {
1086 # define TEST_IMPL(SmallBufferSize) \
1087   do { \
1088     rope<SmallBufferSize> r; \
1089     FATAL_EXPECT_EQ(SmallBufferSize, r.capacity()); \
1090     for (auto i = SmallBufferSize; i--; ) { \
1091       r.append(' '); \
1092     } \
1093     FATAL_EXPECT_EQ(SmallBufferSize, r.capacity()); \
1094     FATAL_EXPECT_EQ(r.size(), r.capacity()); \
1095     r.append(' '); \
1096     FATAL_EXPECT_NE(SmallBufferSize, r.capacity()); \
1097   } while (false)
1098 
1099   TEST_IMPL(0);
1100   TEST_IMPL(1);
1101   TEST_IMPL(2);
1102   TEST_IMPL(3);
1103   TEST_IMPL(4);
1104   TEST_IMPL(5);
1105   TEST_IMPL(6);
1106   TEST_IMPL(7);
1107   TEST_IMPL(8);
1108   TEST_IMPL(9);
1109   TEST_IMPL(10);
1110   TEST_IMPL(11);
1111   TEST_IMPL(12);
1112   TEST_IMPL(13);
1113   TEST_IMPL(14);
1114   TEST_IMPL(15);
1115   TEST_IMPL(16);
1116   TEST_IMPL(17);
1117   TEST_IMPL(18);
1118   TEST_IMPL(19);
1119   TEST_IMPL(20);
1120   TEST_IMPL(21);
1121   TEST_IMPL(22);
1122   TEST_IMPL(23);
1123   TEST_IMPL(24);
1124   TEST_IMPL(25);
1125   TEST_IMPL(26);
1126   TEST_IMPL(27);
1127   TEST_IMPL(28);
1128   TEST_IMPL(29);
1129   TEST_IMPL(30);
1130   TEST_IMPL(31);
1131   TEST_IMPL(32);
1132 
1133 # undef TEST_IMPL
1134 }
1135 
FATAL_TEST(capacity,reserve (absolute))1136 FATAL_TEST(capacity, reserve (absolute)) {
1137 # define TEST_IMPL(SmallBufferSize) \
1138   do { \
1139     auto const capacity = SmallBufferSize * 2 + 1; \
1140     do { \
1141       rope<SmallBufferSize> r; \
1142       FATAL_EXPECT_EQ(SmallBufferSize, r.capacity()); \
1143       r.reserve(capacity); \
1144       FATAL_EXPECT_EQ(capacity, r.capacity()); \
1145       r.reserve(SmallBufferSize); \
1146       FATAL_EXPECT_EQ(capacity, r.capacity()); \
1147     } while (false); \
1148     do { \
1149       rope<SmallBufferSize> r; \
1150       FATAL_EXPECT_EQ(SmallBufferSize, r.capacity()); \
1151       r.reserve(capacity, false); \
1152       FATAL_EXPECT_EQ(capacity, r.capacity()); \
1153       r.reserve(SmallBufferSize, false); \
1154       FATAL_EXPECT_EQ(capacity, r.capacity()); \
1155     } while (false); \
1156   } while (false)
1157 
1158   TEST_IMPL(0);
1159   TEST_IMPL(1);
1160   TEST_IMPL(2);
1161   TEST_IMPL(3);
1162   TEST_IMPL(4);
1163   TEST_IMPL(5);
1164   TEST_IMPL(6);
1165   TEST_IMPL(7);
1166   TEST_IMPL(8);
1167   TEST_IMPL(9);
1168   TEST_IMPL(10);
1169   TEST_IMPL(11);
1170   TEST_IMPL(12);
1171   TEST_IMPL(13);
1172   TEST_IMPL(14);
1173   TEST_IMPL(15);
1174   TEST_IMPL(16);
1175   TEST_IMPL(17);
1176   TEST_IMPL(18);
1177   TEST_IMPL(19);
1178   TEST_IMPL(20);
1179   TEST_IMPL(21);
1180   TEST_IMPL(22);
1181   TEST_IMPL(23);
1182   TEST_IMPL(24);
1183   TEST_IMPL(25);
1184   TEST_IMPL(26);
1185   TEST_IMPL(27);
1186   TEST_IMPL(28);
1187   TEST_IMPL(29);
1188   TEST_IMPL(30);
1189   TEST_IMPL(31);
1190   TEST_IMPL(32);
1191 
1192 # undef TEST_IMPL
1193 }
1194 
FATAL_TEST(capacity,reserve (relative))1195 FATAL_TEST(capacity, reserve (relative)) {
1196 # define TEST_IMPL(SmallBufferSize) \
1197   do { \
1198     rope<SmallBufferSize> r; \
1199     FATAL_EXPECT_EQ(SmallBufferSize, r.capacity()); \
1200     auto const additional = SmallBufferSize + 1; \
1201     auto const capacity = SmallBufferSize + additional; \
1202     r.reserve(capacity, true); \
1203     FATAL_EXPECT_EQ(capacity, r.capacity()); \
1204     r.reserve(SmallBufferSize, true); \
1205     FATAL_EXPECT_EQ(capacity, r.capacity()); \
1206     r.reserve(additional, true); \
1207     FATAL_EXPECT_EQ(capacity, r.capacity()); \
1208   } while (false)
1209 
1210   TEST_IMPL(0);
1211   TEST_IMPL(1);
1212   TEST_IMPL(2);
1213   TEST_IMPL(3);
1214   TEST_IMPL(4);
1215   TEST_IMPL(5);
1216   TEST_IMPL(6);
1217   TEST_IMPL(7);
1218   TEST_IMPL(8);
1219   TEST_IMPL(9);
1220   TEST_IMPL(10);
1221   TEST_IMPL(11);
1222   TEST_IMPL(12);
1223   TEST_IMPL(13);
1224   TEST_IMPL(14);
1225   TEST_IMPL(15);
1226   TEST_IMPL(16);
1227   TEST_IMPL(17);
1228   TEST_IMPL(18);
1229   TEST_IMPL(19);
1230   TEST_IMPL(20);
1231   TEST_IMPL(21);
1232   TEST_IMPL(22);
1233   TEST_IMPL(23);
1234   TEST_IMPL(24);
1235   TEST_IMPL(25);
1236   TEST_IMPL(26);
1237   TEST_IMPL(27);
1238   TEST_IMPL(28);
1239   TEST_IMPL(29);
1240   TEST_IMPL(30);
1241   TEST_IMPL(31);
1242   TEST_IMPL(32);
1243 
1244 # undef TEST_IMPL
1245 }
1246 
1247 ///////////
1248 // clear //
1249 ///////////
1250 
FATAL_TEST(clear,empty)1251 FATAL_TEST(clear, empty) {
1252   rope<> r;
1253   FATAL_EXPECT_TRUE(r.empty());
1254   FATAL_EXPECT_EQ("", r);
1255   FATAL_EXPECT_EQ(0, r.pieces());
1256 
1257   r.clear();
1258   FATAL_EXPECT_TRUE(r.empty());
1259   FATAL_EXPECT_EQ("", r);
1260   FATAL_EXPECT_EQ(0, r.pieces());
1261 
1262   r.clear();
1263   FATAL_EXPECT_TRUE(r.empty());
1264   FATAL_EXPECT_EQ("", r);
1265   FATAL_EXPECT_EQ(0, r.pieces());
1266 
1267   r.clear();
1268   FATAL_EXPECT_TRUE(r.empty());
1269   FATAL_EXPECT_EQ("", r);
1270   FATAL_EXPECT_EQ(0, r.pieces());
1271 }
1272 
FATAL_TEST(clear,one)1273 FATAL_TEST(clear, one) {
1274   rope<> r;
1275   FATAL_EXPECT_TRUE(r.empty());
1276   FATAL_EXPECT_EQ("", r);
1277   FATAL_EXPECT_EQ(0, r.pieces());
1278 
1279   r.append("one");
1280   FATAL_EXPECT_FALSE(r.empty());
1281   FATAL_EXPECT_EQ("one", r);
1282   FATAL_EXPECT_EQ(1, r.pieces());
1283 
1284   r.clear();
1285   FATAL_EXPECT_TRUE(r.empty());
1286   FATAL_EXPECT_EQ("", r);
1287   FATAL_EXPECT_EQ(0, r.pieces());
1288 
1289   r.append(' ');
1290   FATAL_EXPECT_FALSE(r.empty());
1291   FATAL_EXPECT_EQ(" ", r);
1292   FATAL_EXPECT_EQ(1, r.pieces());
1293 
1294   r.clear();
1295   FATAL_EXPECT_TRUE(r.empty());
1296   FATAL_EXPECT_EQ("", r);
1297   FATAL_EXPECT_EQ(0, r.pieces());
1298 
1299   r.append(std::string("two"));
1300   FATAL_EXPECT_FALSE(r.empty());
1301   FATAL_EXPECT_EQ("two", r);
1302   FATAL_EXPECT_EQ(1, r.pieces());
1303 
1304   r.clear();
1305   FATAL_EXPECT_TRUE(r.empty());
1306   FATAL_EXPECT_EQ("", r);
1307   FATAL_EXPECT_EQ(0, r.pieces());
1308 
1309   r.append(string_view(" "));
1310   FATAL_EXPECT_FALSE(r.empty());
1311   FATAL_EXPECT_EQ(" ", r);
1312   FATAL_EXPECT_EQ(1, r.pieces());
1313 
1314   r.clear();
1315   FATAL_EXPECT_TRUE(r.empty());
1316   FATAL_EXPECT_EQ("", r);
1317   FATAL_EXPECT_EQ(0, r.pieces());
1318 
1319   std::string three("three");
1320   r.append(three);
1321   FATAL_EXPECT_FALSE(r.empty());
1322   FATAL_EXPECT_EQ("three", r);
1323   FATAL_EXPECT_EQ(1, r.pieces());
1324 
1325   r.clear();
1326   FATAL_EXPECT_TRUE(r.empty());
1327   FATAL_EXPECT_EQ("", r);
1328   FATAL_EXPECT_EQ(0, r.pieces());
1329 
1330   std::string f(" f");
1331   r.append(std::move(f));
1332   FATAL_EXPECT_FALSE(r.empty());
1333   FATAL_EXPECT_EQ(" f", r);
1334   FATAL_EXPECT_EQ(1, r.pieces());
1335 
1336   r.clear();
1337   FATAL_EXPECT_TRUE(r.empty());
1338   FATAL_EXPECT_EQ("", r);
1339   FATAL_EXPECT_EQ(0, r.pieces());
1340 
1341   std::string const o("o");
1342   r.append(o);
1343   FATAL_EXPECT_FALSE(r.empty());
1344   FATAL_EXPECT_EQ("o", r);
1345   FATAL_EXPECT_EQ(1, r.pieces());
1346 
1347   r.clear();
1348   FATAL_EXPECT_TRUE(r.empty());
1349   FATAL_EXPECT_EQ("", r);
1350   FATAL_EXPECT_EQ(0, r.pieces());
1351 
1352   string_view const ur("ur");
1353   r.append(ur);
1354   FATAL_EXPECT_FALSE(r.empty());
1355   FATAL_EXPECT_EQ("ur", r);
1356   FATAL_EXPECT_EQ(1, r.pieces());
1357 
1358   r.clear();
1359   FATAL_EXPECT_TRUE(r.empty());
1360   FATAL_EXPECT_EQ("", r);
1361   FATAL_EXPECT_EQ(0, r.pieces());
1362 
1363   string_view end("!");
1364   r.append(end);
1365   FATAL_EXPECT_FALSE(r.empty());
1366   FATAL_EXPECT_EQ("!", r);
1367   FATAL_EXPECT_EQ(1, r.pieces());
1368 
1369   r.clear();
1370   FATAL_EXPECT_TRUE(r.empty());
1371   FATAL_EXPECT_EQ("", r);
1372   FATAL_EXPECT_EQ(0, r.pieces());
1373 }
1374 
FATAL_TEST(clear,two)1375 FATAL_TEST(clear, two) {
1376   rope<> r;
1377   FATAL_EXPECT_TRUE(r.empty());
1378   FATAL_EXPECT_EQ("", r);
1379   FATAL_EXPECT_EQ(0, r.pieces());
1380 
1381   r.multi_append("one", ' ');
1382   FATAL_EXPECT_FALSE(r.empty());
1383   FATAL_EXPECT_EQ("one ", r);
1384   FATAL_EXPECT_EQ(2, r.pieces());
1385 
1386   r.clear();
1387   FATAL_EXPECT_TRUE(r.empty());
1388   FATAL_EXPECT_EQ("", r);
1389   FATAL_EXPECT_EQ(0, r.pieces());
1390 
1391   r.multi_append(std::string("two"), string_view(" "));
1392   FATAL_EXPECT_FALSE(r.empty());
1393   FATAL_EXPECT_EQ("two ", r);
1394   FATAL_EXPECT_EQ(2, r.pieces());
1395 
1396   r.clear();
1397   FATAL_EXPECT_TRUE(r.empty());
1398   FATAL_EXPECT_EQ("", r);
1399   FATAL_EXPECT_EQ(0, r.pieces());
1400 
1401   std::string three("three");
1402   string_view space(" ");
1403   r.multi_append(three, space);
1404   FATAL_EXPECT_FALSE(r.empty());
1405   FATAL_EXPECT_EQ("three ", r);
1406   FATAL_EXPECT_EQ(2, r.pieces());
1407 
1408   r.clear();
1409   FATAL_EXPECT_TRUE(r.empty());
1410   FATAL_EXPECT_EQ("", r);
1411   FATAL_EXPECT_EQ(0, r.pieces());
1412 
1413   std::string f(" f");
1414   std::string const o("o");
1415   r.multi_append(std::move(f), o);
1416   FATAL_EXPECT_FALSE(r.empty());
1417   FATAL_EXPECT_EQ(" fo", r);
1418   FATAL_EXPECT_EQ(2, r.pieces());
1419 
1420   r.clear();
1421   FATAL_EXPECT_TRUE(r.empty());
1422   FATAL_EXPECT_EQ("", r);
1423   FATAL_EXPECT_EQ(0, r.pieces());
1424 
1425   string_view const ur("ur");
1426   string_view end("!");
1427   r.multi_append(ur, end);
1428   FATAL_EXPECT_FALSE(r.empty());
1429   FATAL_EXPECT_EQ("ur!", r);
1430   FATAL_EXPECT_EQ(2, r.pieces());
1431 
1432   r.clear();
1433   FATAL_EXPECT_TRUE(r.empty());
1434   FATAL_EXPECT_EQ("", r);
1435   FATAL_EXPECT_EQ(0, r.pieces());
1436 }
1437 
FATAL_TEST(clear,three)1438 FATAL_TEST(clear, three) {
1439   rope<> r;
1440   FATAL_EXPECT_TRUE(r.empty());
1441   FATAL_EXPECT_EQ("", r);
1442   FATAL_EXPECT_EQ(0, r.pieces());
1443 
1444   r.multi_append("one", ' ', std::string("two"));
1445   FATAL_EXPECT_FALSE(r.empty());
1446   FATAL_EXPECT_EQ("one two", r);
1447   FATAL_EXPECT_EQ(3, r.pieces());
1448 
1449   r.clear();
1450   FATAL_EXPECT_TRUE(r.empty());
1451   FATAL_EXPECT_EQ("", r);
1452   FATAL_EXPECT_EQ(0, r.pieces());
1453 
1454   std::string three("three");
1455   std::string f(" f");
1456 
1457   r.multi_append(string_view(" "), three, std::move(f));
1458   FATAL_EXPECT_FALSE(r.empty());
1459   FATAL_EXPECT_EQ(" three f", r);
1460   FATAL_EXPECT_EQ(3, r.pieces());
1461 
1462   r.clear();
1463   FATAL_EXPECT_TRUE(r.empty());
1464   FATAL_EXPECT_EQ("", r);
1465   FATAL_EXPECT_EQ(0, r.pieces());
1466 
1467   std::string const o("o");
1468   string_view const ur("ur");
1469   string_view end("!");
1470 
1471   r.multi_append(o, ur, end);
1472   FATAL_EXPECT_FALSE(r.empty());
1473   FATAL_EXPECT_EQ("our!", r);
1474   FATAL_EXPECT_EQ(3, r.pieces());
1475 
1476   r.clear();
1477   FATAL_EXPECT_TRUE(r.empty());
1478   FATAL_EXPECT_EQ("", r);
1479   FATAL_EXPECT_EQ(0, r.pieces());
1480 }
1481 
FATAL_TEST(clear,many)1482 FATAL_TEST(clear, many) {
1483   rope<> r;
1484   FATAL_EXPECT_TRUE(r.empty());
1485   FATAL_EXPECT_EQ("", r);
1486   FATAL_EXPECT_EQ(0, r.pieces());
1487 
1488   r.multi_append("one", ' ', std::string("two"), string_view(" "));
1489   FATAL_EXPECT_FALSE(r.empty());
1490   FATAL_EXPECT_EQ("one two ", r);
1491   FATAL_EXPECT_EQ(4, r.pieces());
1492 
1493   r.clear();
1494   FATAL_EXPECT_TRUE(r.empty());
1495   FATAL_EXPECT_EQ("", r);
1496   FATAL_EXPECT_EQ(0, r.pieces());
1497 
1498   std::string three("three");
1499   std::string const ou("ou");
1500   string_view end("!");
1501 
1502   r.multi_append(three, " ", 'f', ou, std::string("r"), end);
1503   FATAL_EXPECT_FALSE(r.empty());
1504   FATAL_EXPECT_EQ("three four!", r);
1505   FATAL_EXPECT_EQ(6, r.pieces());
1506 
1507   r.clear();
1508   FATAL_EXPECT_TRUE(r.empty());
1509   FATAL_EXPECT_EQ("", r);
1510   FATAL_EXPECT_EQ(0, r.pieces());
1511 }
1512 
1513 //////////
1514 // find //
1515 //////////
1516 
1517 template <typename T>
find_char_test(std::chrono::milliseconds time,std::size_t minimum_iterations,T && fn)1518 void find_char_test(
1519   std::chrono::milliseconds time,
1520   std::size_t minimum_iterations,
1521   T &&fn
1522 ) {
1523   std::string const alphabet(
1524     "0123456789"
1525     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1526     "abcdefghijklmnopqrstuvwxyz"
1527   );
1528 
1529   random_data rdg;
1530 
1531   for (std::size_t size = 30; size; --size) {
1532     std::string s(size, '\0');
1533     rdg.string(s.begin(), s.end(), alphabet.data(), alphabet.size());
1534 
1535     auto const begin = s.data();
1536     auto const end = std::next(begin, signed_cast(s.size()));
1537 
1538     for (timed_iterations<> i(time, minimum_iterations); i.next(); ) {
1539       rope<> r;
1540       auto const pieces = rdg.chop(
1541         begin, end,
1542         [&](char const *b, char const *e) { r.append(b, e); }
1543       );
1544       FATAL_EXPECT_EQ(pieces, r.pieces());
1545       FATAL_EXPECT_EQ(s, r);
1546 
1547       fn(s, r, alphabet);
1548     }
1549   }
1550 }
1551 
FATAL_TEST(find,char)1552 FATAL_TEST(find, char) {
1553   find_char_test(
1554     std::chrono::milliseconds(100), 1000,
1555     [](
1556       std::string const &s,
1557       rope<> const &r,
1558       std::string const &alphabet
1559     ) {
1560       for (auto c: alphabet) {
1561         auto expected = s.find(c);
1562         if (expected == std::string::npos) {
1563           expected = s.size();
1564         } else {
1565           assert(expected != s.size());
1566         }
1567 
1568         auto const actual = r.find(c);
1569         FATAL_EXPECT_EQ(expected, actual.absolute());
1570       }
1571     }
1572   );
1573 }
1574 
FATAL_TEST(find,char size_type)1575 FATAL_TEST(find, char size_type) {
1576   find_char_test(
1577     std::chrono::milliseconds(100), 1000,
1578     [](
1579       std::string const &s,
1580       rope<> const &r,
1581       std::string const &alphabet
1582     ) {
1583       for (auto offset = s.size() + 1; offset--; ) {
1584         for (auto c: alphabet) {
1585           auto expected = s.find(c, offset);
1586           if (expected == std::string::npos) {
1587             expected = s.size();
1588           } else {
1589             assert(expected != s.size());
1590           }
1591 
1592           auto const actual = r.find(c, offset);
1593           FATAL_EXPECT_EQ(expected, actual.absolute());
1594         }
1595       }
1596     }
1597   );
1598 }
1599 
FATAL_TEST(find,char const_iterator)1600 FATAL_TEST(find, char const_iterator) {
1601   find_char_test(
1602     std::chrono::milliseconds(100), 1000,
1603     [](
1604       std::string const &s,
1605       rope<> const &r,
1606       std::string const &alphabet
1607     ) {
1608       for (auto offset = s.size() + 1; offset--; ) {
1609         auto const r_offset = std::next(r.begin(), signed_cast(offset));
1610         FATAL_EXPECT_EQ(offset, r_offset.absolute());
1611 
1612         for (auto c: alphabet) {
1613           auto expected = s.find(c, offset);
1614           if (expected == std::string::npos) {
1615             expected = s.size();
1616           } else {
1617             assert(expected != s.size());
1618           }
1619 
1620           auto const actual = r.find(c, r_offset);
1621           FATAL_EXPECT_EQ(expected, actual.absolute());
1622         }
1623       }
1624     }
1625   );
1626 }
1627 
1628 /* TODO: IMPLEMENT
1629 FATAL_TEST(find, TODO) {
1630   // TODO: IMPLEMENT
1631   FATAL_EXPECT_UNREACHABLE();
1632 }
1633 
1634 ///////////
1635 // rfind //
1636 ///////////
1637 
1638 FATAL_TEST(rfind, TODO) {
1639   // TODO: IMPLEMENT
1640   FATAL_EXPECT_UNREACHABLE();
1641 }
1642 
1643 ///////////////////
1644 // find_first_of //
1645 ///////////////////
1646 
1647 FATAL_TEST(find_first_of, TODO) {
1648   // TODO: IMPLEMENT
1649   FATAL_EXPECT_UNREACHABLE();
1650 }
1651 
1652 ///////////////////////
1653 // find_first_not_of //
1654 ///////////////////////
1655 
1656 FATAL_TEST(find_first_not_of, TODO) {
1657   // TODO: IMPLEMENT
1658   FATAL_EXPECT_UNREACHABLE();
1659 }
1660 
1661 //////////////////
1662 // find_last_of //
1663 //////////////////
1664 
1665 FATAL_TEST(find_last_of, TODO) {
1666   // TODO: IMPLEMENT
1667   FATAL_EXPECT_UNREACHABLE();
1668 }
1669 
1670 //////////////////////
1671 // find_last_not_of //
1672 //////////////////////
1673 
1674 FATAL_TEST(find_last_not_of, TODO) {
1675   // TODO: IMPLEMENT
1676   FATAL_EXPECT_UNREACHABLE();
1677 }
1678 */
1679 
1680 ///////////////
1681 // iterators //
1682 ///////////////
1683 
FATAL_TEST(const_iterator,empty)1684 FATAL_TEST(const_iterator, empty) {
1685   rope<> r;
1686 
1687   FATAL_EXPECT_EQ(r.cbegin(), r.begin());
1688   FATAL_EXPECT_EQ(r.cend(), r.end());
1689   FATAL_EXPECT_EQ(r.cbegin(), r.cend());
1690   FATAL_EXPECT_EQ(r.begin(), r.end());
1691 }
1692 
FATAL_TEST(const_iterator,foreach)1693 FATAL_TEST(const_iterator, foreach) {
1694 # define TEST_IMPL(...) \
1695   do { \
1696     rope<> r(__VA_ARGS__); \
1697     auto const s = to_string(__VA_ARGS__); \
1698     auto const begin = s.begin(); \
1699     auto const end = s.end(); \
1700     auto j = begin; \
1701     std::size_t n = 0; \
1702     for (auto const i: r) { \
1703       FATAL_ASSERT_LT(j, end); \
1704       FATAL_EXPECT_EQ(*j, i); \
1705       ++j; \
1706       ++n; \
1707     } \
1708     FATAL_EXPECT_EQ(n, s.size()); \
1709     FATAL_EXPECT_EQ(j, end); \
1710   } while (false)
1711 
1712   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1713 
1714 # undef TEST_IMPL
1715 }
1716 
1717 FATAL_TEST(const_iterator, foreach (prefix ++)) {
1718 # define TEST_IMPL(...) \
1719   do { \
1720     rope<> r(__VA_ARGS__); \
1721     auto const s = to_string(__VA_ARGS__); \
1722     auto const begin = s.begin(); \
1723     auto const end = s.end(); \
1724     auto j = begin; \
1725     auto const b = r.begin(); \
1726     auto const e = r.end(); \
1727     auto i = b; \
1728     std::size_t n = 0; \
1729     for (; i != e; ++i, ++j, ++n) { \
1730       FATAL_ASSERT_LT(j, end); \
1731       FATAL_ASSERT_NE(i, e); \
1732       FATAL_ASSERT_LT(i, e); \
1733       FATAL_ASSERT_GE(i, b); \
1734       FATAL_ASSERT_GT(e, i); \
1735       FATAL_ASSERT_LE(b, i); \
1736       FATAL_EXPECT_EQ(*j, *i); \
1737     } \
1738     FATAL_EXPECT_EQ(n, s.size()); \
1739     FATAL_EXPECT_EQ(j, end); \
1740     FATAL_EXPECT_EQ(i, e); \
1741   } while (false)
1742 
1743   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1744 
1745 # undef TEST_IMPL
1746 }
1747 
1748 FATAL_TEST(const_iterator, foreach (postfix ++)) {
1749 # define TEST_IMPL(...) \
1750   do { \
1751     rope<> r(__VA_ARGS__); \
1752     auto const s = to_string(__VA_ARGS__); \
1753     auto const begin = s.begin(); \
1754     auto const end = s.end(); \
1755     auto j = begin; \
1756     auto const b = r.begin(); \
1757     auto const e = r.end(); \
1758     auto i = b; \
1759     std::size_t n = 0; \
1760     for (; i != e; i++, ++j, ++n) { \
1761       FATAL_ASSERT_LT(j, end); \
1762       FATAL_ASSERT_NE(i, e); \
1763       FATAL_ASSERT_LT(i, e); \
1764       FATAL_ASSERT_GE(i, b); \
1765       FATAL_ASSERT_GT(e, i); \
1766       FATAL_ASSERT_LE(b, i); \
1767       FATAL_EXPECT_EQ(*j, *i); \
1768     } \
1769     FATAL_EXPECT_EQ(n, s.size()); \
1770     FATAL_EXPECT_EQ(j, end); \
1771     FATAL_EXPECT_EQ(i, e); \
1772   } while (false)
1773 
1774   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1775 
1776 # undef TEST_IMPL
1777 }
1778 
1779 FATAL_TEST(const_iterator, foreach (prefix --)) {
1780 # define TEST_IMPL(...) \
1781   do { \
1782     rope<> r(__VA_ARGS__); \
1783     auto const s = to_string(__VA_ARGS__); \
1784     auto const begin = s.begin(); \
1785     auto const end = s.end(); \
1786     auto j = end; \
1787     auto const b = r.begin(); \
1788     auto const e = r.end(); \
1789     auto i = e; \
1790     std::size_t n = 0; \
1791     for (; i != b; ++n) { \
1792       --i; \
1793       --j; \
1794       FATAL_ASSERT_GE(j, begin); \
1795       FATAL_ASSERT_LT(j, end); \
1796       FATAL_ASSERT_NE(i, e); \
1797       FATAL_ASSERT_LT(i, e); \
1798       FATAL_ASSERT_GE(i, b); \
1799       FATAL_ASSERT_GT(e, i); \
1800       FATAL_ASSERT_LE(b, i); \
1801       FATAL_EXPECT_EQ(*j, *i); \
1802     } \
1803     FATAL_EXPECT_EQ(n, s.size()); \
1804     FATAL_EXPECT_EQ(i, b); \
1805     FATAL_EXPECT_EQ(j, begin); \
1806   } while (false)
1807 
1808   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1809 
1810 # undef TEST_IMPL
1811 }
1812 
1813 FATAL_TEST(const_iterator, foreach (postfix --)) {
1814 # define TEST_IMPL(...) \
1815   do { \
1816     rope<> r(__VA_ARGS__); \
1817     auto const s = to_string(__VA_ARGS__); \
1818     auto const begin = s.begin(); \
1819     auto const end = s.end(); \
1820     auto j = end; \
1821     auto const b = r.begin(); \
1822     auto const e = r.end(); \
1823     auto i = e; \
1824     std::size_t n = 0; \
1825     for (; i != b; ++n) { \
1826       i--; \
1827       --j; \
1828       FATAL_ASSERT_GE(j, begin); \
1829       FATAL_ASSERT_LT(j, end); \
1830       FATAL_ASSERT_NE(i, e); \
1831       FATAL_ASSERT_LT(i, e); \
1832       FATAL_ASSERT_GE(i, b); \
1833       FATAL_ASSERT_GT(e, i); \
1834       FATAL_ASSERT_LE(b, i); \
1835       FATAL_EXPECT_EQ(*j, *i); \
1836     } \
1837     FATAL_EXPECT_EQ(n, s.size()); \
1838     FATAL_EXPECT_EQ(i, b); \
1839     FATAL_EXPECT_EQ(j, begin); \
1840   } while (false)
1841 
1842   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1843 
1844 # undef TEST_IMPL
1845 }
1846 
1847 FATAL_TEST(const_iterator, foreach (+= 1)) {
1848 # define TEST_IMPL(...) \
1849   do { \
1850     rope<> r(__VA_ARGS__); \
1851     auto const s = to_string(__VA_ARGS__); \
1852     auto const begin = s.begin(); \
1853     auto const end = s.end(); \
1854     auto j = begin; \
1855     auto const b = r.begin(); \
1856     auto const e = r.end(); \
1857     auto i = b; \
1858     std::size_t n = 0; \
1859     for (; i != e; i += 1, ++j, ++n) { \
1860       FATAL_ASSERT_LT(j, end); \
1861       FATAL_ASSERT_NE(i, e); \
1862       FATAL_ASSERT_LT(i, e); \
1863       FATAL_ASSERT_GE(i, b); \
1864       FATAL_ASSERT_GT(e, i); \
1865       FATAL_ASSERT_LE(b, i); \
1866       FATAL_EXPECT_EQ(*j, *i); \
1867     } \
1868     FATAL_EXPECT_EQ(n, s.size()); \
1869     FATAL_EXPECT_EQ(j, end); \
1870     FATAL_EXPECT_EQ(i, e); \
1871   } while (false)
1872 
1873   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1874 
1875 # undef TEST_IMPL
1876 }
1877 
1878 FATAL_TEST(const_iterator, foreach (-= 1)) {
1879 # define TEST_IMPL(...) \
1880   do { \
1881     rope<> r(__VA_ARGS__); \
1882     auto const s = to_string(__VA_ARGS__); \
1883     auto const begin = s.begin(); \
1884     auto const end = s.end(); \
1885     auto j = end; \
1886     auto const b = r.begin(); \
1887     auto const e = r.end(); \
1888     auto i = e; \
1889     std::size_t n = 0; \
1890     for (; i != b; ++n) { \
1891       i -= 1; \
1892       --j; \
1893       FATAL_ASSERT_GE(j, begin); \
1894       FATAL_ASSERT_LT(j, end); \
1895       FATAL_ASSERT_NE(i, e); \
1896       FATAL_ASSERT_LT(i, e); \
1897       FATAL_ASSERT_GE(i, b); \
1898       FATAL_ASSERT_GT(e, i); \
1899       FATAL_ASSERT_LE(b, i); \
1900       FATAL_EXPECT_EQ(*j, *i); \
1901     } \
1902     FATAL_EXPECT_EQ(n, s.size()); \
1903     FATAL_EXPECT_EQ(i, b); \
1904     FATAL_EXPECT_EQ(j, begin); \
1905   } while (false)
1906 
1907   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1908 
1909 # undef TEST_IMPL
1910 }
1911 
1912 //////////
1913 // hash //
1914 //////////
1915 
FATAL_TEST(rope,hasher)1916 FATAL_TEST(rope, hasher) {
1917 # define TEST_IMPL(...) \
1918   do { \
1919     rope<> r1(__VA_ARGS__); \
1920     rope<> r2(to_string(__VA_ARGS__)); \
1921     using hasher = rope<>::hasher; \
1922     FATAL_EXPECT_EQ(hasher()(r1), hasher()(r2)); \
1923   } while (false)
1924 
1925   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1926 
1927 # undef TEST_IMPL
1928 }
1929 
1930 /////////////
1931 // ostream //
1932 /////////////
1933 
FATAL_TEST(std,ostream)1934 FATAL_TEST(std, ostream) {
1935 # define TEST_IMPL(...) \
1936   do { \
1937     rope<> r(__VA_ARGS__); \
1938     std::ostringstream ss; \
1939     ss << r; \
1940     auto const expected = to_string(__VA_ARGS__); \
1941     FATAL_EXPECT_EQ(expected, ss.str()); \
1942   } while (false)
1943 
1944   TEST_IMPL_SINGLE_STRING(TEST_IMPL);
1945 
1946 # undef TEST_IMPL
1947 }
1948 
1949 } // namespace fatal {
1950