151c0b2f7Stbbdev /*
2b15aabb3Stbbdev Copyright (c) 2005-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 #ifndef NOMINMAX
1751c0b2f7Stbbdev #define NOMINMAX
1851c0b2f7Stbbdev #endif
1951c0b2f7Stbbdev #include <tbb/concurrent_map.h>
2051c0b2f7Stbbdev #include "common/concurrent_ordered_common.h"
2151c0b2f7Stbbdev
2251c0b2f7Stbbdev //! \file test_concurrent_map.cpp
2351c0b2f7Stbbdev //! \brief Test for [containers.concurrent_map containers.concurrent_multimap] specifications
2451c0b2f7Stbbdev
2551c0b2f7Stbbdev template <typename... Args>
2651c0b2f7Stbbdev struct AllowMultimapping<tbb::concurrent_multimap<Args...>> : std::true_type {};
2751c0b2f7Stbbdev
2851c0b2f7Stbbdev template <typename Key, typename Mapped>
2951c0b2f7Stbbdev using MyAllocator = LocalCountingAllocator<std::allocator<std::pair<const Key, Mapped>>>;
3051c0b2f7Stbbdev
3151c0b2f7Stbbdev using move_support_tests::FooWithAssign;
3251c0b2f7Stbbdev
3351c0b2f7Stbbdev using map_type = tbb::concurrent_map<int, int, std::less<int>, MyAllocator<int, int>>;
3451c0b2f7Stbbdev using multimap_type = tbb::concurrent_multimap<int, int, std::less<int>, MyAllocator<int, int>>;
3551c0b2f7Stbbdev using checked_map_type = tbb::concurrent_map<int, CheckType<int>, std::less<int>, MyAllocator<int, CheckType<int>>>;
3651c0b2f7Stbbdev using checked_multimap_type = tbb::concurrent_multimap<int, CheckType<int>, std::less<int>, MyAllocator<int, CheckType<int>>>;
3751c0b2f7Stbbdev using greater_map_type = tbb::concurrent_map<int, int, std::greater<int>, MyAllocator<int, int>>;
3851c0b2f7Stbbdev using greater_multimap_type = tbb::concurrent_multimap<int, int, std::greater<int>, MyAllocator<int, int>>;
3951c0b2f7Stbbdev using checked_state_map_type = tbb::concurrent_map<intptr_t, FooWithAssign, std::less<intptr_t>,
4051c0b2f7Stbbdev MyAllocator<intptr_t, FooWithAssign>>;
4151c0b2f7Stbbdev using checked_state_multimap_type = tbb::concurrent_multimap<intptr_t, FooWithAssign, std::less<intptr_t>,
4251c0b2f7Stbbdev MyAllocator<intptr_t, FooWithAssign>>;
4351c0b2f7Stbbdev
4451c0b2f7Stbbdev template <>
4551c0b2f7Stbbdev struct SpecialTests<map_type> {
TestSpecialTests4651c0b2f7Stbbdev static void Test() {
4751c0b2f7Stbbdev SpecialMapTests<map_type>();
4851c0b2f7Stbbdev }
4951c0b2f7Stbbdev };
5051c0b2f7Stbbdev
5151c0b2f7Stbbdev template <>
5251c0b2f7Stbbdev struct SpecialTests<multimap_type> {
TestSpecialTests5351c0b2f7Stbbdev static void Test() {
5451c0b2f7Stbbdev SpecialMultiMapTests<multimap_type>();
5551c0b2f7Stbbdev }
5651c0b2f7Stbbdev };
5751c0b2f7Stbbdev
5851c0b2f7Stbbdev struct COMapTraits : OrderedMoveTraitsBase {
5951c0b2f7Stbbdev template <typename T, typename Allocator>
6051c0b2f7Stbbdev using container_type = tbb::concurrent_map<T, T, std::less<T>, Allocator>;
6151c0b2f7Stbbdev
6251c0b2f7Stbbdev template <typename T>
6351c0b2f7Stbbdev using container_value_type = std::pair<const T, T>;
6451c0b2f7Stbbdev
6551c0b2f7Stbbdev using init_iterator_type = move_support_tests::FooPairIterator;
6651c0b2f7Stbbdev }; // struct COMapTraits
6751c0b2f7Stbbdev
6851c0b2f7Stbbdev struct COMultimapTraits : OrderedMoveTraitsBase {
6951c0b2f7Stbbdev template <typename T, typename Allocator>
7051c0b2f7Stbbdev using container_type = tbb::concurrent_multimap<T, T, std::less<T>, Allocator>;
7151c0b2f7Stbbdev
7251c0b2f7Stbbdev template <typename T>
7351c0b2f7Stbbdev using container_value_type = std::pair<const T, T>;
7451c0b2f7Stbbdev
7551c0b2f7Stbbdev using init_iterator_type = move_support_tests::FooPairIterator;
7651c0b2f7Stbbdev }; // struct COMultimapTraits
7751c0b2f7Stbbdev
7851c0b2f7Stbbdev struct OrderedMapTypesTester {
7951c0b2f7Stbbdev template <bool DefCtorPresent, typename ValueType>
checkOrderedMapTypesTester8051c0b2f7Stbbdev void check( const std::list<ValueType>& lst ) {
8151c0b2f7Stbbdev using key_type = typename ValueType::first_type;
8251c0b2f7Stbbdev using mapped_type = typename ValueType::second_type;
8351c0b2f7Stbbdev
8451c0b2f7Stbbdev TypeTester<DefCtorPresent, tbb::concurrent_map<key_type, mapped_type>>(lst);
8551c0b2f7Stbbdev TypeTester<DefCtorPresent, tbb::concurrent_multimap<key_type, mapped_type>>(lst);
8651c0b2f7Stbbdev }
8751c0b2f7Stbbdev }; // struct OrderedMapTypesTester
8851c0b2f7Stbbdev
test_specific_types()8951c0b2f7Stbbdev void test_specific_types() {
9051c0b2f7Stbbdev test_map_specific_types<OrderedMapTypesTester>();
9151c0b2f7Stbbdev
9251c0b2f7Stbbdev // Regression test for a problem with excessive requirements of emplace()
9351c0b2f7Stbbdev test_emplace_insert<tbb::concurrent_map<int*, test::unique_ptr<int>>,std::false_type>
9451c0b2f7Stbbdev (new int, new int);
9551c0b2f7Stbbdev test_emplace_insert<tbb::concurrent_multimap<int*, test::unique_ptr<int>>,std::false_type>
9651c0b2f7Stbbdev (new int, new int);
9751c0b2f7Stbbdev }
9851c0b2f7Stbbdev
9951c0b2f7Stbbdev // Regression test for an issue in lock free algorithms
10051c0b2f7Stbbdev // In some cases this test hangs due to broken skip list internal structure on levels > 1
10151c0b2f7Stbbdev // This issue was resolved by adding index_number into the skip list node
test_cycles_absense()10251c0b2f7Stbbdev void test_cycles_absense() {
10351c0b2f7Stbbdev for (std::size_t execution = 0; execution != 10; ++execution) {
10451c0b2f7Stbbdev tbb::concurrent_multimap<int, int> mmap;
10551c0b2f7Stbbdev std::vector<int> v(2);
10651c0b2f7Stbbdev int vector_size = int(v.size());
10751c0b2f7Stbbdev
10851c0b2f7Stbbdev for (int i = 0; i != vector_size; ++i) {
10951c0b2f7Stbbdev v[i] = i;
11051c0b2f7Stbbdev }
11151c0b2f7Stbbdev size_t num_threads = 4; // Can be changed to 2 for debugging
11251c0b2f7Stbbdev
11351c0b2f7Stbbdev utils::NativeParallelFor(num_threads, [&](size_t) {
11451c0b2f7Stbbdev for (int i = 0; i != vector_size; ++i) {
11551c0b2f7Stbbdev mmap.emplace(i, i);
11651c0b2f7Stbbdev }
11751c0b2f7Stbbdev });
11851c0b2f7Stbbdev
11951c0b2f7Stbbdev for (int i = 0; i != vector_size; ++i) {
12051c0b2f7Stbbdev REQUIRE(mmap.count(i) == num_threads);
12151c0b2f7Stbbdev }
12251c0b2f7Stbbdev }
12351c0b2f7Stbbdev }
12451c0b2f7Stbbdev
12551c0b2f7Stbbdev //! \brief \ref error_guessing
12651c0b2f7Stbbdev TEST_CASE("basic test for concurrent_map with greater compare") {
12751c0b2f7Stbbdev test_basic<greater_map_type>();
12851c0b2f7Stbbdev }
12951c0b2f7Stbbdev
13051c0b2f7Stbbdev //! \brief \ref error_guessing
13151c0b2f7Stbbdev TEST_CASE("basic test for concurrent_multimap with greater compare") {
13251c0b2f7Stbbdev test_basic<greater_multimap_type>();
13351c0b2f7Stbbdev }
13451c0b2f7Stbbdev
13551c0b2f7Stbbdev //! \brief \ref resource_usage
13651c0b2f7Stbbdev TEST_CASE("basic test for concurrent_map with elements ctor and dtor check") {
13751c0b2f7Stbbdev Checker<checked_map_type::value_type> checker;
13851c0b2f7Stbbdev test_basic<checked_map_type>();
13951c0b2f7Stbbdev }
14051c0b2f7Stbbdev
14151c0b2f7Stbbdev //! \brief \ref resource_usage
14251c0b2f7Stbbdev TEST_CASE("basic test for concurrent_multimap with elements ctor and dtor check") {
14351c0b2f7Stbbdev Checker<checked_multimap_type::value_type> checker;
14451c0b2f7Stbbdev test_basic<checked_multimap_type>();
14551c0b2f7Stbbdev }
14651c0b2f7Stbbdev
14751c0b2f7Stbbdev //! \brief \ref resource_usage
14851c0b2f7Stbbdev TEST_CASE("basic test for concurrent_map with elements state check") {
14951c0b2f7Stbbdev test_basic<checked_state_map_type, /*CheckState = */std::true_type>();
15051c0b2f7Stbbdev }
15151c0b2f7Stbbdev
15251c0b2f7Stbbdev //! \brief \ref resource_usage
15351c0b2f7Stbbdev TEST_CASE("basic test for concurrent_multimap with elements state check") {
15451c0b2f7Stbbdev test_basic<checked_state_multimap_type, /*CheckState = */std::true_type>();
15551c0b2f7Stbbdev }
15651c0b2f7Stbbdev
15751c0b2f7Stbbdev //! \brief \ref error_guessing
15851c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_map with greater compare") {
15951c0b2f7Stbbdev test_concurrent<greater_map_type>();
16051c0b2f7Stbbdev }
16151c0b2f7Stbbdev
16251c0b2f7Stbbdev //! \brief \ref error_guessing
16351c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap with greater compare") {
16451c0b2f7Stbbdev test_concurrent<greater_multimap_type>();
16551c0b2f7Stbbdev }
16651c0b2f7Stbbdev
16751c0b2f7Stbbdev //! \brief \ref resource_usage
16851c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_map with elements ctor and dtor check") {
16951c0b2f7Stbbdev Checker<checked_map_type::value_type> checker;
17051c0b2f7Stbbdev test_concurrent<checked_map_type>();
17151c0b2f7Stbbdev }
17251c0b2f7Stbbdev
17351c0b2f7Stbbdev //! \brief \ref resource_usage
17451c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap with elements ctor and dtor check") {
17551c0b2f7Stbbdev Checker<checked_multimap_type::value_type> checker;
17651c0b2f7Stbbdev test_concurrent<checked_multimap_type>();
17751c0b2f7Stbbdev }
17851c0b2f7Stbbdev
17951c0b2f7Stbbdev //! \brief \ref resource_usage
18051c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_map with elements state check") {
18151c0b2f7Stbbdev test_concurrent<checked_state_map_type>();
18251c0b2f7Stbbdev }
18351c0b2f7Stbbdev
18451c0b2f7Stbbdev //! \brief \ref resource_usage
18551c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap with elements state check") {
18651c0b2f7Stbbdev test_concurrent<checked_state_multimap_type>();
18751c0b2f7Stbbdev }
18851c0b2f7Stbbdev
18951c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
19051c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap no unique keys") {
19151c0b2f7Stbbdev test_concurrent<multimap_type>(true);
19251c0b2f7Stbbdev }
19351c0b2f7Stbbdev
19451c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
19551c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap with greater compare and no unique keys") {
19651c0b2f7Stbbdev test_concurrent<greater_multimap_type>(true);
19751c0b2f7Stbbdev }
19851c0b2f7Stbbdev
19951c0b2f7Stbbdev //! \brief \ref interface \ref error_guessing
20051c0b2f7Stbbdev TEST_CASE("range based for support in concurrent_map") {
20151c0b2f7Stbbdev test_range_based_for_support<map_type>();
20251c0b2f7Stbbdev }
20351c0b2f7Stbbdev
20451c0b2f7Stbbdev //! \brief \ref interface \ref error_guessing
20551c0b2f7Stbbdev TEST_CASE("range based for support in concurrent_multimap") {
20651c0b2f7Stbbdev test_range_based_for_support<multimap_type>();
20751c0b2f7Stbbdev }
20851c0b2f7Stbbdev
20951c0b2f7Stbbdev //! \brief \ref regression
21051c0b2f7Stbbdev TEST_CASE("concurrent_map/multimap with specific key/mapped types") {
21151c0b2f7Stbbdev test_specific_types();
21251c0b2f7Stbbdev }
21351c0b2f7Stbbdev
21451c0b2f7Stbbdev // TODO: add test with scoped_allocator_adaptor with broken macro
21551c0b2f7Stbbdev
21651c0b2f7Stbbdev //! \brief \ref regression
21751c0b2f7Stbbdev TEST_CASE("broken internal structure for multimap") {
21851c0b2f7Stbbdev test_cycles_absense();
21951c0b2f7Stbbdev }
22051c0b2f7Stbbdev
22151c0b2f7Stbbdev //! \brief \ref error_guessing
22251c0b2f7Stbbdev TEST_CASE("concurrent_map::swap with not always equal allocator") {
22351c0b2f7Stbbdev using not_always_equal_alloc_map_type = tbb::concurrent_map<int, int, std::less<int>,
22451c0b2f7Stbbdev NotAlwaysEqualAllocator<std::pair<const int, int>>>;
22551c0b2f7Stbbdev test_swap_not_always_equal_allocator<not_always_equal_alloc_map_type>();
22651c0b2f7Stbbdev }
22751c0b2f7Stbbdev
22851c0b2f7Stbbdev //! \brief \ref error_guessing
22951c0b2f7Stbbdev TEST_CASE("concurrent_multimap::swap with not always equal allocator") {
23051c0b2f7Stbbdev using not_always_equal_alloc_mmap_type = tbb::concurrent_multimap<int, int, std::less<int>,
23151c0b2f7Stbbdev NotAlwaysEqualAllocator<std::pair<const int, int>>>;
23251c0b2f7Stbbdev test_swap_not_always_equal_allocator<not_always_equal_alloc_mmap_type>();
23351c0b2f7Stbbdev }
23451c0b2f7Stbbdev
23551c0b2f7Stbbdev #if TBB_USE_EXCEPTIONS
23651c0b2f7Stbbdev //! \brief \ref error_guessing
23751c0b2f7Stbbdev TEST_CASE("concurrent_map throwing copy constructor") {
23851c0b2f7Stbbdev using exception_map_type = tbb::concurrent_map<ThrowOnCopy, ThrowOnCopy>;
23951c0b2f7Stbbdev test_exception_on_copy_ctor<exception_map_type>();
24051c0b2f7Stbbdev }
24151c0b2f7Stbbdev
24251c0b2f7Stbbdev //! \brief \ref error_guessing
24351c0b2f7Stbbdev TEST_CASE("concurrent_multimap throwing copy constructor") {
24451c0b2f7Stbbdev using exception_mmap_type = tbb::concurrent_multimap<ThrowOnCopy, ThrowOnCopy>;
24551c0b2f7Stbbdev test_exception_on_copy_ctor<exception_mmap_type>();
24651c0b2f7Stbbdev }
24751c0b2f7Stbbdev #endif // TBB_USE_EXCEPTIONS
248*478de5b1Stbbdev
249*478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT
250*478de5b1Stbbdev //! \brief \ref error_guessing
251*478de5b1Stbbdev TEST_CASE("container_range concept for concurrent_map ranges") {
252*478de5b1Stbbdev static_assert(test_concepts::container_range<typename tbb::concurrent_map<int, int>::range_type>);
253*478de5b1Stbbdev static_assert(test_concepts::container_range<typename tbb::concurrent_map<int, int>::const_range_type>);
254*478de5b1Stbbdev }
255*478de5b1Stbbdev
256*478de5b1Stbbdev //! \brief \ref error_guessing
257*478de5b1Stbbdev TEST_CASE("container_range concept for concurrent_multimap ranges") {
258*478de5b1Stbbdev static_assert(test_concepts::container_range<typename tbb::concurrent_multimap<int, int>::range_type>);
259*478de5b1Stbbdev static_assert(test_concepts::container_range<typename tbb::concurrent_multimap<int, int>::const_range_type>);
260*478de5b1Stbbdev }
261*478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT
262