1 /* 2 Copyright (c) 2005-2020 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 //! \file test_tbb_header.cpp 18 //! \brief Test for [all] specification 19 20 /** 21 This test ensures that tbb.h brings in all the public TBB interface definitions, 22 and if all the necessary symbols are exported from the library. 23 24 Most of the checks happen at the compilation or link phases. 25 **/ 26 27 #define __TBB_NO_IMPLICIT_LINKAGE 1 28 29 #if __TBB_CPF_BUILD 30 // Add testing of preview features 31 #define TBB_PREVIEW_CONCURRENT_LRU_CACHE 1 32 #define TBB_PREVIEW_VARIADIC_PARALLEL_INVOKE 1 33 #define TBB_PREVIEW_BLOCKED_RANGE_ND 1 34 #define TBB_PREVIEW_ISOLATED_TASK_GROUP 1 35 #endif 36 37 #if __TBB_TEST_SECONDARY 38 // Test _DEBUG macro custom definitions. 39 #if TBB_USE_DEBUG 40 #ifdef _DEBUG 41 #undef _DEBUG 42 #endif /* _DEBUG */ 43 // Check that empty value successfully enables the debug mode. 44 #define _DEBUG 45 static bool isDebugExpected = true; 46 #else 47 // Check that zero value does not enable the debug mode. 48 #define _DEBUG 0x0 49 static bool isDebugExpected = false; 50 #endif /* TBB_USE_DEBUG */ 51 #define DO_TEST_DEBUG_MACRO 1 52 #else 53 // Test default definitions of _DEBUG. 54 #if _DEBUG 55 static bool isDebugExpected = true; 56 #define DO_TEST_DEBUG_MACRO 1 57 #elif _MSC_VER 58 // for MSVC, _DEBUG not defined indicates a release mode. 59 static bool isDebugExpected = false; 60 #define DO_TEST_DEBUG_MACRO 1 61 #endif /* _DEBUG */ 62 #endif /* __TBB_TEST_SECONDARY */ 63 64 #if DO_TEST_DEBUG_MACRO 65 // Reset TBB_USE_DEBUG defined in makefiles. 66 #undef TBB_USE_DEBUG 67 #endif /* DO_TEST_DEBUG_MACRO */ 68 #define __TBB_CONFIG_PREPROC_ONLY _MSC_VER // For MSVC, prevent including standard headers in tbb_config.h 69 #include "oneapi/tbb/detail/_config.h" 70 71 #if !TBB_USE_DEBUG && defined(_DEBUG) 72 // TBB_USE_DEBUG is 0 but _DEBUG is defined, it means that _DEBUG is 0 73 // MSVC C++ headers consider any definition of _DEBUG, including 0, as debug mode 74 #undef _DEBUG 75 #endif /* !TBB_USE_DEBUG && defined(_DEBUG) */ 76 77 #include "tbb/tbb.h" 78 79 #if !__TBB_TEST_SECONDARY 80 #include "common/test.h" 81 #endif 82 83 static volatile size_t g_sink; 84 85 #define TestTypeDefinitionPresence( Type ) g_sink = sizeof(tbb::Type); 86 #define TestTypeDefinitionPresence2(TypeStart, TypeEnd) g_sink = sizeof(tbb::TypeStart,TypeEnd); 87 #define TestTypeDefinitionPresence3(TypeStart, TypeMid, TypeEnd) g_sink = sizeof(tbb::TypeStart,TypeMid,TypeEnd); 88 #define TestFuncDefinitionPresence(Fn, Args, ReturnType) { ReturnType (*pfn)Args = &tbb::Fn; (void)pfn; } 89 90 struct Body { 91 void operator() () const {} 92 }; 93 struct Body1 { 94 void operator() ( int ) const {} 95 }; 96 struct Body1a { // feeder body for parallel_do 97 void operator() ( int, tbb::feeder<int>& ) const {} 98 }; 99 struct Body1b { // binary operator for reduction and comparison 100 int operator() ( const int, const int ) const { return 0; } 101 }; 102 struct Body2 { 103 Body2 () {} 104 Body2 ( const Body2&, tbb::split ) {} 105 void operator() ( const tbb::blocked_range<int>& ) const {} 106 void join( const Body2& ) {} 107 }; 108 struct Body2a { // for lambda-friendly parallel_reduce 109 int operator() ( const tbb::blocked_range<int>&, const int ) const { return 0; } 110 }; 111 struct Body3 { // for parallel_scan 112 Body3 () {} 113 Body3 ( const Body3&, tbb::split ) {} 114 void operator() ( const tbb::blocked_range2d<int>&, tbb::pre_scan_tag ) const {} 115 void operator() ( const tbb::blocked_range2d<int>&, tbb::final_scan_tag ) const {} 116 void reverse_join( Body3& ) {} 117 void assign( const Body3& ) {} 118 }; 119 struct Body3a { // for lambda-friednly parallel_scan 120 int operator() ( const tbb::blocked_range<int>&, const int, bool ) const { return 0; } 121 }; 122 struct Msg {}; 123 124 // Test if all the necessary symbols are exported for the exceptions thrown by TBB. 125 // Missing exports result either in link error or in runtime assertion failure. 126 #include <stdexcept> 127 128 template <typename E> 129 void TestExceptionClassExports ( const E& exc, tbb::detail::exception_id eid ) { 130 CHECK( eid < tbb::detail::exception_id::last_entry ); 131 #if TBB_USE_EXCEPTIONS 132 for ( int i = 0; i < 2; ++i ) { 133 try { 134 if ( i == 0 ) 135 throw exc; 136 else 137 tbb::detail::throw_exception( eid ); 138 } 139 catch ( E& e ) { 140 CHECK_MESSAGE( e.what(), "Missing what() string" ); 141 } 142 catch ( ... ) { 143 CHECK_MESSAGE( false, "Unrecognized exception. Likely RTTI related exports are missing" ); 144 } 145 } 146 #else /* TBB_USE_EXCEPTIONS */ 147 (void)exc; 148 #endif /* TBB_USE_EXCEPTIONS */ 149 } 150 151 static void TestExceptionClassesExports () { 152 TestExceptionClassExports( std::bad_alloc(), tbb::detail::exception_id::bad_alloc ); 153 TestExceptionClassExports( tbb::bad_last_alloc(), tbb::detail::exception_id::bad_last_alloc ); 154 TestExceptionClassExports( std::invalid_argument("test"), tbb::detail::exception_id::nonpositive_step ); 155 TestExceptionClassExports( std::out_of_range("test"), tbb::detail::exception_id::out_of_range ); 156 TestExceptionClassExports( tbb::missing_wait(), tbb::detail::exception_id::missing_wait ); 157 TestExceptionClassExports( std::out_of_range("test"), tbb::detail::exception_id::invalid_load_factor ); 158 TestExceptionClassExports( std::length_error("test"), tbb::detail::exception_id::reservation_length_error ); 159 TestExceptionClassExports( std::out_of_range("test"), tbb::detail::exception_id::invalid_key ); 160 TestExceptionClassExports( tbb::user_abort(), tbb::detail::exception_id::user_abort ); 161 TestExceptionClassExports( std::runtime_error("test"), tbb::detail::exception_id::bad_tagged_msg_cast ); 162 } 163 164 #if __TBB_CPF_BUILD 165 // These names are only tested in "preview" configuration 166 // When a feature becomes fully supported, its names should be moved to the main test 167 static void TestPreviewNames() { 168 TestTypeDefinitionPresence2( blocked_rangeNd<int,4> ); 169 TestTypeDefinitionPresence2( concurrent_lru_cache<int, int> ); 170 TestTypeDefinitionPresence( isolated_task_group ); 171 } 172 #endif 173 174 static void DefinitionPresence() { 175 TestTypeDefinitionPresence( cache_aligned_allocator<int> ); 176 TestTypeDefinitionPresence( tbb_hash_compare<int> ); 177 TestTypeDefinitionPresence2( concurrent_hash_map<int, int> ); 178 TestTypeDefinitionPresence2( concurrent_unordered_map<int, int> ); 179 TestTypeDefinitionPresence2( concurrent_unordered_multimap<int, int> ); 180 TestTypeDefinitionPresence( concurrent_unordered_set<int> ); 181 TestTypeDefinitionPresence( concurrent_unordered_multiset<int> ); 182 TestTypeDefinitionPresence2( concurrent_map<int, int> ); 183 TestTypeDefinitionPresence2( concurrent_multimap<int, int> ); 184 TestTypeDefinitionPresence( concurrent_set<int> ); 185 TestTypeDefinitionPresence( concurrent_multiset<int> ); 186 TestTypeDefinitionPresence( concurrent_bounded_queue<int> ); 187 TestTypeDefinitionPresence( concurrent_queue<int> ); 188 TestTypeDefinitionPresence( concurrent_priority_queue<int> ); 189 TestTypeDefinitionPresence( concurrent_vector<int> ); 190 TestTypeDefinitionPresence( combinable<int> ); 191 TestTypeDefinitionPresence( enumerable_thread_specific<int> ); 192 /* Flow graph names */ 193 TestTypeDefinitionPresence( flow::graph ); 194 TestTypeDefinitionPresence( flow::continue_msg ); 195 TestTypeDefinitionPresence2(flow::tagged_msg<int, int> ); 196 TestFuncDefinitionPresence( flow::make_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void ); 197 TestFuncDefinitionPresence( flow::remove_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void ); 198 typedef std::tuple<int, int> intpair; 199 TestTypeDefinitionPresence( flow::input_node<int> ); 200 TestTypeDefinitionPresence3(flow::function_node<int, int, tbb::flow::rejecting> ); 201 TestTypeDefinitionPresence3(flow::multifunction_node<int, intpair, tbb::flow::queueing> ); 202 TestTypeDefinitionPresence3(flow::async_node<int, int, tbb::flow::queueing_lightweight> ); 203 TestTypeDefinitionPresence2(flow::continue_node<int, tbb::flow::lightweight> ); 204 TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::reserving> ); 205 TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::key_matching<int> > ); 206 TestTypeDefinitionPresence( flow::split_node<intpair> ); 207 TestTypeDefinitionPresence( flow::overwrite_node<int> ); 208 TestTypeDefinitionPresence( flow::write_once_node<int> ); 209 TestTypeDefinitionPresence( flow::broadcast_node<int> ); 210 TestTypeDefinitionPresence( flow::buffer_node<int> ); 211 TestTypeDefinitionPresence( flow::queue_node<int> ); 212 TestTypeDefinitionPresence( flow::sequencer_node<int> ); 213 TestTypeDefinitionPresence( flow::priority_queue_node<int> ); 214 TestTypeDefinitionPresence( flow::limiter_node<int> ); 215 TestTypeDefinitionPresence2(flow::indexer_node<int, int> ); 216 TestTypeDefinitionPresence2(flow::composite_node<std::tuple<int>, std::tuple<int> > ); 217 /* Mutex names */ 218 TestTypeDefinitionPresence( null_mutex ); 219 TestTypeDefinitionPresence( null_rw_mutex ); 220 TestTypeDefinitionPresence( queuing_mutex ); 221 TestTypeDefinitionPresence( queuing_rw_mutex ); 222 TestTypeDefinitionPresence( spin_mutex ); 223 TestTypeDefinitionPresence( spin_rw_mutex ); 224 TestTypeDefinitionPresence( speculative_spin_mutex ); 225 TestTypeDefinitionPresence( speculative_spin_rw_mutex ); 226 TestTypeDefinitionPresence( task_group_context ); 227 TestTypeDefinitionPresence( task_group ); 228 /* Algorithm related names */ 229 TestTypeDefinitionPresence( blocked_range<int> ); 230 TestTypeDefinitionPresence( blocked_range2d<int> ); 231 TestTypeDefinitionPresence( blocked_range3d<int> ); 232 TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, const Body&), void ); 233 TestFuncDefinitionPresence( parallel_for_each, (int*, int*, const Body1&), void ); 234 TestFuncDefinitionPresence( parallel_for, (int, int, int, const Body1&), void ); 235 TestFuncDefinitionPresence( parallel_for, (const tbb::blocked_range<int>&, const Body2&, const tbb::simple_partitioner&), void ); 236 TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int ); 237 TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::affinity_partitioner&), void ); 238 TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int ); 239 TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::static_partitioner&), void ); 240 TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range2d<int>&, Body3&, const tbb::auto_partitioner&), void ); 241 TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range<int>&, const int&, const Body3a&, const Body1b&), int ); 242 typedef int intarray[10]; 243 TestFuncDefinitionPresence( parallel_sort, (int*, int*), void ); 244 TestFuncDefinitionPresence( parallel_sort, (intarray&, const Body1b&), void ); 245 TestFuncDefinitionPresence( parallel_pipeline, (size_t, const tbb::filter<void,void>&), void ); 246 TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, tbb::task_group_context&), void ); 247 TestFuncDefinitionPresence( parallel_for_each, (const intarray&, const Body1a&, tbb::task_group_context&), void ); 248 TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, const tbb::auto_partitioner&, tbb::task_group_context&), void ); 249 TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, tbb::task_group_context&), void ); 250 TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::auto_partitioner&, tbb::task_group_context&), void ); 251 TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void ); 252 TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::simple_partitioner&, tbb::task_group_context&), void ); 253 TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void ); 254 TestTypeDefinitionPresence( proportional_split ); 255 256 TestTypeDefinitionPresence( task_arena ); 257 TestFuncDefinitionPresence( this_task_arena::current_thread_index, (), int ); 258 TestFuncDefinitionPresence( this_task_arena::max_concurrency, (), int ); 259 TestFuncDefinitionPresence( info::numa_nodes, (), std::vector<tbb::numa_node_id> ); 260 TestFuncDefinitionPresence( info::default_concurrency, (tbb::numa_node_id), int ); 261 TestTypeDefinitionPresence( task_scheduler_observer ); 262 TestTypeDefinitionPresence( tbb_allocator<int> ); 263 TestTypeDefinitionPresence( tick_count ); 264 TestTypeDefinitionPresence( global_control ); 265 266 #if __TBB_CPF_BUILD 267 TestPreviewNames(); 268 #endif 269 #ifdef DO_TEST_DEBUG_MACRO 270 #if TBB_USE_DEBUG 271 CHECK_MESSAGE( isDebugExpected, "Debug mode is observed while release mode is expected." ); 272 #else 273 CHECK_MESSAGE( !isDebugExpected, "Release mode is observed while debug mode is expected." ); 274 #endif /* TBB_USE_DEBUG */ 275 #endif /* DO_TEST_DEBUG_MACRO */ 276 TestExceptionClassesExports(); 277 } 278 279 #if __TBB_TEST_SECONDARY 280 /* This mode is used to produce a secondary object file that is linked with 281 the main one in order to detect "multiple definition" linker error. 282 */ 283 void Secondary() { 284 DefinitionPresence(); 285 } 286 #else 287 //! Test for deifinition presence 288 //! \brief \ref interface 289 TEST_CASE("Test for deifinition presence") { 290 DefinitionPresence(); 291 } 292 293 void Secondary(); 294 //! Test for "multiple definition" linker error 295 //! \brief \ref error_guessing 296 TEST_CASE("Test for multiple definition linker error") { 297 Secondary(); 298 } 299 #endif 300