xref: /oneTBB/test/tbb/test_tbb_header.cpp (revision 51c0b2f7)
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