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