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 "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 TestFuncDefinitionPresence( info::numa_nodes, (), std::vector<tbb::numa_node_id> ); 172 TestFuncDefinitionPresence( info::default_concurrency, (tbb::numa_node_id), int ); 173 } 174 #endif 175 176 static void DefinitionPresence() { 177 TestTypeDefinitionPresence( cache_aligned_allocator<int> ); 178 TestTypeDefinitionPresence( tbb_hash_compare<int> ); 179 TestTypeDefinitionPresence2( concurrent_hash_map<int, int> ); 180 TestTypeDefinitionPresence2( concurrent_unordered_map<int, int> ); 181 TestTypeDefinitionPresence2( concurrent_unordered_multimap<int, int> ); 182 TestTypeDefinitionPresence( concurrent_unordered_set<int> ); 183 TestTypeDefinitionPresence( concurrent_unordered_multiset<int> ); 184 TestTypeDefinitionPresence2( concurrent_map<int, int> ); 185 TestTypeDefinitionPresence2( concurrent_multimap<int, int> ); 186 TestTypeDefinitionPresence( concurrent_set<int> ); 187 TestTypeDefinitionPresence( concurrent_multiset<int> ); 188 TestTypeDefinitionPresence( concurrent_bounded_queue<int> ); 189 TestTypeDefinitionPresence( concurrent_queue<int> ); 190 TestTypeDefinitionPresence( concurrent_priority_queue<int> ); 191 TestTypeDefinitionPresence( concurrent_vector<int> ); 192 TestTypeDefinitionPresence( combinable<int> ); 193 TestTypeDefinitionPresence( enumerable_thread_specific<int> ); 194 /* Flow graph names */ 195 TestTypeDefinitionPresence( flow::graph ); 196 TestTypeDefinitionPresence( flow::continue_msg ); 197 TestTypeDefinitionPresence2(flow::tagged_msg<int, int> ); 198 TestFuncDefinitionPresence( flow::make_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void ); 199 TestFuncDefinitionPresence( flow::remove_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void ); 200 typedef std::tuple<int, int> intpair; 201 TestTypeDefinitionPresence( flow::input_node<int> ); 202 TestTypeDefinitionPresence3(flow::function_node<int, int, tbb::flow::rejecting> ); 203 TestTypeDefinitionPresence3(flow::multifunction_node<int, intpair, tbb::flow::queueing> ); 204 TestTypeDefinitionPresence3(flow::async_node<int, int, tbb::flow::queueing_lightweight> ); 205 TestTypeDefinitionPresence2(flow::continue_node<int, tbb::flow::lightweight> ); 206 TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::reserving> ); 207 TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::key_matching<int> > ); 208 TestTypeDefinitionPresence( flow::split_node<intpair> ); 209 TestTypeDefinitionPresence( flow::overwrite_node<int> ); 210 TestTypeDefinitionPresence( flow::write_once_node<int> ); 211 TestTypeDefinitionPresence( flow::broadcast_node<int> ); 212 TestTypeDefinitionPresence( flow::buffer_node<int> ); 213 TestTypeDefinitionPresence( flow::queue_node<int> ); 214 TestTypeDefinitionPresence( flow::sequencer_node<int> ); 215 TestTypeDefinitionPresence( flow::priority_queue_node<int> ); 216 TestTypeDefinitionPresence( flow::limiter_node<int> ); 217 TestTypeDefinitionPresence2(flow::indexer_node<int, int> ); 218 TestTypeDefinitionPresence2(flow::composite_node<std::tuple<int>, std::tuple<int> > ); 219 /* Mutex names */ 220 TestTypeDefinitionPresence( null_mutex ); 221 TestTypeDefinitionPresence( null_rw_mutex ); 222 TestTypeDefinitionPresence( queuing_mutex ); 223 TestTypeDefinitionPresence( queuing_rw_mutex ); 224 TestTypeDefinitionPresence( spin_mutex ); 225 TestTypeDefinitionPresence( spin_rw_mutex ); 226 TestTypeDefinitionPresence( speculative_spin_mutex ); 227 TestTypeDefinitionPresence( speculative_spin_rw_mutex ); 228 TestTypeDefinitionPresence( task_group_context ); 229 TestTypeDefinitionPresence( task_group ); 230 /* Algorithm related names */ 231 TestTypeDefinitionPresence( blocked_range<int> ); 232 TestTypeDefinitionPresence( blocked_range2d<int> ); 233 TestTypeDefinitionPresence( blocked_range3d<int> ); 234 TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, const Body&), void ); 235 TestFuncDefinitionPresence( parallel_for_each, (int*, int*, const Body1&), void ); 236 TestFuncDefinitionPresence( parallel_for, (int, int, int, const Body1&), void ); 237 TestFuncDefinitionPresence( parallel_for, (const tbb::blocked_range<int>&, const Body2&, const tbb::simple_partitioner&), void ); 238 TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int ); 239 TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::affinity_partitioner&), void ); 240 TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int ); 241 TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::static_partitioner&), void ); 242 TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range2d<int>&, Body3&, const tbb::auto_partitioner&), void ); 243 TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range<int>&, const int&, const Body3a&, const Body1b&), int ); 244 typedef int intarray[10]; 245 TestFuncDefinitionPresence( parallel_sort, (int*, int*), void ); 246 TestFuncDefinitionPresence( parallel_sort, (intarray&, const Body1b&), void ); 247 TestFuncDefinitionPresence( parallel_pipeline, (size_t, const tbb::filter<void,void>&), void ); 248 TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, tbb::task_group_context&), void ); 249 TestFuncDefinitionPresence( parallel_for_each, (const intarray&, const Body1a&, tbb::task_group_context&), void ); 250 TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, const tbb::auto_partitioner&, tbb::task_group_context&), void ); 251 TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, tbb::task_group_context&), void ); 252 TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::auto_partitioner&, tbb::task_group_context&), void ); 253 TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void ); 254 TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::simple_partitioner&, tbb::task_group_context&), void ); 255 TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void ); 256 TestTypeDefinitionPresence( proportional_split ); 257 258 TestTypeDefinitionPresence( task_arena ); 259 TestFuncDefinitionPresence( this_task_arena::current_thread_index, (), int ); 260 TestFuncDefinitionPresence( this_task_arena::max_concurrency, (), 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