1 | /* |
2 | Copyright (c) 2005-2019 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 | /** |
18 | This test ensures that tbb.h brings in all the public TBB interface definitions, |
19 | and if all the necessary symbols are exported from the library. |
20 | |
21 | Most of the checks happen at the compilation or link phases. |
22 | **/ |
23 | #if __TBB_CPF_BUILD |
24 | // Add testing of preview features |
25 | #define TBB_PREVIEW_AGGREGATOR 1 |
26 | #define TBB_PREVIEW_CONCURRENT_LRU_CACHE 1 |
27 | #define TBB_PREVIEW_VARIADIC_PARALLEL_INVOKE 1 |
28 | #define TBB_PREVIEW_FLOW_GRAPH_NODES 1 |
29 | #define TBB_PREVIEW_BLOCKED_RANGE_ND 1 |
30 | #define TBB_PREVIEW_WAITING_FOR_WORKERS 1 |
31 | #define TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS 1 |
32 | #endif |
33 | |
34 | #if __TBB_TEST_SECONDARY |
35 | // Test _DEBUG macro custom definitions. |
36 | #if TBB_USE_DEBUG |
37 | #ifdef _DEBUG |
38 | #undef _DEBUG |
39 | #endif /* _DEBUG */ |
40 | // Check that empty value successfully enables the debug mode. |
41 | #define _DEBUG |
42 | static bool isDebugExpected = true; |
43 | #else |
44 | // Check that zero value does not enable the debug mode. |
45 | #define _DEBUG 0x0 |
46 | static bool isDebugExpected = false; |
47 | #endif /* TBB_USE_DEBUG */ |
48 | #define DO_TEST_DEBUG_MACRO 1 |
49 | #else |
50 | // Test default definitions of _DEBUG. |
51 | #if _DEBUG |
52 | static bool isDebugExpected = true; |
53 | #define DO_TEST_DEBUG_MACRO 1 |
54 | #elif _MSC_VER |
55 | // for MSVC, _DEBUG not defined indicates a release mode. |
56 | static bool isDebugExpected = false; |
57 | #define DO_TEST_DEBUG_MACRO 1 |
58 | #endif /* _DEBUG */ |
59 | #endif /* __TBB_TEST_SECONDARY */ |
60 | |
61 | #if DO_TEST_DEBUG_MACRO |
62 | // Reset TBB_USE_DEBUG defined in makefiles. |
63 | #undef TBB_USE_DEBUG |
64 | #endif /* DO_TEST_DEBUG_MACRO */ |
65 | #define __TBB_CONFIG_PREPROC_ONLY _MSC_VER // For MSVC, prevent including standard headers in tbb_config.h |
66 | #include "tbb/tbb_config.h" |
67 | |
68 | #if !TBB_USE_DEBUG && defined(_DEBUG) |
69 | // TBB_USE_DEBUG is 0 but _DEBUG is defined, it means that _DEBUG is 0 |
70 | // MSVC C++ headers consider any definition of _DEBUG, including 0, as debug mode |
71 | #undef _DEBUG |
72 | #endif /* !TBB_USE_DEBUG && defined(_DEBUG) */ |
73 | |
74 | #include "harness_defs.h" |
75 | #if _MSC_VER |
76 | #pragma warning (disable : 4503) // decorated name length exceeded, name was truncated |
77 | #endif |
78 | |
79 | #if !(__TBB_TEST_SECONDARY && __TBB_CPP11_STD_PLACEHOLDERS_LINKAGE_BROKEN) |
80 | |
81 | #include "tbb/tbb.h" |
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::parallel_do_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 | #if !__TBB_TEST_SECONDARY |
125 | |
126 | #define HARNESS_NO_PARSE_COMMAND_LINE 1 |
127 | #include "harness.h" |
128 | |
129 | // Test if all the necessary symbols are exported for the exceptions thrown by TBB. |
130 | // Missing exports result either in link error or in runtime assertion failure. |
131 | #include <stdexcept> |
132 | |
133 | template <typename E> |
134 | void TestExceptionClassExports ( const E& exc, tbb::internal::exception_id eid ) { |
135 | // The assertion here serves to shut up warnings about "eid not used". |
136 | ASSERT( eid<tbb::internal::eid_max, NULL ); |
137 | #if TBB_USE_EXCEPTIONS |
138 | for ( int i = 0; i < 2; ++i ) { |
139 | try { |
140 | if ( i == 0 ) |
141 | throw exc; |
142 | #if !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN |
143 | else |
144 | tbb::internal::throw_exception( eid ); |
145 | #endif |
146 | } |
147 | catch ( E& e ) { |
148 | ASSERT ( e.what(), "Missing what() string" ); |
149 | } |
150 | catch ( ... ) { |
151 | ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception. Likely RTTI related exports are missing" ); |
152 | } |
153 | } |
154 | #else /* TBB_USE_EXCEPTIONS */ |
155 | (void)exc; |
156 | #endif /* TBB_USE_EXCEPTIONS */ |
157 | } |
158 | |
159 | void TestExceptionClassesExports () { |
160 | TestExceptionClassExports( std::bad_alloc(), tbb::internal::eid_bad_alloc ); |
161 | TestExceptionClassExports( tbb::bad_last_alloc(), tbb::internal::eid_bad_last_alloc ); |
162 | TestExceptionClassExports( std::invalid_argument("test" ), tbb::internal::eid_nonpositive_step ); |
163 | TestExceptionClassExports( std::out_of_range("test" ), tbb::internal::eid_out_of_range ); |
164 | TestExceptionClassExports( std::range_error("test" ), tbb::internal::eid_segment_range_error ); |
165 | TestExceptionClassExports( std::range_error("test" ), tbb::internal::eid_index_range_error ); |
166 | TestExceptionClassExports( tbb::missing_wait(), tbb::internal::eid_missing_wait ); |
167 | TestExceptionClassExports( tbb::invalid_multiple_scheduling(), tbb::internal::eid_invalid_multiple_scheduling ); |
168 | TestExceptionClassExports( tbb::improper_lock(), tbb::internal::eid_improper_lock ); |
169 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_possible_deadlock ); |
170 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_operation_not_permitted ); |
171 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_condvar_wait_failed ); |
172 | TestExceptionClassExports( std::out_of_range("test" ), tbb::internal::eid_invalid_load_factor ); |
173 | TestExceptionClassExports( std::invalid_argument("test" ), tbb::internal::eid_invalid_swap ); |
174 | TestExceptionClassExports( std::length_error("test" ), tbb::internal::eid_reservation_length_error ); |
175 | TestExceptionClassExports( std::out_of_range("test" ), tbb::internal::eid_invalid_key ); |
176 | TestExceptionClassExports( tbb::user_abort(), tbb::internal::eid_user_abort ); |
177 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_bad_tagged_msg_cast ); |
178 | } |
179 | #endif /* !__TBB_TEST_SECONDARY */ |
180 | |
181 | #if __TBB_CPF_BUILD |
182 | // These names are only tested in "preview" configuration |
183 | // When a feature becomes fully supported, its names should be moved to the main test |
184 | struct Handler { |
185 | void operator()( tbb::aggregator_operation* ) {} |
186 | }; |
187 | static void TestPreviewNames() { |
188 | TestTypeDefinitionPresence( aggregator ); |
189 | TestTypeDefinitionPresence( aggregator_ext<Handler> ); |
190 | #if __TBB_CPP11_PRESENT |
191 | TestTypeDefinitionPresence2(blocked_rangeNd<int,4> ); |
192 | #endif |
193 | TestTypeDefinitionPresence2(concurrent_lru_cache<int, int> ); |
194 | #if !__TBB_TEST_SECONDARY |
195 | TestExceptionClassExports( std::runtime_error("test" ), tbb::internal::eid_blocking_thread_join_impossible ); |
196 | #endif |
197 | #if __TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT |
198 | TestTypeDefinitionPresence2(concurrent_map<int, int> ); |
199 | TestTypeDefinitionPresence2(concurrent_multimap<int, int> ); |
200 | TestTypeDefinitionPresence(concurrent_set<int> ); |
201 | TestTypeDefinitionPresence(concurrent_multiset<int> ); |
202 | #endif |
203 | } |
204 | #endif |
205 | |
206 | #if __TBB_TEST_SECONDARY |
207 | /* This mode is used to produce a secondary object file that is linked with |
208 | the main one in order to detect "multiple definition" linker error. |
209 | */ |
210 | #include "harness_assert.h" |
211 | bool Secondary() |
212 | #else |
213 | bool Secondary(); |
214 | int TestMain () |
215 | #endif |
216 | { |
217 | #if __TBB_CPP11_STD_PLACEHOLDERS_LINKAGE_BROKEN |
218 | REPORT("Known issue: \"multiple definition\" linker error detection test skipped.\n" ); |
219 | #endif |
220 | TestTypeDefinitionPresence( aligned_space<int> ); |
221 | TestTypeDefinitionPresence( atomic<int> ); |
222 | TestTypeDefinitionPresence( cache_aligned_allocator<int> ); |
223 | TestTypeDefinitionPresence( tbb_hash_compare<int> ); |
224 | TestTypeDefinitionPresence2(concurrent_hash_map<int, int> ); |
225 | TestTypeDefinitionPresence2(concurrent_unordered_map<int, int> ); |
226 | TestTypeDefinitionPresence2(concurrent_unordered_multimap<int, int> ); |
227 | TestTypeDefinitionPresence( concurrent_unordered_set<int> ); |
228 | TestTypeDefinitionPresence( concurrent_unordered_multiset<int> ); |
229 | TestTypeDefinitionPresence( concurrent_bounded_queue<int> ); |
230 | TestTypeDefinitionPresence( concurrent_queue<int> ); |
231 | TestTypeDefinitionPresence( strict_ppl::concurrent_queue<int> ); |
232 | TestTypeDefinitionPresence( concurrent_priority_queue<int> ); |
233 | TestTypeDefinitionPresence( concurrent_vector<int> ); |
234 | TestTypeDefinitionPresence( combinable<int> ); |
235 | TestTypeDefinitionPresence( enumerable_thread_specific<int> ); |
236 | /* Flow graph names */ |
237 | TestTypeDefinitionPresence( flow::graph ); |
238 | TestTypeDefinitionPresence( flow::continue_msg ); |
239 | TestTypeDefinitionPresence2(flow::tagged_msg<int, int> ); |
240 | TestFuncDefinitionPresence( flow::make_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void ); |
241 | TestFuncDefinitionPresence( flow::remove_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void ); |
242 | typedef tbb::flow::tuple<int, int> intpair; |
243 | TestTypeDefinitionPresence( flow::source_node<int> ); |
244 | TestTypeDefinitionPresence3(flow::function_node<int, int, tbb::flow::rejecting> ); |
245 | TestTypeDefinitionPresence3(flow::multifunction_node<int, intpair, tbb::flow::queueing> ); |
246 | TestTypeDefinitionPresence3(flow::async_node<int, int, tbb::flow::queueing_lightweight> ); |
247 | TestTypeDefinitionPresence2(flow::continue_node<int, tbb::flow::lightweight> ); |
248 | TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::reserving> ); |
249 | TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::key_matching<int> > ); |
250 | TestTypeDefinitionPresence( flow::split_node<intpair> ); |
251 | TestTypeDefinitionPresence( flow::overwrite_node<int> ); |
252 | TestTypeDefinitionPresence( flow::write_once_node<int> ); |
253 | TestTypeDefinitionPresence( flow::broadcast_node<int> ); |
254 | TestTypeDefinitionPresence( flow::buffer_node<int> ); |
255 | TestTypeDefinitionPresence( flow::queue_node<int> ); |
256 | TestTypeDefinitionPresence( flow::sequencer_node<int> ); |
257 | TestTypeDefinitionPresence( flow::priority_queue_node<int> ); |
258 | TestTypeDefinitionPresence( flow::limiter_node<int> ); |
259 | TestTypeDefinitionPresence2(flow::indexer_node<int, int> ); |
260 | #if __TBB_FLOW_GRAPH_CPP11_FEATURES |
261 | TestTypeDefinitionPresence2(flow::composite_node<tbb::flow::tuple<int>, tbb::flow::tuple<int> > ); |
262 | #endif |
263 | /* Mutex names */ |
264 | TestTypeDefinitionPresence( mutex ); |
265 | TestTypeDefinitionPresence( null_mutex ); |
266 | TestTypeDefinitionPresence( null_rw_mutex ); |
267 | TestTypeDefinitionPresence( queuing_mutex ); |
268 | TestTypeDefinitionPresence( queuing_rw_mutex ); |
269 | TestTypeDefinitionPresence( recursive_mutex ); |
270 | TestTypeDefinitionPresence( spin_mutex ); |
271 | TestTypeDefinitionPresence( spin_rw_mutex ); |
272 | TestTypeDefinitionPresence( speculative_spin_mutex ); |
273 | TestTypeDefinitionPresence( speculative_spin_rw_mutex ); |
274 | TestTypeDefinitionPresence( critical_section ); |
275 | TestTypeDefinitionPresence( reader_writer_lock ); |
276 | #if __TBB_TASK_GROUP_CONTEXT |
277 | TestTypeDefinitionPresence( tbb_exception ); |
278 | TestTypeDefinitionPresence( captured_exception ); |
279 | TestTypeDefinitionPresence( movable_exception<int> ); |
280 | #if !TBB_USE_CAPTURED_EXCEPTION |
281 | TestTypeDefinitionPresence( internal::tbb_exception_ptr ); |
282 | #endif /* !TBB_USE_CAPTURED_EXCEPTION */ |
283 | TestTypeDefinitionPresence( task_group_context ); |
284 | TestTypeDefinitionPresence( task_group ); |
285 | TestTypeDefinitionPresence( structured_task_group ); |
286 | TestTypeDefinitionPresence( task_handle<Body> ); |
287 | #endif /* __TBB_TASK_GROUP_CONTEXT */ |
288 | /* Algorithm related names */ |
289 | TestTypeDefinitionPresence( blocked_range<int> ); |
290 | TestTypeDefinitionPresence( blocked_range2d<int> ); |
291 | TestTypeDefinitionPresence( blocked_range3d<int> ); |
292 | TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, const Body&), void ); |
293 | TestFuncDefinitionPresence( parallel_do, (int*, int*, const Body1&), void ); |
294 | TestFuncDefinitionPresence( parallel_for_each, (int*, int*, const Body1&), void ); |
295 | TestFuncDefinitionPresence( parallel_for, (int, int, int, const Body1&), void ); |
296 | TestFuncDefinitionPresence( parallel_for, (const tbb::blocked_range<int>&, const Body2&, const tbb::simple_partitioner&), void ); |
297 | TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int ); |
298 | TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::affinity_partitioner&), void ); |
299 | TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int ); |
300 | TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::static_partitioner&), void ); |
301 | TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range2d<int>&, Body3&, const tbb::auto_partitioner&), void ); |
302 | TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range<int>&, const int&, const Body3a&, const Body1b&), int ); |
303 | typedef int intarray[10]; |
304 | TestFuncDefinitionPresence( parallel_sort, (int*, int*), void ); |
305 | TestFuncDefinitionPresence( parallel_sort, (intarray&, const Body1b&), void ); |
306 | TestTypeDefinitionPresence( pipeline ); |
307 | TestFuncDefinitionPresence( parallel_pipeline, (size_t, const tbb::filter_t<void,void>&), void ); |
308 | #if __TBB_TASK_GROUP_CONTEXT |
309 | TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, tbb::task_group_context&), void ); |
310 | TestFuncDefinitionPresence( parallel_do, (const intarray&, const Body1a&, tbb::task_group_context&), void ); |
311 | TestFuncDefinitionPresence( parallel_for_each, (const intarray&, const Body1&, tbb::task_group_context&), void ); |
312 | TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, const tbb::auto_partitioner&, tbb::task_group_context&), void ); |
313 | TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, tbb::task_group_context&), void ); |
314 | TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::auto_partitioner&, tbb::task_group_context&), void ); |
315 | TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void ); |
316 | TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::simple_partitioner&, tbb::task_group_context&), void ); |
317 | TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void ); |
318 | #endif /* __TBB_TASK_GROUP_CONTEXT */ |
319 | TestTypeDefinitionPresence( proportional_split ); |
320 | |
321 | TestTypeDefinitionPresence( task ); |
322 | TestTypeDefinitionPresence( empty_task ); |
323 | TestTypeDefinitionPresence( task_list ); |
324 | TestTypeDefinitionPresence( task_arena ); |
325 | TestFuncDefinitionPresence( this_task_arena::current_thread_index, (), int ); |
326 | TestFuncDefinitionPresence( this_task_arena::max_concurrency, (), int ); |
327 | #if !__TBB_GCC_OVERLOADED_TEMPLATE_FUNCTION_ADDRESS_BROKEN |
328 | TestFuncDefinitionPresence( this_task_arena::isolate, (const Body&), void ); |
329 | #endif |
330 | TestTypeDefinitionPresence( task_scheduler_init ); |
331 | TestTypeDefinitionPresence( task_scheduler_observer ); |
332 | TestTypeDefinitionPresence( tbb_thread ); |
333 | TestFuncDefinitionPresence( tbb_thread::hardware_concurrency, (), unsigned ); |
334 | TestFuncDefinitionPresence( this_tbb_thread::yield, (), void ); |
335 | TestTypeDefinitionPresence( tbb_allocator<int> ); |
336 | TestTypeDefinitionPresence( zero_allocator<int> ); |
337 | TestTypeDefinitionPresence( tick_count ); |
338 | TestTypeDefinitionPresence( global_control ); |
339 | #if __TBB_CPP11_PRESENT |
340 | TestTypeDefinitionPresence( counting_iterator<int> ); |
341 | TestTypeDefinitionPresence2(zip_iterator<int*,int*> ); |
342 | #endif |
343 | |
344 | #if __TBB_CPF_BUILD |
345 | TestPreviewNames(); |
346 | #endif |
347 | #ifdef DO_TEST_DEBUG_MACRO |
348 | #if TBB_USE_DEBUG |
349 | ASSERT( isDebugExpected, "Debug mode is observed while release mode is expected." ); |
350 | #else |
351 | ASSERT( !isDebugExpected, "Release mode is observed while debug mode is expected." ); |
352 | #endif /* TBB_USE_DEBUG */ |
353 | #endif /* DO_TEST_DEBUG_MACRO */ |
354 | #if __TBB_TEST_SECONDARY |
355 | return true; |
356 | #else |
357 | TestExceptionClassesExports(); |
358 | Secondary(); |
359 | return Harness::Done; |
360 | #endif /* __TBB_TEST_SECONDARY */ |
361 | } |
362 | #endif //!(__TBB_TEST_SECONDARY && __TBB_CPP11_STD_PLACEHOLDERS_LINKING_BROKEN) |
363 | |