rippled
Loading...
Searching...
No Matches
aged_associative_container_test.cpp
1#include <xrpl/beast/clock/manual_clock.h>
2#include <xrpl/beast/container/aged_map.h>
3#include <xrpl/beast/container/aged_multimap.h>
4#include <xrpl/beast/container/aged_multiset.h>
5#include <xrpl/beast/container/aged_set.h>
6#include <xrpl/beast/container/aged_unordered_map.h>
7#include <xrpl/beast/container/aged_unordered_multimap.h>
8#include <xrpl/beast/container/aged_unordered_multiset.h>
9#include <xrpl/beast/container/aged_unordered_set.h>
10#include <xrpl/beast/unit_test.h>
11
12#include <list>
13#include <vector>
14
15#ifndef BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR
16#ifdef _MSC_VER
17#define BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR 0
18#else
19#define BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR 1
20#endif
21#endif
22
23#ifndef BEAST_CONTAINER_EXTRACT_NOREF
24#ifdef _MSC_VER
25#define BEAST_CONTAINER_EXTRACT_NOREF 1
26#else
27#define BEAST_CONTAINER_EXTRACT_NOREF 1
28#endif
29#endif
30
31namespace beast {
32
34{
35public:
36 template <class T>
37 struct CompT
38 {
39 explicit CompT(int)
40 {
41 }
42
43 CompT(CompT const&)
44 {
45 }
46
47 bool
48 operator()(T const& lhs, T const& rhs) const
49 {
50 return m_less(lhs, rhs);
51 }
52
53 private:
54 CompT() = delete;
56 };
57
58 template <class T>
59 class HashT
60 {
61 public:
62 explicit HashT(int)
63 {
64 }
65
67 operator()(T const& t) const
68 {
69 return m_hash(t);
70 }
71
72 private:
73 HashT() = delete;
75 };
76
77 template <class T>
78 struct EqualT
79 {
80 public:
81 explicit EqualT(int)
82 {
83 }
84
85 bool
86 operator()(T const& lhs, T const& rhs) const
87 {
88 return m_eq(lhs, rhs);
89 }
90
91 private:
92 EqualT() = delete;
94 };
95
96 template <class T>
97 struct AllocT
98 {
99 using value_type = T;
100
101 // using std::true_type::type = propagate_on_container_swap :;
102
103 template <class U>
104 struct rebind
105 {
107 };
108
109 explicit AllocT(int)
110 {
111 }
112
113 AllocT(AllocT const&) = default;
114
115 template <class U>
117 {
118 }
119
120 template <class U>
121 bool
122 operator==(AllocT<U> const&) const
123 {
124 return true;
125 }
126
127 template <class U>
128 bool
129 operator!=(AllocT<U> const& o) const
130 {
131 return !(*this == o);
132 }
133
134 T*
135 allocate(std::size_t n, T const* = 0)
136 {
137 return static_cast<T*>(::operator new(n * sizeof(T)));
138 }
139
140 void
142 {
143 ::operator delete(p);
144 }
145
146#if !BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR
148 {
149 }
150#else
151 private:
152 AllocT() = delete;
153#endif
154 };
155
156 //--------------------------------------------------------------------------
157
158 // ordered
159 template <class Base, bool IsUnordered>
160 class MaybeUnordered : public Base
161 {
162 public:
165
166 protected:
167 static std::string
169 {
170 return "";
171 }
172 };
173
174 // unordered
175 template <class Base>
176 class MaybeUnordered<Base, true> : public Base
177 {
178 public:
183
184 protected:
185 static std::string
187 {
188 return "unordered_";
189 }
190 };
191
192 // unique
193 template <class Base, bool IsMulti>
194 class MaybeMulti : public Base
195 {
196 public:
197 protected:
198 static std::string
200 {
201 return "";
202 }
203 };
204
205 // multi
206 template <class Base>
207 class MaybeMulti<Base, true> : public Base
208 {
209 public:
210 protected:
211 static std::string
213 {
214 return "multi";
215 }
216 };
217
218 // set
219 template <class Base, bool IsMap>
220 class MaybeMap : public Base
221 {
222 public:
223 using T = void;
224 using Value = typename Base::Key;
226
227 static typename Base::Key const&
228 extract(Value const& value)
229 {
230 return value;
231 }
232
233 static Values
235 {
236 Values v{
237 "apple",
238 "banana",
239 "cherry",
240 "grape",
241 "orange",
242 };
243 return v;
244 }
245
246 protected:
247 static std::string
249 {
250 return "set";
251 }
252 };
253
254 // map
255 template <class Base>
256 class MaybeMap<Base, true> : public Base
257 {
258 public:
259 using T = int;
262
263 static typename Base::Key const&
264 extract(Value const& value)
265 {
266 return value.first;
267 }
268
269 static Values
271 {
272 Values v{
273 std::make_pair("apple", 1),
274 std::make_pair("banana", 2),
275 std::make_pair("cherry", 3),
276 std::make_pair("grape", 4),
277 std::make_pair("orange", 5)};
278 return v;
279 }
280
281 protected:
282 static std::string
284 {
285 return "map";
286 }
287 };
288
289 //--------------------------------------------------------------------------
290
291 // ordered
292 template <class Base, bool IsUnordered = Base::is_unordered::value>
293 struct ContType
294 {
295 template <
296 class Compare = std::less<typename Base::Key>,
297 class Allocator = std::allocator<typename Base::Value>>
299 Base::is_multi::value,
300 Base::is_map::value,
301 typename Base::Key,
302 typename Base::T,
303 typename Base::Clock,
304 Compare,
305 Allocator>;
306 };
307
308 // unordered
309 template <class Base>
310 struct ContType<Base, true>
311 {
312 template <
314 class KeyEqual = std::equal_to<typename Base::Key>,
315 class Allocator = std::allocator<typename Base::Value>>
317 Base::is_multi::value,
318 Base::is_map::value,
319 typename Base::Key,
320 typename Base::T,
321 typename Base::Clock,
322 Hash,
323 KeyEqual,
324 Allocator>;
325 };
326
327 //--------------------------------------------------------------------------
328
335
336 template <bool IsUnordered, bool IsMulti, bool IsMap>
339 MaybeMulti<MaybeMap<TestTraitsBase, IsMap>, IsMulti>,
340 IsUnordered>
341 {
342 private:
345 IsUnordered>;
346
347 public:
348 using typename Base::Key;
349
353
356
357 static std::string
359 {
360 return std::string("aged_") + Base::name_ordered_part() +
362 }
363 };
364
365 template <bool IsUnordered, bool IsMulti, bool IsMap>
366 struct TestTraits : TestTraitsHelper<IsUnordered, IsMulti, IsMap>,
367 ContType<TestTraitsHelper<IsUnordered, IsMulti, IsMap>>
368 {
369 };
370
371 template <class Cont>
372 static std::string
378
379 template <class Traits>
381 {
382 bool
384 typename Traits::Value const& lhs,
385 typename Traits::Value const& rhs)
386 {
387 return Traits::extract(lhs) == Traits::extract(rhs);
388 }
389 };
390
391 template <class Cont>
393 make_list(Cont const& c)
394 {
395 return std::vector<typename Cont::value_type>(c.begin(), c.end());
396 }
397
398 //--------------------------------------------------------------------------
399
400 template <class Container, class Values>
401 typename std::enable_if<
402 Container::is_map::value && !Container::is_multi::value>::type
403 checkMapContents(Container& c, Values const& v);
404
405 template <class Container, class Values>
406 typename std::enable_if<
407 !(Container::is_map::value && !Container::is_multi::value)>::type
408 checkMapContents(Container, Values const&)
409 {
410 }
411
412 // unordered
413 template <class C, class Values>
414 typename std::enable_if<
416 checkUnorderedContentsRefRef(C&& c, Values const& v);
417
418 template <class C, class Values>
419 typename std::enable_if<
422 {
423 }
424
425 template <class C, class Values>
426 void
427 checkContentsRefRef(C&& c, Values const& v);
428
429 template <class Cont, class Values>
430 void
431 checkContents(Cont& c, Values const& v);
432
433 template <class Cont>
434 void
435 checkContents(Cont& c);
436
437 //--------------------------------------------------------------------------
438
439 // ordered
440 template <bool IsUnordered, bool IsMulti, bool IsMap>
443
444 // unordered
445 template <bool IsUnordered, bool IsMulti, bool IsMap>
448
449 // ordered
450 template <bool IsUnordered, bool IsMulti, bool IsMap>
453
454 // unordered
455 template <bool IsUnordered, bool IsMulti, bool IsMap>
458
459 // ordered
460 template <bool IsUnordered, bool IsMulti, bool IsMap>
463
464 // unordered
465 template <bool IsUnordered, bool IsMulti, bool IsMap>
468
469 //--------------------------------------------------------------------------
470
471 template <bool IsUnordered, bool IsMulti, bool IsMap>
472 void
473 testCopyMove();
474
475 //--------------------------------------------------------------------------
476
477 template <bool IsUnordered, bool IsMulti, bool IsMap>
478 void
479 testIterator();
480
481 // Unordered containers don't have reverse iterators
482 template <bool IsUnordered, bool IsMulti, bool IsMap>
485
486 template <bool IsUnordered, bool IsMulti, bool IsMap>
489 {
490 }
491
492 //--------------------------------------------------------------------------
493
494 template <class Container, class Values>
495 void
496 checkInsertCopy(Container& c, Values const& v);
497
498 template <class Container, class Values>
499 void
500 checkInsertMove(Container& c, Values const& v);
501
502 template <class Container, class Values>
503 void
504 checkInsertHintCopy(Container& c, Values const& v);
505
506 template <class Container, class Values>
507 void
508 checkInsertHintMove(Container& c, Values const& v);
509
510 template <class Container, class Values>
511 void
512 checkEmplace(Container& c, Values const& v);
513
514 template <class Container, class Values>
515 void
516 checkEmplaceHint(Container& c, Values const& v);
517
518 template <bool IsUnordered, bool IsMulti, bool IsMap>
519 void
521
522 //--------------------------------------------------------------------------
523
524 template <bool IsUnordered, bool IsMulti, bool IsMap>
525 void
527
528 //--------------------------------------------------------------------------
529
530 // map, unordered_map
531 template <bool IsUnordered, bool IsMulti, bool IsMap>
534
535 template <bool IsUnordered, bool IsMulti, bool IsMap>
536 typename std::enable_if<!(IsMap && !IsMulti)>::type
538 {
539 }
540
541 //--------------------------------------------------------------------------
542
543 // Helpers for erase tests
544 template <class Container, class Values>
545 void
546 reverseFillAgedContainer(Container& c, Values const& v);
547
548 template <class Iter>
549 Iter
550 nextToEndIter(Iter const beginIter, Iter const endItr);
551
552 //--------------------------------------------------------------------------
553
554 template <class Container, class Iter>
555 bool
556 doElementErase(Container& c, Iter const beginItr, Iter const endItr);
557
558 template <bool IsUnordered, bool IsMulti, bool IsMap>
559 void
561
562 //--------------------------------------------------------------------------
563
564 template <class Container, class BeginEndSrc>
565 void
566 doRangeErase(Container& c, BeginEndSrc const& beginEndSrc);
567
568 template <bool IsUnordered, bool IsMulti, bool IsMap>
569 void
571
572 //--------------------------------------------------------------------------
573
574 // ordered
575 template <bool IsUnordered, bool IsMulti, bool IsMap>
577 testCompare();
578
579 template <bool IsUnordered, bool IsMulti, bool IsMap>
582 {
583 }
584
585 //--------------------------------------------------------------------------
586
587 // ordered
588 template <bool IsUnordered, bool IsMulti, bool IsMap>
591
592 // unordered
593 template <bool IsUnordered, bool IsMulti, bool IsMap>
596
597 //--------------------------------------------------------------------------
598
599 template <bool IsUnordered, bool IsMulti, bool IsMap>
600 void
602
603 template <bool IsUnordered, bool IsMulti>
604 void
606
607 template <bool IsUnordered>
608 void
610};
611
612//------------------------------------------------------------------------------
613
614// Check contents via at() and operator[]
615// map, unordered_map
616template <class Container, class Values>
617typename std::enable_if<
618 Container::is_map::value && !Container::is_multi::value>::type
620 Container& c,
621 Values const& v)
622{
623 if (v.empty())
624 {
625 BEAST_EXPECT(c.empty());
626 BEAST_EXPECT(c.size() == 0);
627 return;
628 }
629
630 try
631 {
632 // Make sure no exception is thrown
633 for (auto const& e : v)
634 c.at(e.first);
635 for (auto const& e : v)
636 BEAST_EXPECT(c.operator[](e.first) == e.second);
637 }
638 catch (std::out_of_range const&)
639 {
640 fail("caught exception");
641 }
642}
643
644// unordered
645template <class C, class Values>
646typename std::enable_if<
649 C&& c,
650 Values const& v)
651{
652 using Cont = typename std::remove_reference<C>::type;
653 using Traits = TestTraits<
654 Cont::is_unordered::value,
655 Cont::is_multi::value,
656 Cont::is_map::value>;
657 using size_type = typename Cont::size_type;
658 auto const hash(c.hash_function());
659 auto const key_eq(c.key_eq());
660 for (size_type i(0); i < c.bucket_count(); ++i)
661 {
662 auto const last(c.end(i));
663 for (auto iter(c.begin(i)); iter != last; ++iter)
664 {
665 auto const match(std::find_if(
666 v.begin(),
667 v.end(),
668 [iter](typename Values::value_type const& e) {
669 return Traits::extract(*iter) == Traits::extract(e);
670 }));
671 BEAST_EXPECT(match != v.end());
672 BEAST_EXPECT(
673 key_eq(Traits::extract(*iter), Traits::extract(*match)));
674 BEAST_EXPECT(
675 hash(Traits::extract(*iter)) == hash(Traits::extract(*match)));
676 }
677 }
678}
679
680template <class C, class Values>
681void
683 C&& c,
684 Values const& v)
685{
686 using Cont = typename std::remove_reference<C>::type;
687 using size_type = typename Cont::size_type;
688
689 BEAST_EXPECT(c.size() == v.size());
690 BEAST_EXPECT(size_type(std::distance(c.begin(), c.end())) == v.size());
691 BEAST_EXPECT(size_type(std::distance(c.cbegin(), c.cend())) == v.size());
692 BEAST_EXPECT(
693 size_type(std::distance(
694 c.chronological.begin(), c.chronological.end())) == v.size());
695 BEAST_EXPECT(
696 size_type(std::distance(
697 c.chronological.cbegin(), c.chronological.cend())) == v.size());
698 BEAST_EXPECT(
699 size_type(std::distance(
700 c.chronological.rbegin(), c.chronological.rend())) == v.size());
701 BEAST_EXPECT(
702 size_type(std::distance(
703 c.chronological.crbegin(), c.chronological.crend())) == v.size());
704
706}
707
708template <class Cont, class Values>
709void
711{
713 checkContentsRefRef(const_cast<Cont const&>(c), v);
714 checkMapContents(c, v);
715}
716
717template <class Cont>
718void
720{
721 using Traits = TestTraits<
722 Cont::is_unordered::value,
723 Cont::is_multi::value,
724 Cont::is_map::value>;
725 using Values = typename Traits::Values;
726 checkContents(c, Values());
727}
728
729//------------------------------------------------------------------------------
730//
731// Construction
732//
733//------------------------------------------------------------------------------
734
735// ordered
736template <bool IsUnordered, bool IsMulti, bool IsMap>
739{
741 using Comp = typename Traits::Comp;
742 using Alloc = typename Traits::Alloc;
743 using MyComp = typename Traits::MyComp;
744 using MyAlloc = typename Traits::MyAlloc;
745 typename Traits::ManualClock clock;
746
747 // testcase (Traits::name() + " empty");
748 testcase("empty");
749
750 {
751 typename Traits::template Cont<Comp, Alloc> c(clock);
752 checkContents(c);
753 }
754
755 {
756 typename Traits::template Cont<MyComp, Alloc> c(clock, MyComp(1));
757 checkContents(c);
758 }
759
760 {
761 typename Traits::template Cont<Comp, MyAlloc> c(clock, MyAlloc(1));
762 checkContents(c);
763 }
764
765 {
766 typename Traits::template Cont<MyComp, MyAlloc> c(
767 clock, MyComp(1), MyAlloc(1));
768 checkContents(c);
769 }
770}
771
772// unordered
773template <bool IsUnordered, bool IsMulti, bool IsMap>
776{
777 using Traits = TestTraits<IsUnordered, IsMulti, IsMap>;
778 using Hash = typename Traits::Hash;
779 using Equal = typename Traits::Equal;
780 using Alloc = typename Traits::Alloc;
781 using MyHash = typename Traits::MyHash;
782 using MyEqual = typename Traits::MyEqual;
783 using MyAlloc = typename Traits::MyAlloc;
784 typename Traits::ManualClock clock;
785
786 // testcase (Traits::name() + " empty");
787 testcase("empty");
788 {
789 typename Traits::template Cont<Hash, Equal, Alloc> c(clock);
790 checkContents(c);
791 }
792
793 {
794 typename Traits::template Cont<MyHash, Equal, Alloc> c(
795 clock, MyHash(1));
796 checkContents(c);
797 }
798
799 {
800 typename Traits::template Cont<Hash, MyEqual, Alloc> c(
801 clock, MyEqual(1));
802 checkContents(c);
803 }
804
805 {
806 typename Traits::template Cont<Hash, Equal, MyAlloc> c(
807 clock, MyAlloc(1));
808 checkContents(c);
809 }
810
811 {
812 typename Traits::template Cont<MyHash, MyEqual, Alloc> c(
813 clock, MyHash(1), MyEqual(1));
814 checkContents(c);
815 }
816
817 {
818 typename Traits::template Cont<MyHash, Equal, MyAlloc> c(
819 clock, MyHash(1), MyAlloc(1));
820 checkContents(c);
821 }
822
823 {
824 typename Traits::template Cont<Hash, MyEqual, MyAlloc> c(
825 clock, MyEqual(1), MyAlloc(1));
826 checkContents(c);
827 }
828
829 {
830 typename Traits::template Cont<MyHash, MyEqual, MyAlloc> c(
831 clock, MyHash(1), MyEqual(1), MyAlloc(1));
832 checkContents(c);
833 }
834}
835
836// ordered
837template <bool IsUnordered, bool IsMulti, bool IsMap>
840{
842 using Comp = typename Traits::Comp;
843 using Alloc = typename Traits::Alloc;
844 using MyComp = typename Traits::MyComp;
845 using MyAlloc = typename Traits::MyAlloc;
846 typename Traits::ManualClock clock;
847 auto const v(Traits::values());
848
849 // testcase (Traits::name() + " range");
850 testcase("range");
851
852 {
853 typename Traits::template Cont<Comp, Alloc> c(
854 v.begin(), v.end(), clock);
855 checkContents(c, v);
856 }
857
858 {
859 typename Traits::template Cont<MyComp, Alloc> c(
860 v.begin(), v.end(), clock, MyComp(1));
861 checkContents(c, v);
862 }
863
864 {
865 typename Traits::template Cont<Comp, MyAlloc> c(
866 v.begin(), v.end(), clock, MyAlloc(1));
867 checkContents(c, v);
868 }
869
870 {
871 typename Traits::template Cont<MyComp, MyAlloc> c(
872 v.begin(), v.end(), clock, MyComp(1), MyAlloc(1));
873 checkContents(c, v);
874 }
875
876 // swap
877
878 {
879 typename Traits::template Cont<Comp, Alloc> c1(
880 v.begin(), v.end(), clock);
881 typename Traits::template Cont<Comp, Alloc> c2(clock);
882 std::swap(c1, c2);
883 checkContents(c2, v);
884 }
885}
886
887// unordered
888template <bool IsUnordered, bool IsMulti, bool IsMap>
891{
892 using Traits = TestTraits<IsUnordered, IsMulti, IsMap>;
893 using Hash = typename Traits::Hash;
894 using Equal = typename Traits::Equal;
895 using Alloc = typename Traits::Alloc;
896 using MyHash = typename Traits::MyHash;
897 using MyEqual = typename Traits::MyEqual;
898 using MyAlloc = typename Traits::MyAlloc;
899 typename Traits::ManualClock clock;
900 auto const v(Traits::values());
901
902 // testcase (Traits::name() + " range");
903 testcase("range");
904
905 {
906 typename Traits::template Cont<Hash, Equal, Alloc> c(
907 v.begin(), v.end(), clock);
908 checkContents(c, v);
909 }
910
911 {
912 typename Traits::template Cont<MyHash, Equal, Alloc> c(
913 v.begin(), v.end(), clock, MyHash(1));
914 checkContents(c, v);
915 }
916
917 {
918 typename Traits::template Cont<Hash, MyEqual, Alloc> c(
919 v.begin(), v.end(), clock, MyEqual(1));
920 checkContents(c, v);
921 }
922
923 {
924 typename Traits::template Cont<Hash, Equal, MyAlloc> c(
925 v.begin(), v.end(), clock, MyAlloc(1));
926 checkContents(c, v);
927 }
928
929 {
930 typename Traits::template Cont<MyHash, MyEqual, Alloc> c(
931 v.begin(), v.end(), clock, MyHash(1), MyEqual(1));
932 checkContents(c, v);
933 }
934
935 {
936 typename Traits::template Cont<MyHash, Equal, MyAlloc> c(
937 v.begin(), v.end(), clock, MyHash(1), MyAlloc(1));
938 checkContents(c, v);
939 }
940
941 {
942 typename Traits::template Cont<Hash, MyEqual, MyAlloc> c(
943 v.begin(), v.end(), clock, MyEqual(1), MyAlloc(1));
944 checkContents(c, v);
945 }
946
947 {
948 typename Traits::template Cont<MyHash, MyEqual, MyAlloc> c(
949 v.begin(), v.end(), clock, MyHash(1), MyEqual(1), MyAlloc(1));
950 checkContents(c, v);
951 }
952}
953
954// ordered
955template <bool IsUnordered, bool IsMulti, bool IsMap>
958{
960 typename Traits::ManualClock clock;
961
962 // testcase (Traits::name() + " init-list");
963 testcase("init-list");
964
965 // VFALCO TODO
966
967 pass();
968}
969
970// unordered
971template <bool IsUnordered, bool IsMulti, bool IsMap>
974{
975 using Traits = TestTraits<IsUnordered, IsMulti, IsMap>;
976 typename Traits::ManualClock clock;
977
978 // testcase (Traits::name() + " init-list");
979 testcase("init-list");
980
981 // VFALCO TODO
982 pass();
983}
984
985//------------------------------------------------------------------------------
986//
987// Copy/Move construction and assign
988//
989//------------------------------------------------------------------------------
990
991template <bool IsUnordered, bool IsMulti, bool IsMap>
992void
994{
996 using Alloc = typename Traits::Alloc;
997 typename Traits::ManualClock clock;
998 auto const v(Traits::values());
999
1000 // testcase (Traits::name() + " copy/move");
1001 testcase("copy/move");
1002
1003 // copy
1004
1005 {
1006 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1007 typename Traits::template Cont<> c2(c);
1008 checkContents(c, v);
1009 checkContents(c2, v);
1010 BEAST_EXPECT(c == c2);
1011 unexpected(c != c2);
1012 }
1013
1014 {
1015 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1016 typename Traits::template Cont<> c2(c, Alloc());
1017 checkContents(c, v);
1018 checkContents(c2, v);
1019 BEAST_EXPECT(c == c2);
1020 unexpected(c != c2);
1021 }
1022
1023 {
1024 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1025 typename Traits::template Cont<> c2(clock);
1026 c2 = c;
1027 checkContents(c, v);
1028 checkContents(c2, v);
1029 BEAST_EXPECT(c == c2);
1030 unexpected(c != c2);
1031 }
1032
1033 // move
1034
1035 {
1036 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1037 typename Traits::template Cont<> c2(std::move(c));
1038 checkContents(c2, v);
1039 }
1040
1041 {
1042 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1043 typename Traits::template Cont<> c2(std::move(c), Alloc());
1044 checkContents(c2, v);
1045 }
1046
1047 {
1048 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1049 typename Traits::template Cont<> c2(clock);
1050 c2 = std::move(c);
1051 checkContents(c2, v);
1052 }
1053}
1054
1055//------------------------------------------------------------------------------
1056//
1057// Iterator construction and assignment
1058//
1059//------------------------------------------------------------------------------
1060
1061template <bool IsUnordered, bool IsMulti, bool IsMap>
1062void
1064{
1066 typename Traits::ManualClock clock;
1067 auto const v(Traits::values());
1068
1069 // testcase (Traits::name() + " iterators");
1070 testcase("iterator");
1071
1072 typename Traits::template Cont<> c{clock};
1073
1074 using iterator = decltype(c.begin());
1075 using const_iterator = decltype(c.cbegin());
1076
1077 // Should be able to construct or assign an iterator from an iterator.
1078 iterator nnIt_0{c.begin()};
1079 iterator nnIt_1{nnIt_0};
1080 BEAST_EXPECT(nnIt_0 == nnIt_1);
1081 iterator nnIt_2;
1082 nnIt_2 = nnIt_1;
1083 BEAST_EXPECT(nnIt_1 == nnIt_2);
1084
1085 // Should be able to construct or assign a const_iterator from a
1086 // const_iterator.
1087 const_iterator ccIt_0{c.cbegin()};
1088 const_iterator ccIt_1{ccIt_0};
1089 BEAST_EXPECT(ccIt_0 == ccIt_1);
1090 const_iterator ccIt_2;
1091 ccIt_2 = ccIt_1;
1092 BEAST_EXPECT(ccIt_1 == ccIt_2);
1093
1094 // Comparison between iterator and const_iterator is okay
1095 BEAST_EXPECT(nnIt_0 == ccIt_0);
1096 BEAST_EXPECT(ccIt_1 == nnIt_1);
1097
1098 // Should be able to construct a const_iterator from an iterator.
1099 const_iterator ncIt_3{c.begin()};
1100 const_iterator ncIt_4{nnIt_0};
1101 BEAST_EXPECT(ncIt_3 == ncIt_4);
1102 const_iterator ncIt_5;
1103 ncIt_5 = nnIt_2;
1104 BEAST_EXPECT(ncIt_5 == ncIt_4);
1105
1106 // None of these should compile because they construct or assign to a
1107 // non-const iterator with a const_iterator.
1108
1109 // iterator cnIt_0 {c.cbegin()};
1110
1111 // iterator cnIt_1 {ccIt_0};
1112
1113 // iterator cnIt_2;
1114 // cnIt_2 = ccIt_2;
1115}
1116
1117template <bool IsUnordered, bool IsMulti, bool IsMap>
1120{
1122 typename Traits::ManualClock clock;
1123 auto const v(Traits::values());
1124
1125 // testcase (Traits::name() + " reverse_iterators");
1126 testcase("reverse_iterator");
1127
1128 typename Traits::template Cont<> c{clock};
1129
1130 using iterator = decltype(c.begin());
1131 using reverse_iterator = decltype(c.rbegin());
1132 using const_reverse_iterator = decltype(c.crbegin());
1133
1134 // Naming decoder ring
1135 // constructed from ------+ +----- constructed type
1136 // /\/\ -- character pairs
1137 // xAyBit
1138 // r (reverse) or f (forward)--^-^
1139 // ^-^------ C (const) or N (non-const)
1140
1141 // Should be able to construct or assign a reverse_iterator from a
1142 // reverse_iterator.
1143 reverse_iterator rNrNit_0{c.rbegin()};
1144 reverse_iterator rNrNit_1{rNrNit_0};
1145 BEAST_EXPECT(rNrNit_0 == rNrNit_1);
1146 reverse_iterator xXrNit_2;
1147 xXrNit_2 = rNrNit_1;
1148 BEAST_EXPECT(rNrNit_1 == xXrNit_2);
1149
1150 // Should be able to construct or assign a const_reverse_iterator from a
1151 // const_reverse_iterator
1152 const_reverse_iterator rCrCit_0{c.crbegin()};
1153 const_reverse_iterator rCrCit_1{rCrCit_0};
1154 BEAST_EXPECT(rCrCit_0 == rCrCit_1);
1155 const_reverse_iterator xXrCit_2;
1156 xXrCit_2 = rCrCit_1;
1157 BEAST_EXPECT(rCrCit_1 == xXrCit_2);
1158
1159 // Comparison between reverse_iterator and const_reverse_iterator is okay
1160 BEAST_EXPECT(rNrNit_0 == rCrCit_0);
1161 BEAST_EXPECT(rCrCit_1 == rNrNit_1);
1162
1163 // Should be able to construct or assign a const_reverse_iterator from a
1164 // reverse_iterator
1165 const_reverse_iterator rNrCit_0{c.rbegin()};
1166 const_reverse_iterator rNrCit_1{rNrNit_0};
1167 BEAST_EXPECT(rNrCit_0 == rNrCit_1);
1168 xXrCit_2 = rNrNit_1;
1169 BEAST_EXPECT(rNrCit_1 == xXrCit_2);
1170
1171 // The standard allows these conversions:
1172 // o reverse_iterator is explicitly constructible from iterator.
1173 // o const_reverse_iterator is explicitly constructible from
1174 // const_iterator.
1175 // Should be able to construct or assign reverse_iterators from
1176 // non-reverse iterators.
1177 reverse_iterator fNrNit_0{c.begin()};
1178 const_reverse_iterator fNrCit_0{c.begin()};
1179 BEAST_EXPECT(fNrNit_0 == fNrCit_0);
1180 const_reverse_iterator fCrCit_0{c.cbegin()};
1181 BEAST_EXPECT(fNrCit_0 == fCrCit_0);
1182
1183 // None of these should compile because they construct a non-reverse
1184 // iterator from a reverse_iterator.
1185 // iterator rNfNit_0 {c.rbegin()};
1186 // const_iterator rNfCit_0 {c.rbegin()};
1187 // const_iterator rCfCit_0 {c.crbegin()};
1188
1189 // You should not be able to assign an iterator to a reverse_iterator or
1190 // vise-versa. So the following lines should not compile.
1191 iterator xXfNit_0;
1192 // xXfNit_0 = xXrNit_2;
1193 // xXrNit_2 = xXfNit_0;
1194}
1195
1196//------------------------------------------------------------------------------
1197//
1198// Modifiers
1199//
1200//------------------------------------------------------------------------------
1201
1202template <class Container, class Values>
1203void
1205 Container& c,
1206 Values const& v)
1207{
1208 for (auto const& e : v)
1209 c.insert(e);
1210 checkContents(c, v);
1211}
1212
1213template <class Container, class Values>
1214void
1216 Container& c,
1217 Values const& v)
1218{
1219 Values v2(v);
1220 for (auto& e : v2)
1221 c.insert(std::move(e));
1222 checkContents(c, v);
1223}
1224
1225template <class Container, class Values>
1226void
1228 Container& c,
1229 Values const& v)
1230{
1231 for (auto const& e : v)
1232 c.insert(c.cend(), e);
1233 checkContents(c, v);
1234}
1235
1236template <class Container, class Values>
1237void
1239 Container& c,
1240 Values const& v)
1241{
1242 Values v2(v);
1243 for (auto& e : v2)
1244 c.insert(c.cend(), std::move(e));
1245 checkContents(c, v);
1246}
1247
1248template <class Container, class Values>
1249void
1251 Container& c,
1252 Values const& v)
1253{
1254 for (auto const& e : v)
1255 c.emplace(e);
1256 checkContents(c, v);
1257}
1258
1259template <class Container, class Values>
1260void
1262 Container& c,
1263 Values const& v)
1264{
1265 for (auto const& e : v)
1266 c.emplace_hint(c.cend(), e);
1267 checkContents(c, v);
1268}
1269
1270template <bool IsUnordered, bool IsMulti, bool IsMap>
1271void
1273{
1275 typename Traits::ManualClock clock;
1276 auto const v(Traits::values());
1277 auto const l(make_list(v));
1278
1279 // testcase (Traits::name() + " modify");
1280 testcase("modify");
1281
1282 {
1283 typename Traits::template Cont<> c(clock);
1284 checkInsertCopy(c, v);
1285 }
1286
1287 {
1288 typename Traits::template Cont<> c(clock);
1289 checkInsertCopy(c, l);
1290 }
1291
1292 {
1293 typename Traits::template Cont<> c(clock);
1294 checkInsertMove(c, v);
1295 }
1296
1297 {
1298 typename Traits::template Cont<> c(clock);
1299 checkInsertMove(c, l);
1300 }
1301
1302 {
1303 typename Traits::template Cont<> c(clock);
1304 checkInsertHintCopy(c, v);
1305 }
1306
1307 {
1308 typename Traits::template Cont<> c(clock);
1309 checkInsertHintCopy(c, l);
1310 }
1311
1312 {
1313 typename Traits::template Cont<> c(clock);
1314 checkInsertHintMove(c, v);
1315 }
1316
1317 {
1318 typename Traits::template Cont<> c(clock);
1319 checkInsertHintMove(c, l);
1320 }
1321}
1322
1323//------------------------------------------------------------------------------
1324//
1325// Chronological ordering
1326//
1327//------------------------------------------------------------------------------
1328
1329template <bool IsUnordered, bool IsMulti, bool IsMap>
1330void
1332{
1334 typename Traits::ManualClock clock;
1335 auto const v(Traits::values());
1336
1337 // testcase (Traits::name() + " chronological");
1338 testcase("chronological");
1339
1340 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1341
1342 BEAST_EXPECT(std::equal(
1343 c.chronological.cbegin(),
1344 c.chronological.cend(),
1345 v.begin(),
1346 v.end(),
1348
1349 // Test touch() with a non-const iterator.
1350 for (auto iter(v.crbegin()); iter != v.crend(); ++iter)
1351 {
1352 using iterator = typename decltype(c)::iterator;
1353 iterator found(c.find(Traits::extract(*iter)));
1354
1355 BEAST_EXPECT(found != c.cend());
1356 if (found == c.cend())
1357 return;
1358 c.touch(found);
1359 }
1360
1361 BEAST_EXPECT(std::equal(
1362 c.chronological.cbegin(),
1363 c.chronological.cend(),
1364 v.crbegin(),
1365 v.crend(),
1367
1368 // Test touch() with a const_iterator
1369 for (auto iter(v.cbegin()); iter != v.cend(); ++iter)
1370 {
1371 using const_iterator = typename decltype(c)::const_iterator;
1372 const_iterator found(c.find(Traits::extract(*iter)));
1373
1374 BEAST_EXPECT(found != c.cend());
1375 if (found == c.cend())
1376 return;
1377 c.touch(found);
1378 }
1379
1380 BEAST_EXPECT(std::equal(
1381 c.chronological.cbegin(),
1382 c.chronological.cend(),
1383 v.cbegin(),
1384 v.cend(),
1386
1387 {
1388 // Because touch (reverse_iterator pos) is not allowed, the following
1389 // lines should not compile for any aged_container type.
1390 // c.touch (c.rbegin());
1391 // c.touch (c.crbegin());
1392 }
1393}
1394
1395//------------------------------------------------------------------------------
1396//
1397// Element creation via operator[]
1398//
1399//------------------------------------------------------------------------------
1400
1401// map, unordered_map
1402template <bool IsUnordered, bool IsMulti, bool IsMap>
1405{
1407 typename Traits::ManualClock clock;
1408 auto v(Traits::values());
1409
1410 // testcase (Traits::name() + " array create");
1411 testcase("array create");
1412
1413 {
1414 // Copy construct key
1415 typename Traits::template Cont<> c(clock);
1416 for (auto e : v)
1417 c[e.first] = e.second;
1418 checkContents(c, v);
1419 }
1420
1421 {
1422 // Move construct key
1423 typename Traits::template Cont<> c(clock);
1424 for (auto e : v)
1425 c[std::move(e.first)] = e.second;
1426 checkContents(c, v);
1427 }
1428}
1429
1430//------------------------------------------------------------------------------
1431//
1432// Helpers for erase tests
1433//
1434//------------------------------------------------------------------------------
1435
1436template <class Container, class Values>
1437void
1439 Container& c,
1440 Values const& values)
1441{
1442 // Just in case the passed in container was not empty.
1443 c.clear();
1444
1445 // c.clock() returns an abstract_clock, so dynamic_cast to manual_clock.
1446 // VFALCO NOTE This is sketchy
1447 using ManualClock = TestTraitsBase::ManualClock;
1448 ManualClock& clk(dynamic_cast<ManualClock&>(c.clock()));
1449 clk.set(0);
1450
1451 Values rev(values);
1452 std::sort(rev.begin(), rev.end());
1453 std::reverse(rev.begin(), rev.end());
1454 for (auto& v : rev)
1455 {
1456 // Add values in reverse order so they are reversed chronologically.
1457 ++clk;
1458 c.insert(v);
1459 }
1460}
1461
1462// Get one iterator before endIter. We have to use operator++ because you
1463// cannot use operator-- with unordered container iterators.
1464template <class Iter>
1465Iter
1467 Iter beginIter,
1468 Iter const endIter)
1469{
1470 if (beginIter == endIter)
1471 {
1472 fail("Internal test failure. Cannot advance beginIter");
1473 return beginIter;
1474 }
1475
1476 //
1477 Iter nextToEnd = beginIter;
1478 do
1479 {
1480 nextToEnd = beginIter++;
1481 } while (beginIter != endIter);
1482 return nextToEnd;
1483}
1484
1485// Implementation for the element erase tests
1486//
1487// This test accepts:
1488// o the container from which we will erase elements
1489// o iterators into that container defining the range of the erase
1490//
1491// This implementation does not declare a pass, since it wants to allow
1492// the caller to examine the size of the container and the returned iterator
1493//
1494// Note that this test works on the aged_associative containers because an
1495// erase only invalidates references and iterators to the erased element
1496// (see 23.2.4/13). Therefore the passed-in end iterator stays valid through
1497// the whole test.
1498template <class Container, class Iter>
1499bool
1501 Container& c,
1502 Iter const beginItr,
1503 Iter const endItr)
1504{
1505 auto it(beginItr);
1506 size_t count = c.size();
1507 while (it != endItr)
1508 {
1509 auto expectIt = it;
1510 ++expectIt;
1511 it = c.erase(it);
1512
1513 if (it != expectIt)
1514 {
1515 fail("Unexpected returned iterator from element erase");
1516 return false;
1517 }
1518
1519 --count;
1520 if (count != c.size())
1521 {
1522 fail("Failed to erase element");
1523 return false;
1524 }
1525
1526 if (c.empty())
1527 {
1528 if (it != endItr)
1529 {
1530 fail("Erase of last element didn't produce end");
1531 return false;
1532 }
1533 }
1534 }
1535 return true;
1536}
1537
1538//------------------------------------------------------------------------------
1539//
1540// Erase of individual elements
1541//
1542//------------------------------------------------------------------------------
1543
1544template <bool IsUnordered, bool IsMulti, bool IsMap>
1545void
1547{
1549
1550 // testcase (Traits::name() + " element erase"
1551 testcase("element erase");
1552
1553 // Make and fill the container
1554 typename Traits::ManualClock clock;
1555 typename Traits::template Cont<> c{clock};
1556 reverseFillAgedContainer(c, Traits::values());
1557
1558 {
1559 // Test standard iterators
1560 auto tempContainer(c);
1561 if (!doElementErase(
1562 tempContainer, tempContainer.cbegin(), tempContainer.cend()))
1563 return; // Test failed
1564
1565 BEAST_EXPECT(tempContainer.empty());
1566 pass();
1567 }
1568 {
1569 // Test chronological iterators
1570 auto tempContainer(c);
1571 auto& chron(tempContainer.chronological);
1572 if (!doElementErase(tempContainer, chron.begin(), chron.end()))
1573 return; // Test failed
1574
1575 BEAST_EXPECT(tempContainer.empty());
1576 pass();
1577 }
1578 {
1579 // Test standard iterator partial erase
1580 auto tempContainer(c);
1581 BEAST_EXPECT(tempContainer.size() > 2);
1582 if (!doElementErase(
1583 tempContainer,
1584 ++tempContainer.begin(),
1585 nextToEndIter(tempContainer.begin(), tempContainer.end())))
1586 return; // Test failed
1587
1588 BEAST_EXPECT(tempContainer.size() == 2);
1589 pass();
1590 }
1591 {
1592 // Test chronological iterator partial erase
1593 auto tempContainer(c);
1594 BEAST_EXPECT(tempContainer.size() > 2);
1595 auto& chron(tempContainer.chronological);
1596 if (!doElementErase(
1597 tempContainer,
1598 ++chron.begin(),
1599 nextToEndIter(chron.begin(), chron.end())))
1600 return; // Test failed
1601
1602 BEAST_EXPECT(tempContainer.size() == 2);
1603 pass();
1604 }
1605 {
1606 auto tempContainer(c);
1607 BEAST_EXPECT(tempContainer.size() > 4);
1608 // erase(reverse_iterator) is not allowed. None of the following
1609 // should compile for any aged_container type.
1610 // c.erase (c.rbegin());
1611 // c.erase (c.crbegin());
1612 // c.erase(c.rbegin(), ++c.rbegin());
1613 // c.erase(c.crbegin(), ++c.crbegin());
1614 }
1615}
1616
1617// Implementation for the range erase tests
1618//
1619// This test accepts:
1620//
1621// o A container with more than 2 elements and
1622// o An object to ask for begin() and end() iterators in the passed container
1623//
1624// This peculiar interface allows either the container itself to be passed as
1625// the second argument or the container's "chronological" element. Both
1626// sources of iterators need to be tested on the container.
1627//
1628// The test locates iterators such that a range-based delete leaves the first
1629// and last elements in the container. It then validates that the container
1630// ended up with the expected contents.
1631//
1632template <class Container, class BeginEndSrc>
1633void
1635 Container& c,
1636 BeginEndSrc const& beginEndSrc)
1637{
1638 BEAST_EXPECT(c.size() > 2);
1639 auto itBeginPlusOne(beginEndSrc.begin());
1640 auto const valueFront = *itBeginPlusOne;
1641 ++itBeginPlusOne;
1642
1643 // Get one iterator before end()
1644 auto itBack(nextToEndIter(itBeginPlusOne, beginEndSrc.end()));
1645 auto const valueBack = *itBack;
1646
1647 // Erase all elements but first and last
1648 auto const retIter = c.erase(itBeginPlusOne, itBack);
1649
1650 BEAST_EXPECT(c.size() == 2);
1651 BEAST_EXPECT(valueFront == *(beginEndSrc.begin()));
1652 BEAST_EXPECT(valueBack == *(++beginEndSrc.begin()));
1653 BEAST_EXPECT(retIter == (++beginEndSrc.begin()));
1654}
1655
1656//------------------------------------------------------------------------------
1657//
1658// Erase range of elements
1659//
1660//------------------------------------------------------------------------------
1661
1662template <bool IsUnordered, bool IsMulti, bool IsMap>
1663void
1665{
1667
1668 // testcase (Traits::name() + " element erase"
1669 testcase("range erase");
1670
1671 // Make and fill the container
1672 typename Traits::ManualClock clock;
1673 typename Traits::template Cont<> c{clock};
1674 reverseFillAgedContainer(c, Traits::values());
1675
1676 // Not bothering to test range erase with reverse iterators.
1677 {
1678 auto tempContainer(c);
1679 doRangeErase(tempContainer, tempContainer);
1680 }
1681 {
1682 auto tempContainer(c);
1683 doRangeErase(tempContainer, tempContainer.chronological);
1684 }
1685}
1686
1687//------------------------------------------------------------------------------
1688//
1689// Container-wide comparison
1690//
1691//------------------------------------------------------------------------------
1692
1693// ordered
1694template <bool IsUnordered, bool IsMulti, bool IsMap>
1697{
1699 typename Traits::ManualClock clock;
1700 auto const v(Traits::values());
1701
1702 // testcase (Traits::name() + " array create");
1703 testcase("array create");
1704
1705 typename Traits::template Cont<> c1(v.begin(), v.end(), clock);
1706
1707 typename Traits::template Cont<> c2(v.begin(), v.end(), clock);
1708 c2.erase(c2.cbegin());
1709
1710 expect(c1 != c2);
1711 unexpected(c1 == c2);
1712 expect(c1 < c2);
1713 expect(c1 <= c2);
1714 unexpected(c1 > c2);
1715 unexpected(c1 >= c2);
1716}
1717
1718//------------------------------------------------------------------------------
1719//
1720// Observers
1721//
1722//------------------------------------------------------------------------------
1723
1724// ordered
1725template <bool IsUnordered, bool IsMulti, bool IsMap>
1728{
1730 typename Traits::ManualClock clock;
1731
1732 // testcase (Traits::name() + " observers");
1733 testcase("observers");
1734
1735 typename Traits::template Cont<> c(clock);
1736 c.key_comp();
1737 c.value_comp();
1738
1739 pass();
1740}
1741
1742// unordered
1743template <bool IsUnordered, bool IsMulti, bool IsMap>
1746{
1747 using Traits = TestTraits<IsUnordered, IsMulti, IsMap>;
1748 typename Traits::ManualClock clock;
1749
1750 // testcase (Traits::name() + " observers");
1751 testcase("observers");
1752
1753 typename Traits::template Cont<> c(clock);
1754 c.hash_function();
1755 c.key_eq();
1756
1757 pass();
1758}
1759
1760//------------------------------------------------------------------------------
1761//
1762// Matrix
1763//
1764//------------------------------------------------------------------------------
1765
1766template <bool IsUnordered, bool IsMulti, bool IsMap>
1767void
1769{
1770 testConstructEmpty<IsUnordered, IsMulti, IsMap>();
1771 testConstructRange<IsUnordered, IsMulti, IsMap>();
1772 testConstructInitList<IsUnordered, IsMulti, IsMap>();
1773 testCopyMove<IsUnordered, IsMulti, IsMap>();
1774 testIterator<IsUnordered, IsMulti, IsMap>();
1775 testReverseIterator<IsUnordered, IsMulti, IsMap>();
1776 testModifiers<IsUnordered, IsMulti, IsMap>();
1777 testChronological<IsUnordered, IsMulti, IsMap>();
1778 testArrayCreate<IsUnordered, IsMulti, IsMap>();
1779 testElementErase<IsUnordered, IsMulti, IsMap>();
1780 testRangeErase<IsUnordered, IsMulti, IsMap>();
1781 testCompare<IsUnordered, IsMulti, IsMap>();
1782 testObservers<IsUnordered, IsMulti, IsMap>();
1783}
1784
1785//------------------------------------------------------------------------------
1786
1788{
1789public:
1790 // Compile time checks
1791
1793 using T = int;
1794
1795 static_assert(
1799 "bad alias: aged_set");
1800
1801 static_assert(
1805 "bad alias: aged_multiset");
1806
1807 static_assert(
1811 "bad alias: aged_map");
1812
1813 static_assert(
1817 "bad alias: aged_multimap");
1818
1819 static_assert(
1823 "bad alias: aged_unordered_set");
1824
1825 static_assert(
1829 "bad alias: aged_unordered_multiset");
1830
1831 static_assert(
1835 "bad alias: aged_unordered_map");
1836
1837 static_assert(
1841 "bad alias: aged_unordered_multimap");
1842
1843 void
1844 run() override
1845 {
1846 testMaybeUnorderedMultiMap<false, false, false>();
1847 }
1848};
1849
1851{
1852public:
1853 void
1854 run() override
1855 {
1856 testMaybeUnorderedMultiMap<false, false, true>();
1857 }
1858};
1859
1861{
1862public:
1863 void
1864 run() override
1865 {
1866 testMaybeUnorderedMultiMap<false, true, false>();
1867 }
1868};
1869
1871{
1872public:
1873 void
1874 run() override
1875 {
1876 testMaybeUnorderedMultiMap<false, true, true>();
1877 }
1878};
1879
1881{
1882public:
1883 void
1884 run() override
1885 {
1886 testMaybeUnorderedMultiMap<true, false, false>();
1887 }
1888};
1889
1891{
1892public:
1893 void
1894 run() override
1895 {
1896 testMaybeUnorderedMultiMap<true, false, true>();
1897 }
1898};
1899
1901{
1902public:
1903 void
1904 run() override
1905 {
1906 testMaybeUnorderedMultiMap<true, true, false>();
1907 }
1908};
1909
1911{
1912public:
1913 void
1914 run() override
1915 {
1916 testMaybeUnorderedMultiMap<true, true, true>();
1917 }
1918};
1919
1920BEAST_DEFINE_TESTSUITE(aged_set, beast, beast);
1921BEAST_DEFINE_TESTSUITE(aged_map, beast, beast);
1922BEAST_DEFINE_TESTSUITE(aged_multiset, beast, beast);
1923BEAST_DEFINE_TESTSUITE(aged_multimap, beast, beast);
1924BEAST_DEFINE_TESTSUITE(aged_unordered_set, beast, beast);
1925BEAST_DEFINE_TESTSUITE(aged_unordered_map, beast, beast);
1926BEAST_DEFINE_TESTSUITE(aged_unordered_multiset, beast, beast);
1927BEAST_DEFINE_TESTSUITE(aged_unordered_multimap, beast, beast);
1928
1929} // namespace beast
std::enable_if< IsMap &&!IsMulti >::type testArrayCreate()
std::enable_if<!std::remove_reference< C >::type::is_unordered::value >::type checkUnorderedContentsRefRef(C &&, Values const &)
std::enable_if<!(Container::is_map::value &&!Container::is_multi::value)>::type checkMapContents(Container, Values const &)
static std::vector< typename Cont::value_type > make_list(Cont const &c)
std::enable_if< Container::is_map::value &&!Container::is_multi::value >::type checkMapContents(Container &c, Values const &v)
bool doElementErase(Container &c, Iter const beginItr, Iter const endItr)
Iter nextToEndIter(Iter const beginIter, Iter const endItr)
std::enable_if< std::remove_reference< C >::type::is_unordered::value >::type checkUnorderedContentsRefRef(C &&c, Values const &v)
std::enable_if<!IsUnordered >::type testConstructInitList()
std::enable_if<!(IsMap &&!IsMulti)>::type testArrayCreate()
void doRangeErase(Container &c, BeginEndSrc const &beginEndSrc)
void run() override
Runs the suite.
void run() override
Runs the suite.
Associative container where each element is also indexed by time.
Associative container where each element is also indexed by time.
Manual clock implementation.
A testsuite class.
Definition suite.h:52
void pass()
Record a successful test condition.
Definition suite.h:508
bool unexpected(Condition shouldBeFalse, String const &reason)
Definition suite.h:496
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:226
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition suite.h:530
T distance(T... args)
T equal(T... args)
T find_if(T... args)
T is_same_v
T make_pair(T... args)
T reverse(T... args)
T sort(T... args)
bool operator()(typename Traits::Value const &lhs, typename Traits::Value const &rhs)
T swap(T... args)