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 | #if __TBB_TEST_USE_WSUGGEST_OVERRIDE |
18 | // __TBB_override may not be used in the tested header file |
19 | #pragma GCC diagnostic ignored "-Wsuggest-override" |
20 | #undef __TBB_TEST_USE_WSUGGEST_OVERRIDE |
21 | #endif |
22 | |
23 | #include "harness_defs.h" // for suppress_unused_warning |
24 | |
25 | #if TBB_USE_EXCEPTIONS |
26 | #include "harness_assert.h" |
27 | #include "../../examples/common/utility/utility.h" |
28 | #include <sstream> |
29 | |
30 | namespace implementation_unit_tests { |
31 | namespace argument_dest_test_suite{ |
32 | void test_type_impl_parse_and_store_simple_parse(){ |
33 | int a=0; |
34 | utility::internal::type_impl<int> a_("" ,"" ,a); |
35 | a_.parse_and_store("9" ); |
36 | ASSERT(a==9,"" ); |
37 | } |
38 | void test_default_value_of_is_matched(){ |
39 | //Testing for result of is_matched() for arguments not yet tried to be parsed. |
40 | //I.e. values were set up by argument::constructor. |
41 | using utility::internal::argument; |
42 | int i; |
43 | argument b("" ,"" ,i); |
44 | ASSERT(!b.is_matched(),"" ); |
45 | |
46 | argument c = b; |
47 | ASSERT(!c.is_matched(),"" ); |
48 | |
49 | argument d = b; |
50 | d = c; |
51 | ASSERT(!d.is_matched(),"" ); |
52 | } |
53 | } |
54 | //TODO: test cases for argument type management |
55 | namespace compile_only{ |
56 | //TODO: enhance these to actually do checks by a negative test, or (if possible) |
57 | //by a positive test that at compile time selects between two alternatives, |
58 | //depending on whether operators exist or not (yes, SFINAE :)) - |
59 | //as non_pod class does provide the operators, and test do not check that compiler |
60 | //will reject types which don't have those. |
61 | using utility::cli_argument_pack; |
62 | void arg_chain(){ |
63 | cli_argument_pack p; |
64 | int size=0; |
65 | p.arg(size,"size" ,"size" ); |
66 | } |
67 | namespace tc_helper{ |
68 | struct non_pod{ |
69 | std::string s; |
70 | friend std::ostream& operator<<(std::ostream& o, non_pod){ return o;} |
71 | friend std::istream& operator>>(std::istream& i, non_pod){ return i;} |
72 | }; |
73 | } |
74 | void non_pod_dest_type(){ |
75 | cli_argument_pack p; |
76 | tc_helper::non_pod np; |
77 | p.arg(np,"" ,"" ); |
78 | } |
79 | } |
80 | namespace cli_argument_pack_suite{ |
81 | void test_copy_assign(){ |
82 | using utility::cli_argument_pack; |
83 | int i=9; |
84 | std::stringstream expected_output; using std::endl; |
85 | expected_output |
86 | << " Program usage is:" << endl |
87 | << " the_binary_name [i=value]" |
88 | << endl << endl |
89 | << " where:" << endl |
90 | << " i - i desc (9)" << endl |
91 | ; |
92 | cli_argument_pack copy(cli_argument_pack().arg(i,"i" ,"i desc" )); |
93 | ASSERT(copy.usage_string("the_binary_name" ) == expected_output.str(),"usage string is not as expected" ); |
94 | cli_argument_pack assignee; assignee = copy; |
95 | ASSERT(assignee.usage_string("the_binary_name" ) == expected_output.str(),"Copying of cli_argument_pack breaks generation of usage string?" ); |
96 | } |
97 | } |
98 | } |
99 | |
100 | #include <utility> |
101 | namespace high_level_api_tests { |
102 | using utility::cli_argument_pack; |
103 | using utility::internal::array_length; |
104 | |
105 | static const char * wrong_exception = "wrong exception thrown" ; |
106 | static const char * wrong_exception_description = "caught exception has wrong description" ; |
107 | void test_parse_basic(){ |
108 | char const* argv[]={"some.exe" ,"1" ,"a" }; |
109 | cli_argument_pack p; |
110 | int i=0; char a=' '; |
111 | p.positional_arg(i,"int" ,"" ).positional_arg(a,"char" ,"" ); |
112 | p.parse(array_length(argv),argv); |
113 | ASSERT(i==1,"" ); |
114 | ASSERT(a=='a',"" ); |
115 | } |
116 | //helper function for test of named flag parsing |
117 | template<typename T, size_t N> |
118 | bool parse_silent_flag( T(& argv)[N]){ |
119 | cli_argument_pack p; |
120 | bool silent=false; |
121 | p.arg(silent,"silent" ,"is extra info needed" ); |
122 | p.parse(array_length(argv),argv); |
123 | return silent; |
124 | } |
125 | void test_named_flags_success(){ |
126 | char const* argv[]={"some.exe" ,"silent" }; |
127 | ASSERT(true == parse_silent_flag(argv),"" ); |
128 | } |
129 | |
130 | void test_named_flags_failure(){ |
131 | try { |
132 | char const* argv[]={"some.exe" ,"1" }; |
133 | parse_silent_flag(argv); |
134 | ASSERT(false,"exception was expected due to invalid argument, but not caught" ); |
135 | } |
136 | catch(std::invalid_argument& e){ |
137 | ASSERT(e.what()==std::string("unknown parameter starting at:'1'" ),wrong_exception_description); |
138 | } |
139 | catch(...){ASSERT(false,wrong_exception);} |
140 | } |
141 | |
142 | //helper function for test of named flag parsing |
143 | template<typename T, size_t N> |
144 | std::pair<bool,int> parse_silent_flag_and_int( T(& argv)[N]){ |
145 | cli_argument_pack p; |
146 | bool silent=false; |
147 | int i=125; |
148 | p |
149 | .arg(silent,"silent" ,"is extra info needed" ) |
150 | .positional_arg(i,"int" ,"" ); |
151 | p.parse(array_length(argv),argv); |
152 | return std::make_pair(silent,i); |
153 | } |
154 | |
155 | void test_named_flags_failure_and_other_arg(){ |
156 | char const* argv[]={"some.exe" ,"1" }; |
157 | ASSERT(std::make_pair(false,1) == parse_silent_flag_and_int(argv),"" ); |
158 | } |
159 | |
160 | void test_named_flags_and_other_arg(){ |
161 | char const* argv[]={"some.exe" ,"silent" ,"7" }; |
162 | ASSERT(std::make_pair(true,7) == parse_silent_flag_and_int(argv),"" ); |
163 | } |
164 | |
165 | void test_named_flags_and_other_arg_different_order(){ |
166 | char const* argv[]={"some.exe" ,"7" ,"silent" }; |
167 | ASSERT(std::make_pair(true,7) == parse_silent_flag_and_int(argv),"" ); |
168 | } |
169 | |
170 | void test_flags_only_others_default(){ |
171 | char const* argv[]={"some.exe" ,"silent" }; |
172 | ASSERT(std::make_pair(true,125) == parse_silent_flag_and_int(argv),"" ); |
173 | } |
174 | |
175 | namespace parameters_validation_test_suite{ |
176 | namespace test_validation_function_called_helpers{ |
177 | struct validator{ |
178 | static bool called; |
179 | static bool accept(const int & ){ |
180 | called = true; |
181 | return true; |
182 | } |
183 | }; |
184 | bool validator::called =false; |
185 | } |
186 | void test_validation_function_called(){ |
187 | using test_validation_function_called_helpers::validator; |
188 | |
189 | char const* argv[]={"some.exe" ,"7" }; |
190 | cli_argument_pack p; |
191 | int size =0; |
192 | p.positional_arg(size,"size" ,"" ,validator::accept); |
193 | p.parse(array_length(argv),argv); |
194 | ASSERT((validator::called),"validation function has not been called" ); |
195 | } |
196 | void test_validation_failed(){ |
197 | struct validator{ |
198 | static bool reject(const int &){ |
199 | return false; |
200 | } |
201 | }; |
202 | char const* argv[]={"some.exe" ,"7" }; |
203 | cli_argument_pack p; |
204 | int size =0; |
205 | p.positional_arg(size,"size" ,"" ,validator::reject); |
206 | try { |
207 | p.parse(array_length(argv),argv); |
208 | ASSERT((false),"An exception was expected due to failed argument validation, " |
209 | "but no exception thrown" ); |
210 | } |
211 | catch(std::invalid_argument& e){ |
212 | std::string error_msg("'7' is invalid value for argument 'size'" ); |
213 | ASSERT(e.what()==error_msg , wrong_exception_description); |
214 | } |
215 | catch(...){ASSERT((false),wrong_exception);} |
216 | } |
217 | } |
218 | namespace error_handling { |
219 | void test_wrong_input(){ |
220 | char const* argv[]={"some.exe" ,"silent" }; |
221 | cli_argument_pack p; |
222 | int size =0; |
223 | p.positional_arg(size,"size" ,"" ); |
224 | try{ |
225 | p.parse(array_length(argv),argv); |
226 | ASSERT(false,"An exception was expected due to wrong input, but no exception thrown" ); |
227 | } |
228 | catch(std::invalid_argument & e){ |
229 | std::string error_msg("'silent' is incorrect input for argument 'size' (error converting string 'silent')" ); |
230 | ASSERT(e.what()==error_msg, wrong_exception_description); |
231 | } |
232 | catch(...){ASSERT(false,wrong_exception);} |
233 | } |
234 | void test_duplicate_arg_names(){ |
235 | cli_argument_pack p; |
236 | int a=0; |
237 | p.arg(a,"a" ,"" ); |
238 | try{ |
239 | int dup_a=0; |
240 | p.arg(dup_a,"a" ,"" ); |
241 | ASSERT(false, "An exception was expected due adding duplicate parameter name, but not thrown" ); |
242 | } |
243 | catch(std::invalid_argument& e){ |
244 | ASSERT(e.what()==std::string("argument with name: 'a' already registered" ),wrong_exception_description); |
245 | } |
246 | catch(...){ASSERT(false,wrong_exception);} |
247 | } |
248 | void test_duplicate_positional_arg_names(){ |
249 | cli_argument_pack p; |
250 | int a=0; |
251 | p.positional_arg(a,"a" ,"" ); |
252 | try{ |
253 | int dup_a=0; |
254 | p.positional_arg(dup_a,"a" ,"" ); |
255 | ASSERT(false, "An exception was expected due adding duplicate parameter name, but not thrown" ); |
256 | } |
257 | catch(std::invalid_argument& e){ |
258 | ASSERT(e.what()==std::string("argument with name: 'a' already registered" ),wrong_exception_description); |
259 | } |
260 | catch(...){ASSERT(false,wrong_exception);} |
261 | } |
262 | } |
263 | namespace usage_string { |
264 | void test_one_arg(){ |
265 | cli_argument_pack p; |
266 | int size =9; |
267 | p.arg(size,"size" ,"size of problem domain" ); |
268 | std::string const binary_name = "binary.exe" ; |
269 | std::stringstream expected_output; |
270 | using std::endl; |
271 | expected_output << " Program usage is:" << endl |
272 | << " " << binary_name << " [size=value]" |
273 | << endl << endl |
274 | << " where:" << endl |
275 | << " size - size of problem domain (9)" << endl |
276 | ; |
277 | std::string usage= p.usage_string(binary_name); |
278 | ASSERT(usage==expected_output.str(),"" ); |
279 | } |
280 | void test_named_and_postional_args(){ |
281 | cli_argument_pack p; |
282 | int size =9; |
283 | int length =8; |
284 | int stride = 7; |
285 | p |
286 | .arg(size,"size" ,"" ) |
287 | .positional_arg(length,"length" ,"" ) |
288 | .positional_arg(stride,"stride" ,"" ); |
289 | std::string const binary_name = "binary.exe" ; |
290 | std::stringstream expected_output; |
291 | using std::endl; |
292 | expected_output << " Program usage is:" << endl |
293 | << " " << binary_name << " [size=value] [length=value] [stride=value] [length [stride]]" |
294 | << endl << endl |
295 | << " where:" << endl |
296 | << " size - (9)" << endl |
297 | << " length - (8)" << endl |
298 | << " stride - (7)" << endl |
299 | ; |
300 | std::string usage= p.usage_string(binary_name); |
301 | ASSERT(usage==expected_output.str(),"" ); |
302 | } |
303 | void test_bool_flag(){ |
304 | bool flag=false; |
305 | cli_argument_pack p; |
306 | p.arg(flag,"flag" ,"" ); |
307 | std::string const binary_name = "binary.exe" ; |
308 | std::stringstream expected_output; |
309 | using std::endl; |
310 | expected_output << " Program usage is:" << endl |
311 | << " " << binary_name << " [flag]" |
312 | << endl << endl |
313 | << " where:" << endl |
314 | << " flag - (0)" << endl |
315 | ; |
316 | std::string usage= p.usage_string(binary_name); |
317 | ASSERT(usage==expected_output.str(),"" ); |
318 | |
319 | } |
320 | |
321 | } |
322 | namespace name_positional_syntax { |
323 | void test_basic(){ |
324 | cli_argument_pack p; |
325 | int size =0; |
326 | int time = 0; |
327 | p |
328 | .positional_arg(size,"size" ,"" ) |
329 | .positional_arg(time,"time" ,"" ); |
330 | char const* argv[]={"some.exe" ,"1" ,"2" }; |
331 | p.parse(array_length(argv),argv); |
332 | ASSERT(size==1,"" ); |
333 | ASSERT(time==2,"" ); |
334 | } |
335 | void test_positional_args_explicitly_named(){ |
336 | const char* no_or_wrong_exception_error_msg = "exception was expected but not thrown, or wrong exception caught" ; |
337 | //TODO: Similar functionality is used all over the test. Generalize this helper further, and use as wide within the test as possible? |
338 | struct failed_with_exception{ |
339 | static bool _(cli_argument_pack & p, std::size_t argc, char const* argv[]){ |
340 | try{ |
341 | p.parse(argc,argv); |
342 | return false; |
343 | } |
344 | catch(std::exception &){ |
345 | return true; |
346 | } |
347 | catch(...){ |
348 | return false; |
349 | } |
350 | } |
351 | }; |
352 | { |
353 | cli_argument_pack p; |
354 | int a,b,c,d; |
355 | p |
356 | .positional_arg(a,"a" ,"" ) |
357 | .positional_arg(b,"b" ,"" ) |
358 | .positional_arg(c,"c" ,"" ) |
359 | .positional_arg(d,"d" ,"" ); |
360 | char const* argv[]={"some.exe" ,"a=7" ,"0" ,"1" ,"2" ,"4" }; |
361 | ASSERT(failed_with_exception::_(p,array_length(argv),argv),no_or_wrong_exception_error_msg); |
362 | } |
363 | { |
364 | cli_argument_pack p; |
365 | int a,b,c,d; |
366 | p |
367 | .positional_arg(a,"a" ,"" ) |
368 | .positional_arg(b,"b" ,"" ) |
369 | .positional_arg(c,"c" ,"" ) |
370 | .positional_arg(d,"d" ,"" ); |
371 | char const* argv[]={"some.exe" ,"a=7" ,"0" ,"1" ,"2" }; |
372 | ASSERT(failed_with_exception::_(p,array_length(argv),argv),no_or_wrong_exception_error_msg); |
373 | } |
374 | { |
375 | cli_argument_pack p; |
376 | int a=-1,b=-1,c = -1,d=-1; |
377 | p |
378 | .positional_arg(a,"a" ,"" ) |
379 | .positional_arg(b,"b" ,"" ) |
380 | .positional_arg(c,"c" ,"" ) |
381 | .positional_arg(d,"d" ,"" ); |
382 | char const* argv[]={"some.exe" ,"0" ,"1" ,"d=7" ,}; |
383 | ASSERT(!failed_with_exception::_(p,array_length(argv),argv),"unexpected exception" ); |
384 | ASSERT(a==0,"" ); ASSERT(b==1,"" ); ASSERT(c==-1,"" );ASSERT(d==7,"" ); |
385 | } |
386 | } |
387 | } |
388 | namespace name_value_syntax { |
389 | void test_basic(){ |
390 | cli_argument_pack p; |
391 | int size =0; |
392 | p.arg(size,"size" ,"size of problem domain" ); |
393 | char const* argv[]={"some.exe" ,"size=7" }; |
394 | p.parse(array_length(argv),argv); |
395 | ASSERT(size==7,"" ); |
396 | } |
397 | |
398 | void test_relaxed_order(){ |
399 | cli_argument_pack p; |
400 | int size =0; |
401 | int time=0; |
402 | p |
403 | .arg(size,"size" ,"" ) |
404 | .arg(time,"time" ,"" ); |
405 | char const* argv[]={"some.exe" ,"time=1" ,"size=2" }; |
406 | p.parse(array_length(argv),argv); |
407 | ASSERT(size==2,"" ); |
408 | ASSERT(time==1,"" ); |
409 | } |
410 | |
411 | } |
412 | namespace number_of_argument_value{ |
413 | void test_only_single_values_allowed(){ |
414 | cli_argument_pack p; |
415 | int a=0; |
416 | p.arg(a,"a" ,"" ); |
417 | const char* argv[] = {"" ,"a=7" ,"a=8" }; |
418 | try { |
419 | p.parse(array_length(argv),argv); |
420 | ASSERT(false,"exception was expected due to duplicated values provided in input, but not thrown" ); |
421 | } |
422 | catch(std::invalid_argument& e){ |
423 | //TODO: use patterns (regexp ?) to generate /validate exception descriptions |
424 | ASSERT(e.what() == std::string("several values specified for: 'a' argument" ),wrong_exception_description); |
425 | } |
426 | catch(...){ASSERT(false,wrong_exception);} |
427 | } |
428 | } |
429 | namespace thread_range_tests{ |
430 | using utility::thread_number_range; |
431 | using utility::internal::thread_range_step; |
432 | using utility::internal::step_function_multiply; |
433 | using utility::internal::step_function_plus; |
434 | using utility::internal::step_function_power2_ladder; |
435 | |
436 | int auto_value(){ |
437 | return 100; |
438 | } |
439 | bool operator ==(thread_range_step const& left, utility::internal::thread_range_step const& right){ |
440 | return (left.step_function == right.step_function) |
441 | && (left.step_function_argument == right.step_function_argument) |
442 | ; |
443 | } |
444 | |
445 | bool operator ==(thread_number_range const& left, thread_number_range const& right){ |
446 | return (left.auto_number_of_threads==right.auto_number_of_threads) |
447 | && (left.first == right.first) |
448 | && (left.last == right.last) |
449 | && (left.step == right.step) |
450 | ; |
451 | } |
452 | |
453 | void constructor_default_values(){ |
454 | thread_number_range r(auto_value); |
455 | const int default_num_threads = auto_value(); |
456 | ASSERT((r.first==1)&&(r.last==default_num_threads),"" ); |
457 | } |
458 | void validation(){ |
459 | try{ |
460 | thread_number_range range(auto_value,12,6); |
461 | Harness::suppress_unused_warning(range); |
462 | ASSERT(false,"exception was expected due to invalid range specified, but not thrown" ); |
463 | } |
464 | catch(std::invalid_argument& e){ |
465 | ASSERT(e.what() == std::string("decreasing sequence not allowed" ), wrong_exception_description); |
466 | } |
467 | catch(...){ASSERT(false,wrong_exception);} |
468 | } |
469 | |
470 | thread_number_range thread_number_range_from_string(std::string const& string_to_parse){ |
471 | thread_number_range r(auto_value,0,0); |
472 | std::stringstream str(string_to_parse); str>>r; |
473 | return r; |
474 | } |
475 | static const char* thread_range_parse_failed = "error parsing thread range string" ; |
476 | void post_process_single_value(){ |
477 | ASSERT(thread_number_range_from_string("auto" ) == |
478 | thread_number_range(auto_value,auto_value(),auto_value()) |
479 | ,thread_range_parse_failed |
480 | ); |
481 | } |
482 | void post_process_pair_value(){ |
483 | ASSERT(thread_number_range_from_string("1:auto" ) == |
484 | thread_number_range(auto_value,1,auto_value()) |
485 | ,thread_range_parse_failed |
486 | ); |
487 | |
488 | ASSERT(thread_number_range_from_string("auto:auto" ) == |
489 | thread_number_range(auto_value,auto_value(),auto_value()) |
490 | ,thread_range_parse_failed |
491 | ); |
492 | } |
493 | |
494 | void post_process_troika_value_with_plus_step(){ |
495 | ASSERT(thread_number_range_from_string("1:auto:+2" ) == |
496 | thread_number_range(auto_value,1,auto_value(),thread_range_step(step_function_plus,2)) |
497 | ,thread_range_parse_failed |
498 | ); |
499 | } |
500 | |
501 | void post_process_troika_value_with_multiply_step(){ |
502 | ASSERT(thread_number_range_from_string("1:auto:*2.6" ) == |
503 | thread_number_range(auto_value,1,auto_value(),thread_range_step(step_function_multiply,2.6)) |
504 | ,thread_range_parse_failed |
505 | ); |
506 | } |
507 | |
508 | void post_process_troika_value_with_ladder_step(){ |
509 | try{ |
510 | thread_number_range range = thread_number_range_from_string("1:16:#3" ); |
511 | Harness::suppress_unused_warning(range); |
512 | ASSERT(false,"exception was expected due to invalid range specified, but not thrown" ); |
513 | } |
514 | catch(std::invalid_argument& e){ |
515 | ASSERT(e.what() == std::string("the argument of # should be a power of 2" ), wrong_exception_description); |
516 | } |
517 | catch(...){ASSERT(false,wrong_exception);} |
518 | |
519 | ASSERT(thread_number_range_from_string("1:32:#4" ) == |
520 | thread_number_range(auto_value,1,32,thread_range_step(step_function_power2_ladder,4)) |
521 | ,thread_range_parse_failed |
522 | ); |
523 | } |
524 | |
525 | void test_print_content(){ |
526 | std::stringstream str; |
527 | str<<thread_number_range(auto_value,1,8,thread_range_step(step_function_multiply,2)); |
528 | ASSERT(str.str() == "1:8:*2" ,"Unexpected string" ); |
529 | } |
530 | } |
531 | } |
532 | |
533 | void run_implementation_unit_tests(){ |
534 | using namespace implementation_unit_tests; |
535 | argument_dest_test_suite::test_type_impl_parse_and_store_simple_parse(); |
536 | argument_dest_test_suite::test_default_value_of_is_matched(); |
537 | |
538 | cli_argument_pack_suite::test_copy_assign(); |
539 | } |
540 | void run_high_level_api_tests(){ |
541 | using namespace high_level_api_tests; |
542 | |
543 | test_parse_basic(); |
544 | test_named_flags_success(); |
545 | test_named_flags_failure(); |
546 | test_named_flags_failure_and_other_arg(); |
547 | test_named_flags_and_other_arg(); |
548 | test_flags_only_others_default(); |
549 | test_named_flags_and_other_arg_different_order(); |
550 | |
551 | usage_string::test_one_arg(); |
552 | usage_string::test_named_and_postional_args(); |
553 | usage_string::test_bool_flag(); |
554 | |
555 | parameters_validation_test_suite::test_validation_function_called(); |
556 | parameters_validation_test_suite::test_validation_failed(); |
557 | |
558 | name_value_syntax::test_basic(); |
559 | name_value_syntax::test_relaxed_order(); |
560 | |
561 | number_of_argument_value::test_only_single_values_allowed(); |
562 | |
563 | name_positional_syntax::test_basic(); |
564 | name_positional_syntax::test_positional_args_explicitly_named(); |
565 | |
566 | error_handling::test_wrong_input(); |
567 | error_handling::test_duplicate_arg_names(); |
568 | error_handling::test_duplicate_positional_arg_names(); |
569 | |
570 | thread_range_tests::constructor_default_values(); |
571 | thread_range_tests::validation(); |
572 | thread_range_tests::post_process_single_value(); |
573 | thread_range_tests::post_process_pair_value(); |
574 | thread_range_tests::post_process_troika_value_with_plus_step(); |
575 | thread_range_tests::post_process_troika_value_with_multiply_step(); |
576 | thread_range_tests::post_process_troika_value_with_ladder_step(); |
577 | thread_range_tests::test_print_content(); |
578 | } |
579 | #endif // TBB_USE_EXCEPTIONS |
580 | |
581 | #include "harness.h" |
582 | int TestMain(){ |
583 | #if TBB_USE_EXCEPTIONS |
584 | Harness::suppress_unused_warning(utility::thread_number_range_desc); |
585 | try{ |
586 | run_implementation_unit_tests(); |
587 | run_high_level_api_tests(); |
588 | }catch(std::exception& e){ |
589 | //something went wrong , dump any possible details |
590 | std::stringstream str; str<< "run time error: " << e.what()<<std::endl; |
591 | ASSERT(false,str.str().c_str()); |
592 | } |
593 | return Harness::Done; |
594 | #else |
595 | REPORT("Known issue: the test cannot work with exceptions disabled\n" ); |
596 | return Harness::Done; |
597 | #endif |
598 | } |
599 | |