151c0b2f7Stbbdev /* 2*b15aabb3Stbbdev Copyright (c) 2019-2021 Intel Corporation 351c0b2f7Stbbdev 451c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License"); 551c0b2f7Stbbdev you may not use this file except in compliance with the License. 651c0b2f7Stbbdev You may obtain a copy of the License at 751c0b2f7Stbbdev 851c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0 951c0b2f7Stbbdev 1051c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software 1151c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS, 1251c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1351c0b2f7Stbbdev See the License for the specific language governing permissions and 1451c0b2f7Stbbdev limitations under the License. 1551c0b2f7Stbbdev */ 1651c0b2f7Stbbdev 1751c0b2f7Stbbdev #ifndef __TBB_test_common_concurrent_ordered_common_H 1851c0b2f7Stbbdev #define __TBB_test_common_concurrent_ordered_common_H 1951c0b2f7Stbbdev 20*b15aabb3Stbbdev #define __TBB_TEST_CPP20_COMPARISONS __TBB_CPP20_COMPARISONS_PRESENT && __TBB_CPP20_CONCEPTS_PRESENT 2151c0b2f7Stbbdev #include "common/concurrent_associative_common.h" 2251c0b2f7Stbbdev #include "test_comparisons.h" 2351c0b2f7Stbbdev 2451c0b2f7Stbbdev template<typename MyTable> 2551c0b2f7Stbbdev inline void CheckContainerAllocator(MyTable &table, size_t expected_allocs, size_t expected_frees, bool exact) { 2651c0b2f7Stbbdev typename MyTable::allocator_type a = table.get_allocator(); 2751c0b2f7Stbbdev CheckAllocator<MyTable>(a, expected_allocs, expected_frees, exact); 2851c0b2f7Stbbdev } 2951c0b2f7Stbbdev 3051c0b2f7Stbbdev template<typename Container> 3151c0b2f7Stbbdev inline void CheckNoAllocations(Container&) { 3251c0b2f7Stbbdev // TODO: enable 3351c0b2f7Stbbdev // CheckContainerAllocator(cont, 0, 0, false); 3451c0b2f7Stbbdev } 3551c0b2f7Stbbdev 3651c0b2f7Stbbdev template <typename Container> 3751c0b2f7Stbbdev struct OrderChecker { 3851c0b2f7Stbbdev typename Container::value_compare& val_comp; 3951c0b2f7Stbbdev typename Container::key_compare& key_comp; 4051c0b2f7Stbbdev 4151c0b2f7Stbbdev OrderChecker(typename Container::value_compare& v_comp, typename Container::key_compare& k_comp) 4251c0b2f7Stbbdev : val_comp(v_comp), key_comp(k_comp) {} 4351c0b2f7Stbbdev 4451c0b2f7Stbbdev bool operator()(const typename Container::value_type& lhs, const typename Container::value_type& rhs) { 4551c0b2f7Stbbdev if (AllowMultimapping<Container>::value) 4651c0b2f7Stbbdev // We need to use not greater comparator for multicontainer 4751c0b2f7Stbbdev return !val_comp(rhs, lhs) && !key_comp(Value<Container>::key(rhs), Value<Container>::key(lhs)); 4851c0b2f7Stbbdev return val_comp(lhs, rhs) && key_comp(Value<Container>::key(lhs), Value<Container>::key(rhs)); 4951c0b2f7Stbbdev } 5051c0b2f7Stbbdev }; // struct OrderChecker 5151c0b2f7Stbbdev 5251c0b2f7Stbbdev template <typename Container> 5351c0b2f7Stbbdev void check_container_order( const Container& cont ) { 5451c0b2f7Stbbdev if (!cont.empty()) { 5551c0b2f7Stbbdev typename Container::key_compare key_comp = cont.key_comp(); 5651c0b2f7Stbbdev typename Container::value_compare value_comp = cont.value_comp(); 5751c0b2f7Stbbdev OrderChecker<Container> check_order(value_comp, key_comp); 5851c0b2f7Stbbdev 5951c0b2f7Stbbdev for (auto it = cont.begin(); std::next(it) != cont.end();) { 6051c0b2f7Stbbdev auto pr_it = it++; 6151c0b2f7Stbbdev REQUIRE_MESSAGE(check_order(*pr_it, *it), "The order of the elements is broken"); 6251c0b2f7Stbbdev } 6351c0b2f7Stbbdev } 6451c0b2f7Stbbdev } 6551c0b2f7Stbbdev 6651c0b2f7Stbbdev template <typename Container> 6751c0b2f7Stbbdev void test_ordered_methods() { 6851c0b2f7Stbbdev Container cont; 6951c0b2f7Stbbdev const Container& ccont = cont; 7051c0b2f7Stbbdev 7151c0b2f7Stbbdev int r, random_threshold = 10, uncontained_key = random_threshold / 2; 7251c0b2f7Stbbdev for (int i = 0; i < 100; ++i) { 7351c0b2f7Stbbdev r = std::rand() % random_threshold; 7451c0b2f7Stbbdev if (r != uncontained_key) { 7551c0b2f7Stbbdev cont.insert(Value<Container>::make(r)); 7651c0b2f7Stbbdev } 7751c0b2f7Stbbdev } 7851c0b2f7Stbbdev 7951c0b2f7Stbbdev check_container_order(cont); 8051c0b2f7Stbbdev 8151c0b2f7Stbbdev typename Container::value_compare val_comp = cont.value_comp(); 8251c0b2f7Stbbdev typename Container::iterator l_bound_check, u_bound_check; 8351c0b2f7Stbbdev for (int key = -1; key < random_threshold + 1; ++key) { 8451c0b2f7Stbbdev auto eq_range = cont.equal_range(key); 8551c0b2f7Stbbdev // Check equal_range content 8651c0b2f7Stbbdev for (auto it = eq_range.first; it != eq_range.second; ++it) 8751c0b2f7Stbbdev REQUIRE_MESSAGE(*it == Value<Container>::make(key), "equal_range contains wrong value"); 8851c0b2f7Stbbdev 8951c0b2f7Stbbdev // Manual search of upper and lower bounds 9051c0b2f7Stbbdev l_bound_check = cont.end(); 9151c0b2f7Stbbdev u_bound_check = cont.end(); 9251c0b2f7Stbbdev for (auto it = cont.begin(); it != cont.end(); ++it){ 9351c0b2f7Stbbdev if (!val_comp(*it, Value<Container>::make(key)) && l_bound_check == cont.end()) { 9451c0b2f7Stbbdev l_bound_check = it; 9551c0b2f7Stbbdev } 9651c0b2f7Stbbdev if (val_comp(Value<Container>::make(key), *it) && u_bound_check == cont.end()) { 9751c0b2f7Stbbdev u_bound_check = it; 9851c0b2f7Stbbdev break; 9951c0b2f7Stbbdev } 10051c0b2f7Stbbdev } 10151c0b2f7Stbbdev 10251c0b2f7Stbbdev typename Container::range_type cont_range = cont.range(); 10351c0b2f7Stbbdev typename Container::const_range_type ccont_range = ccont.range(); 10451c0b2f7Stbbdev REQUIRE_MESSAGE(cont_range.size() == ccont_range.size(), "Incorrect ordered container range size"); 10551c0b2f7Stbbdev REQUIRE_MESSAGE(cont_range.size() == cont.size(), "Incorrect ordered container range size"); 10651c0b2f7Stbbdev 10751c0b2f7Stbbdev typename Container::iterator l_bound = cont.lower_bound(key); 10851c0b2f7Stbbdev typename Container::iterator u_bound = cont.upper_bound(key); 10951c0b2f7Stbbdev 11051c0b2f7Stbbdev REQUIRE_MESSAGE(l_bound == l_bound_check, "lower_bound() returned wrong iterator"); 11151c0b2f7Stbbdev REQUIRE_MESSAGE(u_bound == u_bound_check, "upper_bound() returned wrong iterator"); 11251c0b2f7Stbbdev 11351c0b2f7Stbbdev using const_iterator = typename Container::const_iterator; 11451c0b2f7Stbbdev const_iterator cl_bound = ccont.lower_bound(key); 11551c0b2f7Stbbdev const_iterator cu_bound = ccont.upper_bound(key); 11651c0b2f7Stbbdev 11751c0b2f7Stbbdev REQUIRE_MESSAGE(cl_bound == const_iterator(l_bound), "lower_bound() const returned wrong iterator"); 11851c0b2f7Stbbdev REQUIRE_MESSAGE(cu_bound == const_iterator(u_bound), "upper_bound() const returned wrong iterator"); 11951c0b2f7Stbbdev 12051c0b2f7Stbbdev REQUIRE((l_bound == eq_range.first && u_bound == eq_range.second)); 12151c0b2f7Stbbdev } 12251c0b2f7Stbbdev } 12351c0b2f7Stbbdev 12451c0b2f7Stbbdev template <typename Container, typename CheckElementState = std::false_type> 12551c0b2f7Stbbdev void test_basic() { 12651c0b2f7Stbbdev test_basic_common<Container, CheckElementState>(); 12751c0b2f7Stbbdev test_ordered_methods<Container>(); 12851c0b2f7Stbbdev } 12951c0b2f7Stbbdev 13051c0b2f7Stbbdev template <typename Container> 13151c0b2f7Stbbdev void test_concurrent_order() { 13251c0b2f7Stbbdev // TODO: MinThread - MaxThread loop 13351c0b2f7Stbbdev auto num_threads = utils::get_platform_max_threads(); 13451c0b2f7Stbbdev Container cont; 13551c0b2f7Stbbdev int items = 1000; 13651c0b2f7Stbbdev utils::NativeParallelFor(num_threads, [&](std::size_t index) { 13751c0b2f7Stbbdev int step = index % 4 + 1; 13851c0b2f7Stbbdev bool reverse = (step % 2 == 0); 13951c0b2f7Stbbdev if (reverse) { 14051c0b2f7Stbbdev for (int i = 0; i < items; i += step) { 14151c0b2f7Stbbdev cont.insert(Value<Container>::make(i)); 14251c0b2f7Stbbdev } 14351c0b2f7Stbbdev } else { 14451c0b2f7Stbbdev for (int i = items; i > 0; i -= step) { 14551c0b2f7Stbbdev cont.insert(Value<Container>::make(i)); 14651c0b2f7Stbbdev } 14751c0b2f7Stbbdev } 14851c0b2f7Stbbdev }); 14951c0b2f7Stbbdev 15051c0b2f7Stbbdev check_container_order(cont); 15151c0b2f7Stbbdev } 15251c0b2f7Stbbdev 15351c0b2f7Stbbdev template <typename Container> 15451c0b2f7Stbbdev void test_concurrent(bool asymptotic = false) { 15551c0b2f7Stbbdev test_concurrent_common<Container>(asymptotic); 15651c0b2f7Stbbdev test_concurrent_order<Container>(); 15751c0b2f7Stbbdev } 15851c0b2f7Stbbdev 15951c0b2f7Stbbdev struct OrderedMoveTraitsBase { 16051c0b2f7Stbbdev static constexpr std::size_t expected_number_of_items_to_allocate_for_steal_move = 584; // TODO: remove allocation of dummy_node 16151c0b2f7Stbbdev 16251c0b2f7Stbbdev template <typename OrderedType, typename Iterator> 16351c0b2f7Stbbdev static OrderedType& construct_container( typename std::aligned_storage<sizeof(OrderedType)>::type& storage, 16451c0b2f7Stbbdev Iterator begin, Iterator end ) 16551c0b2f7Stbbdev { 16651c0b2f7Stbbdev OrderedType* ptr = reinterpret_cast<OrderedType*>(&storage); 16751c0b2f7Stbbdev new (ptr) OrderedType(begin, end); 16851c0b2f7Stbbdev return *ptr; 16951c0b2f7Stbbdev } 17051c0b2f7Stbbdev 17151c0b2f7Stbbdev template <typename OrderedType, typename Iterator, typename Allocator> 17251c0b2f7Stbbdev static OrderedType& construct_container( typename std::aligned_storage<sizeof(OrderedType)>::type& storage, 17351c0b2f7Stbbdev Iterator begin, Iterator end, const Allocator& alloc ) 17451c0b2f7Stbbdev { 17551c0b2f7Stbbdev OrderedType* ptr = reinterpret_cast<OrderedType*>(&storage); 17651c0b2f7Stbbdev new (ptr) OrderedType(begin, end, typename OrderedType::key_compare(), alloc); 17751c0b2f7Stbbdev return *ptr; 17851c0b2f7Stbbdev } 17951c0b2f7Stbbdev 18051c0b2f7Stbbdev template <typename OrderedType, typename Iterator> 18151c0b2f7Stbbdev static bool equal( const OrderedType& c, Iterator begin, Iterator end ) { 18251c0b2f7Stbbdev bool equal_sizes = std::size_t(std::distance(begin, end)) == c.size(); 18351c0b2f7Stbbdev if (!equal_sizes) return false; 18451c0b2f7Stbbdev for (Iterator it = begin; it != end; ++it) { 18551c0b2f7Stbbdev if (!c.contains(Value<OrderedType>::key((*it)))) return false; 18651c0b2f7Stbbdev } 18751c0b2f7Stbbdev return true; 18851c0b2f7Stbbdev } 18951c0b2f7Stbbdev }; 19051c0b2f7Stbbdev 19151c0b2f7Stbbdev namespace std { 19251c0b2f7Stbbdev template <> 19351c0b2f7Stbbdev struct less<std::weak_ptr<int>> { 19451c0b2f7Stbbdev bool operator()( const std::weak_ptr<int>& lhs, const std::weak_ptr<int>& rhs ) const { 19551c0b2f7Stbbdev return *lhs.lock() < *rhs.lock(); 19651c0b2f7Stbbdev } 19751c0b2f7Stbbdev }; 19851c0b2f7Stbbdev 19951c0b2f7Stbbdev template <> 20051c0b2f7Stbbdev struct less<const std::weak_ptr<int>> : less<std::weak_ptr<int>> {}; 20151c0b2f7Stbbdev } 20251c0b2f7Stbbdev 20351c0b2f7Stbbdev template <bool DefCtorPresent, typename Table> 20451c0b2f7Stbbdev void Examine(Table c, const std::list<typename Table::value_type>& lst) { 20551c0b2f7Stbbdev CommonExamine<DefCtorPresent>(c, lst); 20651c0b2f7Stbbdev } 20751c0b2f7Stbbdev 20851c0b2f7Stbbdev template <bool DefCtorPresent, typename Table> 20951c0b2f7Stbbdev void TypeTester( const std::list<typename Table::value_type>& lst ) { 21051c0b2f7Stbbdev REQUIRE_MESSAGE(lst.size() >= 5, "Array should have at least 5 elements"); 21151c0b2f7Stbbdev REQUIRE_MESSAGE(lst.size() <= 100, "The test has O(n^2) complexity so a big number of elements can lead long execution time"); 21251c0b2f7Stbbdev 21351c0b2f7Stbbdev // Construct an empty table 21451c0b2f7Stbbdev Table c1; 21551c0b2f7Stbbdev c1.insert(lst.begin(), lst.end()); 21651c0b2f7Stbbdev Examine<DefCtorPresent>(c1, lst); 21751c0b2f7Stbbdev 21851c0b2f7Stbbdev typename Table::key_compare compare; 21951c0b2f7Stbbdev typename Table::allocator_type allocator; 22051c0b2f7Stbbdev 22151c0b2f7Stbbdev auto it = lst.begin(); 22251c0b2f7Stbbdev auto init = {*it++, *it++, *it++}; 22351c0b2f7Stbbdev 22451c0b2f7Stbbdev // Constructor from an std::initializer_list 22551c0b2f7Stbbdev Table c2(init); 22651c0b2f7Stbbdev c2.insert(it, lst.end()); 22751c0b2f7Stbbdev Examine<DefCtorPresent>(c2, lst); 22851c0b2f7Stbbdev 22951c0b2f7Stbbdev // Constructor from an std::initializer_list, default comparator and non-default allocator 23051c0b2f7Stbbdev Table c2_alloc(init, allocator); 23151c0b2f7Stbbdev c2_alloc.insert(it, lst.end()); 23251c0b2f7Stbbdev Examine<DefCtorPresent>(c2_alloc, lst); 23351c0b2f7Stbbdev 23451c0b2f7Stbbdev // Constructor from an std::initializer_list, non-default comparator and allocator 23551c0b2f7Stbbdev Table c2_comp_alloc(init, compare, allocator); 23651c0b2f7Stbbdev c2_comp_alloc.insert(it, lst.end()); 23751c0b2f7Stbbdev Examine<DefCtorPresent>(c2_comp_alloc, lst); 23851c0b2f7Stbbdev 23951c0b2f7Stbbdev // Copying constructor 24051c0b2f7Stbbdev Table c3(c1); 24151c0b2f7Stbbdev Examine<DefCtorPresent>(c3, lst); 24251c0b2f7Stbbdev 24351c0b2f7Stbbdev // Copying constructor with the allocator 24451c0b2f7Stbbdev Table c3_alloc(c1, allocator); 24551c0b2f7Stbbdev Examine<DefCtorPresent>(c3_alloc, lst); 24651c0b2f7Stbbdev 24751c0b2f7Stbbdev // Constructor with non-default compare 24851c0b2f7Stbbdev Table c4(compare); 24951c0b2f7Stbbdev c4.insert(lst.begin(), lst.end()); 25051c0b2f7Stbbdev Examine<DefCtorPresent>(c4, lst); 25151c0b2f7Stbbdev 25251c0b2f7Stbbdev // Constructor with non-default allocator 25351c0b2f7Stbbdev Table c5(allocator); 25451c0b2f7Stbbdev c5.insert(lst.begin(), lst.end()); 25551c0b2f7Stbbdev Examine<DefCtorPresent>(c5, lst); 25651c0b2f7Stbbdev 25751c0b2f7Stbbdev // Constructor with non-default compare and non-default allocator 25851c0b2f7Stbbdev Table c6(compare, allocator); 25951c0b2f7Stbbdev c6.insert(lst.begin(), lst.end()); 26051c0b2f7Stbbdev Examine<DefCtorPresent>(c6, lst); 26151c0b2f7Stbbdev 26251c0b2f7Stbbdev // Constructor from an iteration range 26351c0b2f7Stbbdev Table c7(c1.begin(), c1.end()); 26451c0b2f7Stbbdev Examine<DefCtorPresent>(c7, lst); 26551c0b2f7Stbbdev 26651c0b2f7Stbbdev // Constructor from an iteration range, default compare and non-default allocator 26751c0b2f7Stbbdev Table c8(c1.begin(), c1.end(), allocator); 26851c0b2f7Stbbdev Examine<DefCtorPresent>(c8, lst); 26951c0b2f7Stbbdev 27051c0b2f7Stbbdev // Constructor from an iteration range, non-default compare and non-default allocator 27151c0b2f7Stbbdev Table c9(c1.begin(), c1.end(), compare, allocator); 27251c0b2f7Stbbdev Examine<DefCtorPresent>(c9, lst); 27351c0b2f7Stbbdev } 27451c0b2f7Stbbdev 27551c0b2f7Stbbdev struct TransparentLess { 27651c0b2f7Stbbdev template <typename T, typename U> 27751c0b2f7Stbbdev auto operator()( T&& lhs, U&& rhs ) const 27851c0b2f7Stbbdev -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs)) { 27951c0b2f7Stbbdev return lhs < rhs; 28051c0b2f7Stbbdev } 28151c0b2f7Stbbdev 28251c0b2f7Stbbdev using is_transparent = void; 28351c0b2f7Stbbdev }; 28451c0b2f7Stbbdev 28551c0b2f7Stbbdev template <template <typename...> class Container, typename... Args> 28651c0b2f7Stbbdev void check_heterogeneous_functions_key_int() { 28751c0b2f7Stbbdev check_heterogeneous_functions_key_int_impl<Container<Args..., TransparentLess>>(); 28851c0b2f7Stbbdev } 28951c0b2f7Stbbdev 29051c0b2f7Stbbdev template <template <typename...> class Container, typename... Args> 29151c0b2f7Stbbdev void check_heterogeneous_functions_key_string() { 29251c0b2f7Stbbdev check_heterogeneous_functions_key_string_impl<Container<Args..., TransparentLess>>(); 29351c0b2f7Stbbdev } 29451c0b2f7Stbbdev 29551c0b2f7Stbbdev template <typename Container> 29651c0b2f7Stbbdev void check_heterogeneous_bound_functions() { 29751c0b2f7Stbbdev static_assert(std::is_same<typename Container::key_type, int>::value, 29851c0b2f7Stbbdev "incorrect key_type for heterogeneous bounds test"); 29951c0b2f7Stbbdev // Initialization 30051c0b2f7Stbbdev Container c; 30151c0b2f7Stbbdev const Container& cc = c; 30251c0b2f7Stbbdev 30351c0b2f7Stbbdev int size = 10; 30451c0b2f7Stbbdev for (int i = 0; i < size; ++i) { 30551c0b2f7Stbbdev c.insert(Value<Container>::make(i)); 30651c0b2f7Stbbdev } 30751c0b2f7Stbbdev // Insert first duplicated element for multicontainers 30851c0b2f7Stbbdev if (AllowMultimapping<Container>::value) { 30951c0b2f7Stbbdev c.insert(Value<Container>::make(0)); 31051c0b2f7Stbbdev } 31151c0b2f7Stbbdev 31251c0b2f7Stbbdev // Upper and lower bound testing 31351c0b2f7Stbbdev for (int i = 0; i < size; ++i) { 31451c0b2f7Stbbdev int_key k(i); 31551c0b2f7Stbbdev int key = i; 31651c0b2f7Stbbdev 31751c0b2f7Stbbdev REQUIRE_MESSAGE(c.lower_bound(k) == c.lower_bound(key), "Incorrect heterogeneous lower_bound return value"); 31851c0b2f7Stbbdev REQUIRE_MESSAGE(c.upper_bound(k) == c.upper_bound(key), "Incorrect heterogeneous upper_bound return value"); 31951c0b2f7Stbbdev REQUIRE_MESSAGE(cc.lower_bound(k) == cc.lower_bound(key), "Incorrect const heterogeneous lower_bound return value"); 32051c0b2f7Stbbdev REQUIRE_MESSAGE(cc.upper_bound(k) == cc.upper_bound(key), "Incorrect const heterogeneous upper_bound return value"); 32151c0b2f7Stbbdev } 32251c0b2f7Stbbdev } 32351c0b2f7Stbbdev 32451c0b2f7Stbbdev template <typename Container> 32551c0b2f7Stbbdev void test_comparisons_basic() { 32651c0b2f7Stbbdev using comparisons_testing::testEqualityAndLessComparisons; 32751c0b2f7Stbbdev Container c1, c2; 32851c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */true, /*ExpectLess = */false>(c1, c2); 32951c0b2f7Stbbdev 33051c0b2f7Stbbdev c1.insert(Value<Container>::make(1)); 33151c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */false, /*ExpectLess = */false>(c1, c2); 33251c0b2f7Stbbdev 33351c0b2f7Stbbdev c2.insert(Value<Container>::make(1)); 33451c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */true, /*ExpectLess = */false>(c1, c2); 33551c0b2f7Stbbdev 33651c0b2f7Stbbdev c2.insert(Value<Container>::make(2)); 33751c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */false, /*ExpectLess = */true>(c1, c2); 33851c0b2f7Stbbdev 33951c0b2f7Stbbdev c1.clear(); 34051c0b2f7Stbbdev c2.clear(); 34151c0b2f7Stbbdev 34251c0b2f7Stbbdev testEqualityAndLessComparisons</*ExpectEqual = */true, /*ExpectLess = */false>(c1, c2); 34351c0b2f7Stbbdev } 34451c0b2f7Stbbdev 34551c0b2f7Stbbdev template <typename TwoWayComparableContainerType> 34651c0b2f7Stbbdev void test_two_way_comparable_container() { 34751c0b2f7Stbbdev TwoWayComparableContainerType c1, c2; 34851c0b2f7Stbbdev c1.insert(Value<TwoWayComparableContainerType>::make(1)); 34951c0b2f7Stbbdev c2.insert(Value<TwoWayComparableContainerType>::make(1)); 35051c0b2f7Stbbdev comparisons_testing::TwoWayComparable::reset(); 35151c0b2f7Stbbdev REQUIRE_MESSAGE(!(c1 < c2), "Incorrect operator < result"); 35251c0b2f7Stbbdev comparisons_testing::check_two_way_comparison(); 35351c0b2f7Stbbdev REQUIRE_MESSAGE(!(c1 > c2), "Incorrect operator > result"); 35451c0b2f7Stbbdev comparisons_testing::check_two_way_comparison(); 35551c0b2f7Stbbdev REQUIRE_MESSAGE(c1 <= c2, "Incorrect operator <= result"); 35651c0b2f7Stbbdev comparisons_testing::check_two_way_comparison(); 35751c0b2f7Stbbdev REQUIRE_MESSAGE(c1 >= c2, "Incorrect operator >= result"); 35851c0b2f7Stbbdev comparisons_testing::check_two_way_comparison(); 35951c0b2f7Stbbdev } 36051c0b2f7Stbbdev 361*b15aabb3Stbbdev #if __TBB_TEST_CPP20_COMPARISONS 362*b15aabb3Stbbdev template <typename ThreeWayComparableContainerType> 363*b15aabb3Stbbdev void test_three_way_comparable_container() { 364*b15aabb3Stbbdev ThreeWayComparableContainerType c1, c2; 365*b15aabb3Stbbdev c1.insert(Value<ThreeWayComparableContainerType>::make(1)); 366*b15aabb3Stbbdev c2.insert(Value<ThreeWayComparableContainerType>::make(1)); 367*b15aabb3Stbbdev comparisons_testing::ThreeWayComparable::reset(); 368*b15aabb3Stbbdev REQUIRE_MESSAGE(!(c1 <=> c2 < 0), "Incorrect operator<=> result"); 369*b15aabb3Stbbdev comparisons_testing::check_three_way_comparison(); 370*b15aabb3Stbbdev 371*b15aabb3Stbbdev REQUIRE_MESSAGE(!(c1 < c2), "Incorrect operator< result"); 372*b15aabb3Stbbdev comparisons_testing::check_three_way_comparison(); 373*b15aabb3Stbbdev 374*b15aabb3Stbbdev REQUIRE_MESSAGE(!(c1 > c2), "Incorrect operator> result"); 375*b15aabb3Stbbdev comparisons_testing::check_three_way_comparison(); 376*b15aabb3Stbbdev 377*b15aabb3Stbbdev REQUIRE_MESSAGE(c1 <= c2, "Incorrect operator>= result"); 378*b15aabb3Stbbdev comparisons_testing::check_three_way_comparison(); 379*b15aabb3Stbbdev 380*b15aabb3Stbbdev REQUIRE_MESSAGE(c1 >= c2, "Incorrect operator>= result"); 381*b15aabb3Stbbdev comparisons_testing::check_three_way_comparison(); 382*b15aabb3Stbbdev } 383*b15aabb3Stbbdev #endif 384*b15aabb3Stbbdev 38551c0b2f7Stbbdev template <template <typename...> class ContainerType> 38651c0b2f7Stbbdev void test_map_comparisons() { 38751c0b2f7Stbbdev using integral_container = ContainerType<int, int>; 38851c0b2f7Stbbdev using two_way_comparable_container = ContainerType<comparisons_testing::TwoWayComparable, 38951c0b2f7Stbbdev comparisons_testing::TwoWayComparable>; 39051c0b2f7Stbbdev test_comparisons_basic<integral_container>(); 39151c0b2f7Stbbdev test_comparisons_basic<two_way_comparable_container>(); 39251c0b2f7Stbbdev test_two_way_comparable_container<two_way_comparable_container>(); 393*b15aabb3Stbbdev 394*b15aabb3Stbbdev #if __TBB_TEST_CPP20_COMPARISONS 395*b15aabb3Stbbdev using two_way_less_only_container = ContainerType<comparisons_testing::LessComparableOnly, 396*b15aabb3Stbbdev comparisons_testing::LessComparableOnly>; 397*b15aabb3Stbbdev 398*b15aabb3Stbbdev using three_way_only_container = ContainerType<comparisons_testing::ThreeWayComparableOnly, 399*b15aabb3Stbbdev comparisons_testing::ThreeWayComparableOnly>; 400*b15aabb3Stbbdev 401*b15aabb3Stbbdev using three_way_comparable_container = ContainerType<comparisons_testing::ThreeWayComparable, 402*b15aabb3Stbbdev comparisons_testing::ThreeWayComparable>; 403*b15aabb3Stbbdev 404*b15aabb3Stbbdev test_comparisons_basic<two_way_less_only_container>(); 405*b15aabb3Stbbdev test_comparisons_basic<three_way_only_container>(); 406*b15aabb3Stbbdev test_comparisons_basic<three_way_comparable_container>(); 407*b15aabb3Stbbdev test_three_way_comparable_container<three_way_comparable_container>(); 408*b15aabb3Stbbdev #endif // __TBB_TEST_CPP20_COMPARISONS 40951c0b2f7Stbbdev } 41051c0b2f7Stbbdev 41151c0b2f7Stbbdev template <template <typename...> class ContainerType> 41251c0b2f7Stbbdev void test_set_comparisons() { 41351c0b2f7Stbbdev using integral_container = ContainerType<int>; 41451c0b2f7Stbbdev using two_way_comparable_container = ContainerType<comparisons_testing::TwoWayComparable>; 41551c0b2f7Stbbdev 41651c0b2f7Stbbdev test_comparisons_basic<integral_container>(); 41751c0b2f7Stbbdev test_comparisons_basic<two_way_comparable_container>(); 41851c0b2f7Stbbdev test_two_way_comparable_container<two_way_comparable_container>(); 419*b15aabb3Stbbdev 420*b15aabb3Stbbdev #if __TBB_TEST_CPP20_COMPARISONS 421*b15aabb3Stbbdev using two_way_less_only_container = ContainerType<comparisons_testing::LessComparableOnly>; 422*b15aabb3Stbbdev using three_way_only_container = ContainerType<comparisons_testing::ThreeWayComparableOnly>; 423*b15aabb3Stbbdev using three_way_comparable_container = ContainerType<comparisons_testing::ThreeWayComparable>; 424*b15aabb3Stbbdev 425*b15aabb3Stbbdev test_comparisons_basic<two_way_less_only_container>(); 426*b15aabb3Stbbdev test_comparisons_basic<three_way_only_container>(); 427*b15aabb3Stbbdev test_comparisons_basic<three_way_comparable_container>(); 428*b15aabb3Stbbdev test_three_way_comparable_container<three_way_comparable_container>(); 429*b15aabb3Stbbdev #endif // __TBB_TEST_CPP20_COMPARISONS 43051c0b2f7Stbbdev } 43151c0b2f7Stbbdev 43251c0b2f7Stbbdev #endif // __TBB_test_common_concurrent_ordered_common_H 433