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