151c0b2f7Stbbdev /*
2*d5fd1e97SKonstantin Boyarinov Copyright (c) 2005-2023 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
17b15aabb3Stbbdev #if __INTEL_COMPILER && _MSC_VER
18b15aabb3Stbbdev #pragma warning(disable : 2586) // decorated name length exceeded, name was truncated
19b15aabb3Stbbdev #endif
20b15aabb3Stbbdev
2151c0b2f7Stbbdev #define TBB_DEFINE_STD_HASH_SPECIALIZATIONS 1
2251c0b2f7Stbbdev #include <tbb/concurrent_unordered_map.h>
2351c0b2f7Stbbdev #include "common/concurrent_unordered_common.h"
2451c0b2f7Stbbdev
2551c0b2f7Stbbdev //! \file test_concurrent_unordered_map.cpp
2651c0b2f7Stbbdev //! \brief Test for [containers.concurrent_unordered_map containers.concurrent_unordered_multimap] specifications
2751c0b2f7Stbbdev
2851c0b2f7Stbbdev template <typename... Args>
2951c0b2f7Stbbdev struct AllowMultimapping<tbb::concurrent_unordered_multimap<Args...>> : std::true_type {};
3051c0b2f7Stbbdev
3151c0b2f7Stbbdev template <typename Key, typename Mapped>
3251c0b2f7Stbbdev using MyAllocator = LocalCountingAllocator<std::allocator<std::pair<const Key, Mapped>>>;
3351c0b2f7Stbbdev
3451c0b2f7Stbbdev using move_support_tests::FooWithAssign;
3551c0b2f7Stbbdev
3651c0b2f7Stbbdev using map_type = tbb::concurrent_unordered_map<int, int, std::hash<int>, std::equal_to<int>, MyAllocator<int, int>>;
3751c0b2f7Stbbdev using multimap_type = tbb::concurrent_unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, MyAllocator<int, int>>;
3851c0b2f7Stbbdev using degenerate_map_type = tbb::concurrent_unordered_map<int, int, degenerate_hash<int>, std::equal_to<int>, MyAllocator<int, int>>;
3951c0b2f7Stbbdev using degenerate_multimap_type = tbb::concurrent_unordered_multimap<int, int, degenerate_hash<int>, std::equal_to<int>, MyAllocator<int, int>>;
4051c0b2f7Stbbdev
4151c0b2f7Stbbdev using checked_map_type = tbb::concurrent_unordered_map<int, CheckType<int>, std::hash<int>, std::equal_to<int>, MyAllocator<int, CheckType<int>>>;
4251c0b2f7Stbbdev using checked_multimap_type = tbb::concurrent_unordered_multimap<int, CheckType<int>, std::hash<int>, std::equal_to<int>, MyAllocator<int, CheckType<int>>>;
4351c0b2f7Stbbdev using checked_state_map_type = tbb::concurrent_unordered_map<intptr_t, FooWithAssign, std::hash<intptr_t>,
4451c0b2f7Stbbdev std::equal_to<intptr_t>, MyAllocator<intptr_t, FooWithAssign>>;
4551c0b2f7Stbbdev using checked_state_multimap_type = tbb::concurrent_unordered_multimap<intptr_t, FooWithAssign, std::hash<intptr_t>,
4651c0b2f7Stbbdev std::equal_to<intptr_t>, MyAllocator<intptr_t, FooWithAssign>>;
4751c0b2f7Stbbdev
4851c0b2f7Stbbdev struct CumapTraits : UnorderedMoveTraitsBase {
4951c0b2f7Stbbdev template <typename T, typename Allocator>
5051c0b2f7Stbbdev using container_type = tbb::concurrent_unordered_map<T, T, std::hash<T>, std::equal_to<T>, Allocator>;
5151c0b2f7Stbbdev
5251c0b2f7Stbbdev template <typename T>
5351c0b2f7Stbbdev using container_value_type = std::pair<const T, T>;
5451c0b2f7Stbbdev
5551c0b2f7Stbbdev using init_iterator_type = move_support_tests::FooPairIterator;
5651c0b2f7Stbbdev }; // struct CumapTraits
5751c0b2f7Stbbdev
5851c0b2f7Stbbdev struct CumultimapTraits : UnorderedMoveTraitsBase {
5951c0b2f7Stbbdev template <typename T, typename Allocator>
6051c0b2f7Stbbdev using container_type = tbb::concurrent_unordered_multimap<T, T, std::hash<T>, std::equal_to<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 CumultimapTraits
6751c0b2f7Stbbdev
6851c0b2f7Stbbdev template <>
6951c0b2f7Stbbdev struct SpecialTests<map_type> {
TestSpecialTests7051c0b2f7Stbbdev static void Test() {
7151c0b2f7Stbbdev SpecialMapTests<map_type>();
7251c0b2f7Stbbdev }
7351c0b2f7Stbbdev };
7451c0b2f7Stbbdev
7551c0b2f7Stbbdev template <>
7651c0b2f7Stbbdev struct SpecialTests<multimap_type> {
TestSpecialTests7751c0b2f7Stbbdev static void Test() {
7851c0b2f7Stbbdev SpecialMultiMapTests<multimap_type>();
7951c0b2f7Stbbdev }
8051c0b2f7Stbbdev };
8151c0b2f7Stbbdev
8251c0b2f7Stbbdev struct UnorderedMapTypesTester {
8351c0b2f7Stbbdev template <template <typename...> class GeneralTableType, typename Key, typename Mapped>
8451c0b2f7Stbbdev using table_type = GeneralTableType<Key, Mapped, std::hash<Key>, utils::IsEqual>;
8551c0b2f7Stbbdev
8651c0b2f7Stbbdev template <bool DefCtorPresent, typename ValueType>
checkUnorderedMapTypesTester8751c0b2f7Stbbdev void check( const std::list<ValueType>& lst ) {
8851c0b2f7Stbbdev using key_type = typename std::remove_const<typename ValueType::first_type>::type;
8951c0b2f7Stbbdev using mapped_type = typename ValueType::second_type;
9051c0b2f7Stbbdev
9151c0b2f7Stbbdev TypeTester<DefCtorPresent, table_type<tbb::concurrent_unordered_map, key_type, mapped_type>>(lst);
9251c0b2f7Stbbdev TypeTester<DefCtorPresent, table_type<tbb::concurrent_unordered_multimap, key_type, mapped_type>>(lst);
9351c0b2f7Stbbdev }
9451c0b2f7Stbbdev }; // struct UnorderedMapTypesTester
9551c0b2f7Stbbdev
test_specific_types()9651c0b2f7Stbbdev void test_specific_types() {
9751c0b2f7Stbbdev test_map_specific_types<UnorderedMapTypesTester>();
9851c0b2f7Stbbdev
9951c0b2f7Stbbdev // Regression test for a problem with excessive requirements of emplace()
10051c0b2f7Stbbdev test_emplace_insert<tbb::concurrent_unordered_map<int*, test::unique_ptr<int>>, std::false_type>
10151c0b2f7Stbbdev (new int, new int);
10251c0b2f7Stbbdev test_emplace_insert<tbb::concurrent_unordered_multimap<int*, test::unique_ptr<int>>, std::false_type>
10351c0b2f7Stbbdev (new int, new int);
10451c0b2f7Stbbdev }
10551c0b2f7Stbbdev
10651c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
10751c0b2f7Stbbdev TEST_CASE("basic test for concurrent_unordered_map with degenerate hash") {
10851c0b2f7Stbbdev test_basic<degenerate_map_type>();
10951c0b2f7Stbbdev }
11051c0b2f7Stbbdev
11151c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
11251c0b2f7Stbbdev TEST_CASE("basic test for concurrent_unordered_multimap with degenerate hash") {
11351c0b2f7Stbbdev test_basic<degenerate_multimap_type>();
11451c0b2f7Stbbdev }
11551c0b2f7Stbbdev
11651c0b2f7Stbbdev //! \brief \ref resource_usage
11751c0b2f7Stbbdev TEST_CASE("basic test for concurrent_unordered_map with elements ctor and dtor check") {
11851c0b2f7Stbbdev Checker<checked_map_type::mapped_type> checker;
11951c0b2f7Stbbdev test_basic<checked_map_type>();
12051c0b2f7Stbbdev }
12151c0b2f7Stbbdev
12251c0b2f7Stbbdev //! \brief \ref resource_usage
12351c0b2f7Stbbdev TEST_CASE("basic test for concurrent_unordered_multimap with elements ctor and dtor check") {
12451c0b2f7Stbbdev Checker<checked_multimap_type::mapped_type> checker;
12551c0b2f7Stbbdev test_basic<checked_multimap_type>();
12651c0b2f7Stbbdev }
12751c0b2f7Stbbdev
12851c0b2f7Stbbdev //! \brief \ref resource_usage
12951c0b2f7Stbbdev TEST_CASE("basic test for concurrent_unordered_map with elements state check") {
13051c0b2f7Stbbdev test_basic<checked_state_map_type, /*CheckState = */std::true_type>();
13151c0b2f7Stbbdev }
13251c0b2f7Stbbdev
13351c0b2f7Stbbdev //! \brief \ref resource_usage
13451c0b2f7Stbbdev TEST_CASE("basic test for concurrent_unordered_multimap with elements state check") {
13551c0b2f7Stbbdev test_basic<checked_state_multimap_type, /*CheckState = */std::true_type>();
13651c0b2f7Stbbdev }
13751c0b2f7Stbbdev
13851c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
13951c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_unordered_map with degenerate hash") {
14051c0b2f7Stbbdev test_concurrent<degenerate_map_type>();
14151c0b2f7Stbbdev }
14251c0b2f7Stbbdev
14351c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
14451c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_unordered_multimap with degenerate hash") {
14551c0b2f7Stbbdev test_concurrent<degenerate_multimap_type>();
14651c0b2f7Stbbdev }
14751c0b2f7Stbbdev
14851c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
14951c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_unordered_multimap no unique keys") {
15051c0b2f7Stbbdev test_concurrent<multimap_type>(true);
15151c0b2f7Stbbdev }
15251c0b2f7Stbbdev
15351c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
15451c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_unordered_multimap with degenerate hash and no unique keys") {
15551c0b2f7Stbbdev test_concurrent<degenerate_multimap_type>(true);
15651c0b2f7Stbbdev }
15751c0b2f7Stbbdev
15851c0b2f7Stbbdev //! \brief \ref resource_usage
15951c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_unordered_map with elements ctor and dtor check") {
16051c0b2f7Stbbdev Checker<checked_map_type::mapped_type> checker;
16151c0b2f7Stbbdev test_concurrent<checked_map_type>();
16251c0b2f7Stbbdev }
16351c0b2f7Stbbdev
16451c0b2f7Stbbdev //! \brief \ref resource_usage
16551c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_unordered_multimap with elements ctor and dtor check") {
16651c0b2f7Stbbdev Checker<checked_multimap_type::mapped_type> checker;
16751c0b2f7Stbbdev test_concurrent<checked_multimap_type>();
16851c0b2f7Stbbdev }
16951c0b2f7Stbbdev
17051c0b2f7Stbbdev //! \brief \ref resource_usage
17151c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_unordered_map with elements state check") {
17251c0b2f7Stbbdev test_concurrent<checked_state_map_type>();
17351c0b2f7Stbbdev }
17451c0b2f7Stbbdev
17551c0b2f7Stbbdev //! \brief \ref resource_usage
17651c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_unordered_multimap with elements state check") {
17751c0b2f7Stbbdev test_concurrent<checked_state_multimap_type>();
17851c0b2f7Stbbdev }
17951c0b2f7Stbbdev
18051c0b2f7Stbbdev //! \brief \ref interface \ref error_guessing
18151c0b2f7Stbbdev TEST_CASE("range based for support in concurrent_unordered_map") {
18251c0b2f7Stbbdev test_range_based_for_support<map_type>();
18351c0b2f7Stbbdev }
18451c0b2f7Stbbdev
18551c0b2f7Stbbdev //! \brief \ref interface \ref error_guessing
18651c0b2f7Stbbdev TEST_CASE("range based for support in concurrent_unordered_multimap") {
18751c0b2f7Stbbdev test_range_based_for_support<multimap_type>();
18851c0b2f7Stbbdev }
18951c0b2f7Stbbdev
19051c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
19151c0b2f7Stbbdev TEST_CASE("merge and concurrent merge in concurrent_unordered_map with degenerative hash") {
19251c0b2f7Stbbdev node_handling_tests::test_merge<map_type, degenerate_multimap_type>(1000);
19351c0b2f7Stbbdev }
19451c0b2f7Stbbdev
19551c0b2f7Stbbdev //! \brief \ref regression
19651c0b2f7Stbbdev TEST_CASE("concurrent_unordered map/multimap with specific key/mapped types") {
19751c0b2f7Stbbdev test_specific_types();
19851c0b2f7Stbbdev }
19951c0b2f7Stbbdev
20051c0b2f7Stbbdev //! \brief \ref error_guessing
20151c0b2f7Stbbdev TEST_CASE("concurrent_unordered_map::swap with not always equal allocator") {
20251c0b2f7Stbbdev using not_always_equal_alloc_map_type = tbb::concurrent_unordered_map<int, int, std::hash<int>, std::equal_to<int>,
20351c0b2f7Stbbdev NotAlwaysEqualAllocator<std::pair<const int, int>>>;
20451c0b2f7Stbbdev test_swap_not_always_equal_allocator<not_always_equal_alloc_map_type>();
20551c0b2f7Stbbdev }
20651c0b2f7Stbbdev
20751c0b2f7Stbbdev //! \brief \ref error_guessing
20851c0b2f7Stbbdev TEST_CASE("concurrent_unordered_multimap::swap with not always equal allocator") {
20951c0b2f7Stbbdev using not_always_equal_alloc_mmap_type = tbb::concurrent_unordered_multimap<int, int, std::hash<int>, std::equal_to<int>,
21051c0b2f7Stbbdev NotAlwaysEqualAllocator<std::pair<const int, int>>>;
21151c0b2f7Stbbdev test_swap_not_always_equal_allocator<not_always_equal_alloc_mmap_type>();
21251c0b2f7Stbbdev }
21351c0b2f7Stbbdev
21451c0b2f7Stbbdev #if TBB_USE_EXCEPTIONS
21551c0b2f7Stbbdev //! \brief \ref error_guessing
21651c0b2f7Stbbdev TEST_CASE("concurrent_unordered_map throwing copy constructor") {
21751c0b2f7Stbbdev using exception_map_type = tbb::concurrent_unordered_map<ThrowOnCopy, ThrowOnCopy>;
21851c0b2f7Stbbdev test_exception_on_copy_ctor<exception_map_type>();
21951c0b2f7Stbbdev }
22051c0b2f7Stbbdev
22151c0b2f7Stbbdev //! \brief \ref error_guessing
22251c0b2f7Stbbdev TEST_CASE("concurrent_unordered_multimap throwing copy constructor") {
22351c0b2f7Stbbdev using exception_mmap_type = tbb::concurrent_unordered_multimap<ThrowOnCopy, ThrowOnCopy>;
22451c0b2f7Stbbdev test_exception_on_copy_ctor<exception_mmap_type>();
22551c0b2f7Stbbdev }
22651c0b2f7Stbbdev
22751c0b2f7Stbbdev //! \brief \ref error_guessing
22851c0b2f7Stbbdev TEST_CASE("concurrent_unordered_map whitebox throwing copy constructor") {
22951c0b2f7Stbbdev using allocator_type = StaticSharedCountingAllocator<std::allocator<std::pair<const int, int>>>;
23051c0b2f7Stbbdev using exception_mmap_type = tbb::concurrent_unordered_map<int, int, std::hash<int>, std::equal_to<int>, allocator_type>;
23151c0b2f7Stbbdev
23251c0b2f7Stbbdev exception_mmap_type map;
233b15aabb3Stbbdev for (int i = 0; i < 10; ++i) {
23451c0b2f7Stbbdev map.insert(std::pair<const int, int>(i, 42));
23551c0b2f7Stbbdev }
23651c0b2f7Stbbdev
23751c0b2f7Stbbdev allocator_type::set_limits(1);
__anonf1fab3910102null23851c0b2f7Stbbdev REQUIRE_THROWS_AS( [&] {
23951c0b2f7Stbbdev exception_mmap_type map1(map);
24051c0b2f7Stbbdev utils::suppress_unused_warning(map1);
24151c0b2f7Stbbdev }(), const std::bad_alloc);
24251c0b2f7Stbbdev }
24351c0b2f7Stbbdev
24451c0b2f7Stbbdev #endif // TBB_USE_EXCEPTIONS
24551c0b2f7Stbbdev
24651c0b2f7Stbbdev // TODO: add test_scoped_allocator support with broken macro
247478de5b1Stbbdev
248478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT
249478de5b1Stbbdev //! \brief \ref error_guessing
250478de5b1Stbbdev TEST_CASE("container_range concept for concurrent_unordered_map ranges") {
251478de5b1Stbbdev static_assert(test_concepts::container_range<typename tbb::concurrent_unordered_map<int, int>::range_type>);
252478de5b1Stbbdev static_assert(test_concepts::container_range<typename tbb::concurrent_unordered_map<int, int>::const_range_type>);
253478de5b1Stbbdev }
254478de5b1Stbbdev
255478de5b1Stbbdev //! \brief \ref error_guessing
256478de5b1Stbbdev TEST_CASE("container_range concept for concurrent_unordered_multimap ranges") {
257478de5b1Stbbdev static_assert(test_concepts::container_range<typename tbb::concurrent_unordered_multimap<int, int>::range_type>);
258478de5b1Stbbdev static_assert(test_concepts::container_range<typename tbb::concurrent_unordered_multimap<int, int>::const_range_type>);
259478de5b1Stbbdev }
260478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT
261*d5fd1e97SKonstantin Boyarinov
262*d5fd1e97SKonstantin Boyarinov //! \brief \ref regression
263*d5fd1e97SKonstantin Boyarinov TEST_CASE("reserve(0) issue regression test") {
264*d5fd1e97SKonstantin Boyarinov test_reserve_regression<oneapi::tbb::concurrent_unordered_map<int, int>>();
265*d5fd1e97SKonstantin Boyarinov test_reserve_regression<oneapi::tbb::concurrent_unordered_multimap<int, int>>();
266*d5fd1e97SKonstantin Boyarinov }
267