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