1*51c0b2f7Stbbdev /* 2*51c0b2f7Stbbdev Copyright (c) 2019-2020 Intel Corporation 3*51c0b2f7Stbbdev 4*51c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License"); 5*51c0b2f7Stbbdev you may not use this file except in compliance with the License. 6*51c0b2f7Stbbdev You may obtain a copy of the License at 7*51c0b2f7Stbbdev 8*51c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0 9*51c0b2f7Stbbdev 10*51c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software 11*51c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS, 12*51c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*51c0b2f7Stbbdev See the License for the specific language governing permissions and 14*51c0b2f7Stbbdev limitations under the License. 15*51c0b2f7Stbbdev */ 16*51c0b2f7Stbbdev 17*51c0b2f7Stbbdev #ifndef __TBB_test_common_concurrent_ordered_common_H 18*51c0b2f7Stbbdev #define __TBB_test_common_concurrent_ordered_common_H 19*51c0b2f7Stbbdev 20*51c0b2f7Stbbdev #include "common/concurrent_associative_common.h" 21*51c0b2f7Stbbdev #include "test_comparisons.h" 22*51c0b2f7Stbbdev 23*51c0b2f7Stbbdev template<typename MyTable> 24*51c0b2f7Stbbdev inline void CheckContainerAllocator(MyTable &table, size_t expected_allocs, size_t expected_frees, bool exact) { 25*51c0b2f7Stbbdev typename MyTable::allocator_type a = table.get_allocator(); 26*51c0b2f7Stbbdev CheckAllocator<MyTable>(a, expected_allocs, expected_frees, exact); 27*51c0b2f7Stbbdev } 28*51c0b2f7Stbbdev 29*51c0b2f7Stbbdev template<typename Container> 30*51c0b2f7Stbbdev inline void CheckNoAllocations(Container&) { 31*51c0b2f7Stbbdev // TODO: enable 32*51c0b2f7Stbbdev // CheckContainerAllocator(cont, 0, 0, false); 33*51c0b2f7Stbbdev } 34*51c0b2f7Stbbdev 35*51c0b2f7Stbbdev template <typename Container> 36*51c0b2f7Stbbdev struct OrderChecker { 37*51c0b2f7Stbbdev typename Container::value_compare& val_comp; 38*51c0b2f7Stbbdev typename Container::key_compare& key_comp; 39*51c0b2f7Stbbdev 40*51c0b2f7Stbbdev OrderChecker(typename Container::value_compare& v_comp, typename Container::key_compare& k_comp) 41*51c0b2f7Stbbdev : val_comp(v_comp), key_comp(k_comp) {} 42*51c0b2f7Stbbdev 43*51c0b2f7Stbbdev bool operator()(const typename Container::value_type& lhs, const typename Container::value_type& rhs) { 44*51c0b2f7Stbbdev if (AllowMultimapping<Container>::value) 45*51c0b2f7Stbbdev // We need to use not greater comparator for multicontainer 46*51c0b2f7Stbbdev return !val_comp(rhs, lhs) && !key_comp(Value<Container>::key(rhs), Value<Container>::key(lhs)); 47*51c0b2f7Stbbdev return val_comp(lhs, rhs) && key_comp(Value<Container>::key(lhs), Value<Container>::key(rhs)); 48*51c0b2f7Stbbdev } 49*51c0b2f7Stbbdev }; // struct OrderChecker 50*51c0b2f7Stbbdev 51*51c0b2f7Stbbdev template <typename Container> 52*51c0b2f7Stbbdev void check_container_order( const Container& cont ) { 53*51c0b2f7Stbbdev if (!cont.empty()) { 54*51c0b2f7Stbbdev typename Container::key_compare key_comp = cont.key_comp(); 55*51c0b2f7Stbbdev typename Container::value_compare value_comp = cont.value_comp(); 56*51c0b2f7Stbbdev OrderChecker<Container> check_order(value_comp, key_comp); 57*51c0b2f7Stbbdev 58*51c0b2f7Stbbdev for (auto it = cont.begin(); std::next(it) != cont.end();) { 59*51c0b2f7Stbbdev auto pr_it = it++; 60*51c0b2f7Stbbdev REQUIRE_MESSAGE(check_order(*pr_it, *it), "The order of the elements is broken"); 61*51c0b2f7Stbbdev } 62*51c0b2f7Stbbdev } 63*51c0b2f7Stbbdev } 64*51c0b2f7Stbbdev 65*51c0b2f7Stbbdev template <typename Container> 66*51c0b2f7Stbbdev void test_ordered_methods() { 67*51c0b2f7Stbbdev Container cont; 68*51c0b2f7Stbbdev const Container& ccont = cont; 69*51c0b2f7Stbbdev 70*51c0b2f7Stbbdev int r, random_threshold = 10, uncontained_key = random_threshold / 2; 71*51c0b2f7Stbbdev for (int i = 0; i < 100; ++i) { 72*51c0b2f7Stbbdev r = std::rand() % random_threshold; 73*51c0b2f7Stbbdev if (r != uncontained_key) { 74*51c0b2f7Stbbdev cont.insert(Value<Container>::make(r)); 75*51c0b2f7Stbbdev } 76*51c0b2f7Stbbdev } 77*51c0b2f7Stbbdev 78*51c0b2f7Stbbdev check_container_order(cont); 79*51c0b2f7Stbbdev 80*51c0b2f7Stbbdev typename Container::value_compare val_comp = cont.value_comp(); 81*51c0b2f7Stbbdev typename Container::iterator l_bound_check, u_bound_check; 82*51c0b2f7Stbbdev for (int key = -1; key < random_threshold + 1; ++key) { 83*51c0b2f7Stbbdev auto eq_range = cont.equal_range(key); 84*51c0b2f7Stbbdev // Check equal_range content 85*51c0b2f7Stbbdev for (auto it = eq_range.first; it != eq_range.second; ++it) 86*51c0b2f7Stbbdev REQUIRE_MESSAGE(*it == Value<Container>::make(key), "equal_range contains wrong value"); 87*51c0b2f7Stbbdev 88*51c0b2f7Stbbdev // Manual search of upper and lower bounds 89*51c0b2f7Stbbdev l_bound_check = cont.end(); 90*51c0b2f7Stbbdev u_bound_check = cont.end(); 91*51c0b2f7Stbbdev for (auto it = cont.begin(); it != cont.end(); ++it){ 92*51c0b2f7Stbbdev if (!val_comp(*it, Value<Container>::make(key)) && l_bound_check == cont.end()) { 93*51c0b2f7Stbbdev l_bound_check = it; 94*51c0b2f7Stbbdev } 95*51c0b2f7Stbbdev if (val_comp(Value<Container>::make(key), *it) && u_bound_check == cont.end()) { 96*51c0b2f7Stbbdev u_bound_check = it; 97*51c0b2f7Stbbdev break; 98*51c0b2f7Stbbdev } 99*51c0b2f7Stbbdev } 100*51c0b2f7Stbbdev 101*51c0b2f7Stbbdev typename Container::range_type cont_range = cont.range(); 102*51c0b2f7Stbbdev typename Container::const_range_type ccont_range = ccont.range(); 103*51c0b2f7Stbbdev REQUIRE_MESSAGE(cont_range.size() == ccont_range.size(), "Incorrect ordered container range size"); 104*51c0b2f7Stbbdev REQUIRE_MESSAGE(cont_range.size() == cont.size(), "Incorrect ordered container range size"); 105*51c0b2f7Stbbdev 106*51c0b2f7Stbbdev typename Container::iterator l_bound = cont.lower_bound(key); 107*51c0b2f7Stbbdev typename Container::iterator u_bound = cont.upper_bound(key); 108*51c0b2f7Stbbdev 109*51c0b2f7Stbbdev REQUIRE_MESSAGE(l_bound == l_bound_check, "lower_bound() returned wrong iterator"); 110*51c0b2f7Stbbdev REQUIRE_MESSAGE(u_bound == u_bound_check, "upper_bound() returned wrong iterator"); 111*51c0b2f7Stbbdev 112*51c0b2f7Stbbdev using const_iterator = typename Container::const_iterator; 113*51c0b2f7Stbbdev const_iterator cl_bound = ccont.lower_bound(key); 114*51c0b2f7Stbbdev const_iterator cu_bound = ccont.upper_bound(key); 115*51c0b2f7Stbbdev 116*51c0b2f7Stbbdev REQUIRE_MESSAGE(cl_bound == const_iterator(l_bound), "lower_bound() const returned wrong iterator"); 117*51c0b2f7Stbbdev REQUIRE_MESSAGE(cu_bound == const_iterator(u_bound), "upper_bound() const returned wrong iterator"); 118*51c0b2f7Stbbdev 119*51c0b2f7Stbbdev REQUIRE((l_bound == eq_range.first && u_bound == eq_range.second)); 120*51c0b2f7Stbbdev } 121*51c0b2f7Stbbdev } 122*51c0b2f7Stbbdev 123*51c0b2f7Stbbdev template <typename Container, typename CheckElementState = std::false_type> 124*51c0b2f7Stbbdev void test_basic() { 125*51c0b2f7Stbbdev test_basic_common<Container, CheckElementState>(); 126*51c0b2f7Stbbdev test_ordered_methods<Container>(); 127*51c0b2f7Stbbdev } 128*51c0b2f7Stbbdev 129*51c0b2f7Stbbdev template <typename Container> 130*51c0b2f7Stbbdev void test_concurrent_order() { 131*51c0b2f7Stbbdev // TODO: MinThread - MaxThread loop 132*51c0b2f7Stbbdev auto num_threads = utils::get_platform_max_threads(); 133*51c0b2f7Stbbdev Container cont; 134*51c0b2f7Stbbdev int items = 1000; 135*51c0b2f7Stbbdev utils::NativeParallelFor(num_threads, [&](std::size_t index) { 136*51c0b2f7Stbbdev int step = index % 4 + 1; 137*51c0b2f7Stbbdev bool reverse = (step % 2 == 0); 138*51c0b2f7Stbbdev if (reverse) { 139*51c0b2f7Stbbdev for (int i = 0; i < items; i += step) { 140*51c0b2f7Stbbdev cont.insert(Value<Container>::make(i)); 141*51c0b2f7Stbbdev } 142*51c0b2f7Stbbdev } else { 143*51c0b2f7Stbbdev for (int i = items; i > 0; i -= step) { 144*51c0b2f7Stbbdev cont.insert(Value<Container>::make(i)); 145*51c0b2f7Stbbdev } 146*51c0b2f7Stbbdev } 147*51c0b2f7Stbbdev }); 148*51c0b2f7Stbbdev 149*51c0b2f7Stbbdev check_container_order(cont); 150*51c0b2f7Stbbdev } 151*51c0b2f7Stbbdev 152*51c0b2f7Stbbdev template <typename Container> 153*51c0b2f7Stbbdev void test_concurrent(bool asymptotic = false) { 154*51c0b2f7Stbbdev test_concurrent_common<Container>(asymptotic); 155*51c0b2f7Stbbdev test_concurrent_order<Container>(); 156*51c0b2f7Stbbdev } 157*51c0b2f7Stbbdev 158*51c0b2f7Stbbdev struct OrderedMoveTraitsBase { 159*51c0b2f7Stbbdev static constexpr std::size_t expected_number_of_items_to_allocate_for_steal_move = 584; // TODO: remove allocation of dummy_node 160*51c0b2f7Stbbdev 161*51c0b2f7Stbbdev template <typename OrderedType, typename Iterator> 162*51c0b2f7Stbbdev static OrderedType& construct_container( typename std::aligned_storage<sizeof(OrderedType)>::type& storage, 163*51c0b2f7Stbbdev Iterator begin, Iterator end ) 164*51c0b2f7Stbbdev { 165*51c0b2f7Stbbdev OrderedType* ptr = reinterpret_cast<OrderedType*>(&storage); 166*51c0b2f7Stbbdev new (ptr) OrderedType(begin, end); 167*51c0b2f7Stbbdev return *ptr; 168*51c0b2f7Stbbdev } 169*51c0b2f7Stbbdev 170*51c0b2f7Stbbdev template <typename OrderedType, typename Iterator, typename Allocator> 171*51c0b2f7Stbbdev static OrderedType& construct_container( typename std::aligned_storage<sizeof(OrderedType)>::type& storage, 172*51c0b2f7Stbbdev Iterator begin, Iterator end, const Allocator& alloc ) 173*51c0b2f7Stbbdev { 174*51c0b2f7Stbbdev OrderedType* ptr = reinterpret_cast<OrderedType*>(&storage); 175*51c0b2f7Stbbdev new (ptr) OrderedType(begin, end, typename OrderedType::key_compare(), alloc); 176*51c0b2f7Stbbdev return *ptr; 177*51c0b2f7Stbbdev } 178*51c0b2f7Stbbdev 179*51c0b2f7Stbbdev template <typename OrderedType, typename Iterator> 180*51c0b2f7Stbbdev static bool equal( const OrderedType& c, Iterator begin, Iterator end ) { 181*51c0b2f7Stbbdev bool equal_sizes = std::size_t(std::distance(begin, end)) == c.size(); 182*51c0b2f7Stbbdev if (!equal_sizes) return false; 183*51c0b2f7Stbbdev for (Iterator it = begin; it != end; ++it) { 184*51c0b2f7Stbbdev if (!c.contains(Value<OrderedType>::key((*it)))) return false; 185*51c0b2f7Stbbdev } 186*51c0b2f7Stbbdev return true; 187*51c0b2f7Stbbdev } 188*51c0b2f7Stbbdev }; 189*51c0b2f7Stbbdev 190*51c0b2f7Stbbdev namespace std { 191*51c0b2f7Stbbdev template <> 192*51c0b2f7Stbbdev struct less<std::weak_ptr<int>> { 193*51c0b2f7Stbbdev bool operator()( const std::weak_ptr<int>& lhs, const std::weak_ptr<int>& rhs ) const { 194*51c0b2f7Stbbdev return *lhs.lock() < *rhs.lock(); 195*51c0b2f7Stbbdev } 196*51c0b2f7Stbbdev }; 197*51c0b2f7Stbbdev 198*51c0b2f7Stbbdev template <> 199*51c0b2f7Stbbdev struct less<const std::weak_ptr<int>> : less<std::weak_ptr<int>> {}; 200*51c0b2f7Stbbdev } 201*51c0b2f7Stbbdev 202*51c0b2f7Stbbdev template <bool DefCtorPresent, typename Table> 203*51c0b2f7Stbbdev void Examine(Table c, const std::list<typename Table::value_type>& lst) { 204*51c0b2f7Stbbdev CommonExamine<DefCtorPresent>(c, lst); 205*51c0b2f7Stbbdev } 206*51c0b2f7Stbbdev 207*51c0b2f7Stbbdev template <bool DefCtorPresent, typename Table> 208*51c0b2f7Stbbdev void TypeTester( const std::list<typename Table::value_type>& lst ) { 209*51c0b2f7Stbbdev REQUIRE_MESSAGE(lst.size() >= 5, "Array should have at least 5 elements"); 210*51c0b2f7Stbbdev REQUIRE_MESSAGE(lst.size() <= 100, "The test has O(n^2) complexity so a big number of elements can lead long execution time"); 211*51c0b2f7Stbbdev 212*51c0b2f7Stbbdev // Construct an empty table 213*51c0b2f7Stbbdev Table c1; 214*51c0b2f7Stbbdev c1.insert(lst.begin(), lst.end()); 215*51c0b2f7Stbbdev Examine<DefCtorPresent>(c1, lst); 216*51c0b2f7Stbbdev 217*51c0b2f7Stbbdev typename Table::key_compare compare; 218*51c0b2f7Stbbdev typename Table::allocator_type allocator; 219*51c0b2f7Stbbdev 220*51c0b2f7Stbbdev auto it = lst.begin(); 221*51c0b2f7Stbbdev auto init = {*it++, *it++, *it++}; 222*51c0b2f7Stbbdev 223*51c0b2f7Stbbdev // Constructor from an std::initializer_list 224*51c0b2f7Stbbdev Table c2(init); 225*51c0b2f7Stbbdev c2.insert(it, lst.end()); 226*51c0b2f7Stbbdev Examine<DefCtorPresent>(c2, lst); 227*51c0b2f7Stbbdev 228*51c0b2f7Stbbdev // Constructor from an std::initializer_list, default comparator and non-default allocator 229*51c0b2f7Stbbdev Table c2_alloc(init, allocator); 230*51c0b2f7Stbbdev c2_alloc.insert(it, lst.end()); 231*51c0b2f7Stbbdev Examine<DefCtorPresent>(c2_alloc, lst); 232*51c0b2f7Stbbdev 233*51c0b2f7Stbbdev // Constructor from an std::initializer_list, non-default comparator and allocator 234*51c0b2f7Stbbdev Table c2_comp_alloc(init, compare, allocator); 235*51c0b2f7Stbbdev c2_comp_alloc.insert(it, lst.end()); 236*51c0b2f7Stbbdev Examine<DefCtorPresent>(c2_comp_alloc, lst); 237*51c0b2f7Stbbdev 238*51c0b2f7Stbbdev // Copying constructor 239*51c0b2f7Stbbdev Table c3(c1); 240*51c0b2f7Stbbdev Examine<DefCtorPresent>(c3, lst); 241*51c0b2f7Stbbdev 242*51c0b2f7Stbbdev // Copying constructor with the allocator 243*51c0b2f7Stbbdev Table c3_alloc(c1, allocator); 244*51c0b2f7Stbbdev Examine<DefCtorPresent>(c3_alloc, lst); 245*51c0b2f7Stbbdev 246*51c0b2f7Stbbdev // Constructor with non-default compare 247*51c0b2f7Stbbdev Table c4(compare); 248*51c0b2f7Stbbdev c4.insert(lst.begin(), lst.end()); 249*51c0b2f7Stbbdev Examine<DefCtorPresent>(c4, lst); 250*51c0b2f7Stbbdev 251*51c0b2f7Stbbdev // Constructor with non-default allocator 252*51c0b2f7Stbbdev Table c5(allocator); 253*51c0b2f7Stbbdev c5.insert(lst.begin(), lst.end()); 254*51c0b2f7Stbbdev Examine<DefCtorPresent>(c5, lst); 255*51c0b2f7Stbbdev 256*51c0b2f7Stbbdev // Constructor with non-default compare and non-default allocator 257*51c0b2f7Stbbdev Table c6(compare, allocator); 258*51c0b2f7Stbbdev c6.insert(lst.begin(), lst.end()); 259*51c0b2f7Stbbdev Examine<DefCtorPresent>(c6, lst); 260*51c0b2f7Stbbdev 261*51c0b2f7Stbbdev // Constructor from an iteration range 262*51c0b2f7Stbbdev Table c7(c1.begin(), c1.end()); 263*51c0b2f7Stbbdev Examine<DefCtorPresent>(c7, lst); 264*51c0b2f7Stbbdev 265*51c0b2f7Stbbdev // Constructor from an iteration range, default compare and non-default allocator 266*51c0b2f7Stbbdev Table c8(c1.begin(), c1.end(), allocator); 267*51c0b2f7Stbbdev Examine<DefCtorPresent>(c8, lst); 268*51c0b2f7Stbbdev 269*51c0b2f7Stbbdev // Constructor from an iteration range, non-default compare and non-default allocator 270*51c0b2f7Stbbdev Table c9(c1.begin(), c1.end(), compare, allocator); 271*51c0b2f7Stbbdev Examine<DefCtorPresent>(c9, lst); 272*51c0b2f7Stbbdev } 273*51c0b2f7Stbbdev 274*51c0b2f7Stbbdev struct TransparentLess { 275*51c0b2f7Stbbdev template <typename T, typename U> 276*51c0b2f7Stbbdev auto operator()( T&& lhs, U&& rhs ) const 277*51c0b2f7Stbbdev -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs)) { 278*51c0b2f7Stbbdev return lhs < rhs; 279*51c0b2f7Stbbdev } 280*51c0b2f7Stbbdev 281*51c0b2f7Stbbdev using is_transparent = void; 282*51c0b2f7Stbbdev }; 283*51c0b2f7Stbbdev 284*51c0b2f7Stbbdev template <template <typename...> class Container, typename... Args> 285*51c0b2f7Stbbdev void check_heterogeneous_functions_key_int() { 286*51c0b2f7Stbbdev check_heterogeneous_functions_key_int_impl<Container<Args..., TransparentLess>>(); 287*51c0b2f7Stbbdev } 288*51c0b2f7Stbbdev 289*51c0b2f7Stbbdev template <template <typename...> class Container, typename... Args> 290*51c0b2f7Stbbdev void check_heterogeneous_functions_key_string() { 291*51c0b2f7Stbbdev check_heterogeneous_functions_key_string_impl<Container<Args..., TransparentLess>>(); 292*51c0b2f7Stbbdev } 293*51c0b2f7Stbbdev 294*51c0b2f7Stbbdev template <typename Container> 295*51c0b2f7Stbbdev void check_heterogeneous_bound_functions() { 296*51c0b2f7Stbbdev static_assert(std::is_same<typename Container::key_type, int>::value, 297*51c0b2f7Stbbdev "incorrect key_type for heterogeneous bounds test"); 298*51c0b2f7Stbbdev // Initialization 299*51c0b2f7Stbbdev Container c; 300*51c0b2f7Stbbdev const Container& cc = c; 301*51c0b2f7Stbbdev 302*51c0b2f7Stbbdev int size = 10; 303*51c0b2f7Stbbdev for (int i = 0; i < size; ++i) { 304*51c0b2f7Stbbdev c.insert(Value<Container>::make(i)); 305*51c0b2f7Stbbdev } 306*51c0b2f7Stbbdev // Insert first duplicated element for multicontainers 307*51c0b2f7Stbbdev if (AllowMultimapping<Container>::value) { 308*51c0b2f7Stbbdev c.insert(Value<Container>::make(0)); 309*51c0b2f7Stbbdev } 310*51c0b2f7Stbbdev 311*51c0b2f7Stbbdev // Upper and lower bound testing 312*51c0b2f7Stbbdev for (int i = 0; i < size; ++i) { 313*51c0b2f7Stbbdev int_key k(i); 314*51c0b2f7Stbbdev int key = i; 315*51c0b2f7Stbbdev 316*51c0b2f7Stbbdev REQUIRE_MESSAGE(c.lower_bound(k) == c.lower_bound(key), "Incorrect heterogeneous lower_bound return value"); 317*51c0b2f7Stbbdev REQUIRE_MESSAGE(c.upper_bound(k) == c.upper_bound(key), "Incorrect heterogeneous upper_bound return value"); 318*51c0b2f7Stbbdev REQUIRE_MESSAGE(cc.lower_bound(k) == cc.lower_bound(key), "Incorrect const heterogeneous lower_bound return value"); 319*51c0b2f7Stbbdev REQUIRE_MESSAGE(cc.upper_bound(k) == cc.upper_bound(key), "Incorrect const heterogeneous upper_bound return value"); 320*51c0b2f7Stbbdev } 321*51c0b2f7Stbbdev } 322*51c0b2f7Stbbdev 323*51c0b2f7Stbbdev template <typename Container> 324*51c0b2f7Stbbdev void test_comparisons_basic() { 325*51c0b2f7Stbbdev using comparisons_testing::testEqualityAndLessComparisons; 326*51c0b2f7Stbbdev Container c1, c2; 327*51c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */true, /*ExpectLess = */false>(c1, c2); 328*51c0b2f7Stbbdev 329*51c0b2f7Stbbdev c1.insert(Value<Container>::make(1)); 330*51c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */false, /*ExpectLess = */false>(c1, c2); 331*51c0b2f7Stbbdev 332*51c0b2f7Stbbdev c2.insert(Value<Container>::make(1)); 333*51c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */true, /*ExpectLess = */false>(c1, c2); 334*51c0b2f7Stbbdev 335*51c0b2f7Stbbdev c2.insert(Value<Container>::make(2)); 336*51c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */false, /*ExpectLess = */true>(c1, c2); 337*51c0b2f7Stbbdev 338*51c0b2f7Stbbdev c1.clear(); 339*51c0b2f7Stbbdev c2.clear(); 340*51c0b2f7Stbbdev 341*51c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */true, /*ExpectLess = */false>(c1, c2); 342*51c0b2f7Stbbdev } 343*51c0b2f7Stbbdev 344*51c0b2f7Stbbdev template <typename TwoWayComparableContainerType> 345*51c0b2f7Stbbdev void test_two_way_comparable_container() { 346*51c0b2f7Stbbdev TwoWayComparableContainerType c1, c2; 347*51c0b2f7Stbbdev c1.insert(Value<TwoWayComparableContainerType>::make(1)); 348*51c0b2f7Stbbdev c2.insert(Value<TwoWayComparableContainerType>::make(1)); 349*51c0b2f7Stbbdev comparisons_testing::TwoWayComparable::reset(); 350*51c0b2f7Stbbdev REQUIRE_MESSAGE(!(c1 < c2), "Incorrect operator < result"); 351*51c0b2f7Stbbdev comparisons_testing::check_two_way_comparison(); 352*51c0b2f7Stbbdev REQUIRE_MESSAGE(!(c1 > c2), "Incorrect operator > result"); 353*51c0b2f7Stbbdev comparisons_testing::check_two_way_comparison(); 354*51c0b2f7Stbbdev REQUIRE_MESSAGE(c1 <= c2, "Incorrect operator <= result"); 355*51c0b2f7Stbbdev comparisons_testing::check_two_way_comparison(); 356*51c0b2f7Stbbdev REQUIRE_MESSAGE(c1 >= c2, "Incorrect operator >= result"); 357*51c0b2f7Stbbdev comparisons_testing::check_two_way_comparison(); 358*51c0b2f7Stbbdev } 359*51c0b2f7Stbbdev 360*51c0b2f7Stbbdev template <template <typename...> class ContainerType> 361*51c0b2f7Stbbdev void test_map_comparisons() { 362*51c0b2f7Stbbdev using integral_container = ContainerType<int, int>; 363*51c0b2f7Stbbdev using two_way_comparable_container = ContainerType<comparisons_testing::TwoWayComparable, 364*51c0b2f7Stbbdev comparisons_testing::TwoWayComparable>; 365*51c0b2f7Stbbdev test_comparisons_basic<integral_container>(); 366*51c0b2f7Stbbdev test_comparisons_basic<two_way_comparable_container>(); 367*51c0b2f7Stbbdev test_two_way_comparable_container<two_way_comparable_container>(); 368*51c0b2f7Stbbdev } 369*51c0b2f7Stbbdev 370*51c0b2f7Stbbdev template <template <typename...> class ContainerType> 371*51c0b2f7Stbbdev void test_set_comparisons() { 372*51c0b2f7Stbbdev using integral_container = ContainerType<int>; 373*51c0b2f7Stbbdev using two_way_comparable_container = ContainerType<comparisons_testing::TwoWayComparable>; 374*51c0b2f7Stbbdev 375*51c0b2f7Stbbdev test_comparisons_basic<integral_container>(); 376*51c0b2f7Stbbdev test_comparisons_basic<two_way_comparable_container>(); 377*51c0b2f7Stbbdev test_two_way_comparable_container<two_way_comparable_container>(); 378*51c0b2f7Stbbdev } 379*51c0b2f7Stbbdev 380*51c0b2f7Stbbdev #endif // __TBB_test_common_concurrent_ordered_common_H 381