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