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
83static 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
90struct Body {
91 void operator() () const {}
92};
93struct Body1 {
94 void operator() ( int ) const {}
95};
96struct Body1a { // feeder body for parallel_do
97 void operator() ( int, tbb::parallel_do_feeder<int>& ) const {}
98};
99struct Body1b { // binary operator for reduction and comparison
100 int operator() ( const int, const int ) const { return 0; }
101};
102struct Body2 {
103 Body2 () {}
104 Body2 ( const Body2&, tbb::split ) {}
105 void operator() ( const tbb::blocked_range<int>& ) const {}
106 void join( const Body2& ) {}
107};
108struct Body2a { // for lambda-friendly parallel_reduce
109 int operator() ( const tbb::blocked_range<int>&, const int ) const { return 0; }
110};
111struct 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};
119struct Body3a { // for lambda-friednly parallel_scan
120 int operator() ( const tbb::blocked_range<int>&, const int, bool ) const { return 0; }
121};
122struct 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
133template <typename E>
134void 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
159void 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
184struct Handler {
185 void operator()( tbb::aggregator_operation* ) {}
186};
187static 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"
211bool Secondary()
212#else
213bool Secondary();
214int 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