1 // Copyright (c) 2014-2017 Hartmut Kaiser
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <hpx/hpx_init.hpp>
7 #include <hpx/hpx.hpp>
8 #include <hpx/include/parallel_mismatch.hpp>
9 #include <hpx/util/lightweight_test.hpp>
10
11 #include <cstddef>
12 #include <iostream>
13 #include <iterator>
14 #include <numeric>
15 #include <random>
16 #include <string>
17 #include <utility>
18 #include <vector>
19
20 #include "test_utils.hpp"
21
22 ///////////////////////////////////////////////////////////////////////////////
23 int seed = std::random_device{}();
24 std::mt19937 gen(seed);
25 std::uniform_int_distribution<> dis(0,10006);
26
27 template <typename ExPolicy, typename IteratorTag>
test_mismatch_binary1(ExPolicy policy,IteratorTag)28 void test_mismatch_binary1(ExPolicy policy, IteratorTag)
29 {
30 static_assert(
31 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
32 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
33
34 typedef std::vector<std::size_t>::iterator base_iterator;
35 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
36
37 typedef std::pair<base_iterator, base_iterator> base_return_type;
38 typedef std::pair<iterator, base_iterator> return_type;
39
40 std::vector<std::size_t> c1(10007);
41 std::vector<std::size_t> c2(c1.size());
42
43 std::size_t first_value = gen(); //-V101
44 std::iota(std::begin(c1), std::end(c1), first_value);
45 std::iota(std::begin(c2), std::end(c2), first_value);
46
47 iterator begin1 = iterator(std::begin(c1));
48 iterator end1 = iterator(std::end(c1));
49
50 {
51 return_type result = hpx::parallel::mismatch(policy,
52 begin1, end1, std::begin(c2), std::end(c2));
53
54 // verify values
55 HPX_TEST_EQ(std::size_t(std::distance(begin1, result.first)), c1.size());
56 HPX_TEST_EQ(std::size_t(std::distance(std::begin(c2), result.second)),
57 c2.size());
58 }
59
60 {
61 std::size_t changed_idx = dis(gen); //-V104
62 ++c1[changed_idx];
63
64 return_type result = hpx::parallel::mismatch(policy,
65 begin1, end1, std::begin(c2), std::end(c2));
66
67 // verify values
68 HPX_TEST_EQ(std::size_t(std::distance(begin1, result.first)), changed_idx);
69 HPX_TEST_EQ(std::size_t(std::distance(std::begin(c2), result.second)),
70 changed_idx);
71 }
72 }
73
74 template <typename ExPolicy, typename IteratorTag>
test_mismatch_binary1_async(ExPolicy p,IteratorTag)75 void test_mismatch_binary1_async(ExPolicy p, IteratorTag)
76 {
77 typedef std::vector<std::size_t>::iterator base_iterator;
78 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
79
80 typedef std::pair<base_iterator, base_iterator> base_return_type;
81 typedef std::pair<iterator, base_iterator> return_type;
82
83 std::vector<std::size_t> c1(10007);
84 std::vector<std::size_t> c2(c1.size());
85
86 std::size_t first_value = gen(); //-V101
87 std::iota(std::begin(c1), std::end(c1), first_value);
88 std::iota(std::begin(c2), std::end(c2), first_value);
89
90 iterator begin1 = iterator(std::begin(c1));
91 iterator end1 = iterator(std::end(c1));
92
93 {
94 hpx::future<return_type> f =
95 hpx::parallel::mismatch(p,
96 begin1, end1, std::begin(c2), std::end(c2));
97 f.wait();
98
99 // verify values
100 return_type result = f.get();
101 HPX_TEST_EQ(std::size_t(std::distance(begin1, result.first)),
102 c1.size());
103 HPX_TEST_EQ(std::size_t(std::distance(std::begin(c2),
104 result.second)), c2.size());
105 }
106
107 {
108 std::size_t changed_idx = dis(gen); //-V104
109 ++c1[changed_idx];
110
111 hpx::future<return_type> f =
112 hpx::parallel::mismatch(p,
113 begin1, end1, std::begin(c2), std::end(c2));
114 f.wait();
115
116 // verify values
117 return_type result = f.get();
118 HPX_TEST_EQ(std::size_t(std::distance(begin1, result.first)),
119 changed_idx);
120 HPX_TEST_EQ(std::size_t(std::distance(std::begin(c2),
121 result.second)), changed_idx);
122 }
123 }
124
125 template <typename IteratorTag>
test_mismatch_binary1()126 void test_mismatch_binary1()
127 {
128 using namespace hpx::parallel;
129
130 test_mismatch_binary1(execution::seq, IteratorTag());
131 test_mismatch_binary1(execution::par, IteratorTag());
132 test_mismatch_binary1(execution::par_unseq, IteratorTag());
133
134 test_mismatch_binary1_async(execution::seq(execution::task), IteratorTag());
135 test_mismatch_binary1_async(execution::par(execution::task), IteratorTag());
136 }
137
mismatch_binary_test1()138 void mismatch_binary_test1()
139 {
140 test_mismatch_binary1<std::random_access_iterator_tag>();
141 test_mismatch_binary1<std::forward_iterator_tag>();
142 #if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
143 test_mismatch_binary1<std::input_iterator_tag>();
144 #endif
145 }
146
147 ///////////////////////////////////////////////////////////////////////////////
148 template <typename ExPolicy, typename IteratorTag>
test_mismatch_binary2(ExPolicy policy,IteratorTag)149 void test_mismatch_binary2(ExPolicy policy, IteratorTag)
150 {
151 static_assert(
152 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
153 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
154
155 typedef std::vector<std::size_t>::iterator base_iterator;
156 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
157
158 typedef std::pair<base_iterator, base_iterator> base_return_type;
159 typedef std::pair<iterator, base_iterator> return_type;
160
161 std::vector<std::size_t> c1(10007);
162 std::vector<std::size_t> c2(c1.size());
163
164 std::size_t first_value = gen(); //-V101
165 std::iota(std::begin(c1), std::end(c1), first_value);
166 std::iota(std::begin(c2), std::end(c2), first_value);
167
168 iterator begin1 = iterator(std::begin(c1));
169 iterator end1 = iterator(std::end(c1));
170
171 {
172 return_type result = hpx::parallel::mismatch(policy,
173 begin1, end1, std::begin(c2), std::end(c2),
174 std::equal_to<std::size_t>());
175
176 // verify values
177 HPX_TEST_EQ(std::size_t(std::distance(begin1, result.first)),
178 c1.size());
179 HPX_TEST_EQ(std::size_t(std::distance(std::begin(c2),
180 result.second)), c2.size());
181 }
182
183 {
184 std::size_t changed_idx = dis(gen); //-V104
185 ++c1[changed_idx];
186
187 return_type result = hpx::parallel::mismatch(policy,
188 begin1, end1, std::begin(c2), std::end(c2),
189 std::equal_to<std::size_t>());
190
191 // verify values
192 HPX_TEST_EQ(std::size_t(std::distance(begin1, result.first)), changed_idx);
193 HPX_TEST_EQ(std::size_t(std::distance(std::begin(c2), result.second)),
194 changed_idx);
195 }
196 }
197
198 template <typename ExPolicy, typename IteratorTag>
test_mismatch_binary2_async(ExPolicy p,IteratorTag)199 void test_mismatch_binary2_async(ExPolicy p, IteratorTag)
200 {
201 typedef std::vector<std::size_t>::iterator base_iterator;
202 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
203
204 typedef std::pair<base_iterator, base_iterator> base_return_type;
205 typedef std::pair<iterator, base_iterator> return_type;
206
207 std::vector<std::size_t> c1(10007);
208 std::vector<std::size_t> c2(c1.size());
209
210 std::size_t first_value = gen(); //-V101
211 std::iota(std::begin(c1), std::end(c1), first_value);
212 std::iota(std::begin(c2), std::end(c2), first_value);
213
214 iterator begin1 = iterator(std::begin(c1));
215 iterator end1 = iterator(std::end(c1));
216
217 {
218 hpx::future<return_type> f =
219 hpx::parallel::mismatch(p,
220 begin1, end1, std::begin(c2), std::end(c2),
221 std::equal_to<std::size_t>());
222 f.wait();
223
224 // verify values
225 return_type result = f.get();
226 HPX_TEST_EQ(std::size_t(std::distance(begin1, result.first)), c1.size());
227 HPX_TEST_EQ(std::size_t(std::distance(std::begin(c2),
228 result.second)), c2.size());
229 }
230
231 {
232 std::size_t changed_idx = dis(gen); //-V104
233 ++c1[changed_idx];
234
235 hpx::future<return_type> f =
236 hpx::parallel::mismatch(p,
237 begin1, end1, std::begin(c2), std::end(c2),
238 std::equal_to<std::size_t>());
239 f.wait();
240
241 // verify values
242 return_type result = f.get();
243 HPX_TEST_EQ(std::size_t(std::distance(begin1, result.first)), changed_idx);
244 HPX_TEST_EQ(std::size_t(std::distance(std::begin(c2),
245 result.second)), changed_idx);
246 }
247 }
248
249 template <typename IteratorTag>
test_mismatch_binary2()250 void test_mismatch_binary2()
251 {
252 using namespace hpx::parallel;
253
254 test_mismatch_binary2(execution::seq, IteratorTag());
255 test_mismatch_binary2(execution::par, IteratorTag());
256 test_mismatch_binary2(execution::par_unseq, IteratorTag());
257
258 test_mismatch_binary2_async(execution::seq(execution::task), IteratorTag());
259 test_mismatch_binary2_async(execution::par(execution::task), IteratorTag());
260 }
261
mismatch_binary_test2()262 void mismatch_binary_test2()
263 {
264 test_mismatch_binary2<std::random_access_iterator_tag>();
265 test_mismatch_binary2<std::forward_iterator_tag>();
266 #if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
267 test_mismatch_binary2<std::input_iterator_tag>();
268 #endif
269 }
270
271 ///////////////////////////////////////////////////////////////////////////////
272 template <typename ExPolicy, typename IteratorTag>
test_mismatch_binary_exception(ExPolicy policy,IteratorTag)273 void test_mismatch_binary_exception(ExPolicy policy, IteratorTag)
274 {
275 static_assert(
276 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
277 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
278
279 typedef std::vector<std::size_t>::iterator base_iterator;
280 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
281
282 typedef std::pair<base_iterator, base_iterator> base_return_type;
283 typedef std::pair<iterator, base_iterator> return_type;
284
285 std::vector<std::size_t> c1(10007);
286 std::vector<std::size_t> c2(c1.size());
287
288 std::size_t first_value = gen(); //-V101
289 std::iota(std::begin(c1), std::end(c1), first_value);
290 std::iota(std::begin(c2), std::end(c2), first_value);
291
292 bool caught_exception = false;
293 try {
294 hpx::parallel::mismatch(policy,
295 iterator(std::begin(c1)), iterator(std::end(c1)),
296 std::begin(c2), std::end(c2),
297 [](std::size_t v1, std::size_t v2) {
298 return throw std::runtime_error("test"), true;
299 });
300
301 HPX_TEST(false);
302 }
303 catch(hpx::exception_list const& e) {
304 caught_exception = true;
305 test::test_num_exceptions<ExPolicy, IteratorTag>::call(policy, e);
306 }
307 catch(...) {
308 HPX_TEST(false);
309 }
310
311 HPX_TEST(caught_exception);
312 }
313
314 template <typename ExPolicy, typename IteratorTag>
test_mismatch_binary_exception_async(ExPolicy p,IteratorTag)315 void test_mismatch_binary_exception_async(ExPolicy p, IteratorTag)
316 {
317 typedef std::vector<std::size_t>::iterator base_iterator;
318 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
319
320 typedef std::pair<base_iterator, base_iterator> base_return_type;
321 typedef std::pair<iterator, base_iterator> return_type;
322
323 std::vector<std::size_t> c1(10007);
324 std::vector<std::size_t> c2(c1.size());
325
326 std::size_t first_value = gen(); //-V101
327 std::iota(std::begin(c1), std::end(c1), first_value);
328 std::iota(std::begin(c2), std::end(c2), first_value);
329
330 bool caught_exception = false;
331 bool returned_from_algorithm = false;
332 try {
333 hpx::future<return_type> f =
334 hpx::parallel::mismatch(p,
335 iterator(std::begin(c1)), iterator(std::end(c1)),
336 std::begin(c2), std::end(c2),
337 [](std::size_t v1, std::size_t v2) {
338 return throw std::runtime_error("test"), true;
339 });
340 returned_from_algorithm = true;
341 f.get();
342
343 HPX_TEST(false);
344 }
345 catch(hpx::exception_list const& e) {
346 caught_exception = true;
347 test::test_num_exceptions<ExPolicy, IteratorTag>::call(p, e);
348 }
349 catch(...) {
350 HPX_TEST(false);
351 }
352
353 HPX_TEST(caught_exception);
354 HPX_TEST(returned_from_algorithm);
355 }
356
357 template <typename IteratorTag>
test_mismatch_binary_exception()358 void test_mismatch_binary_exception()
359 {
360 using namespace hpx::parallel;
361
362 // If the execution policy object is of type vector_execution_policy,
363 // std::terminate shall be called. therefore we do not test exceptions
364 // with a vector execution policy
365 test_mismatch_binary_exception(execution::seq, IteratorTag());
366 test_mismatch_binary_exception(execution::par, IteratorTag());
367
368 test_mismatch_binary_exception_async(execution::seq(execution::task),
369 IteratorTag());
370 test_mismatch_binary_exception_async(execution::par(execution::task),
371 IteratorTag());
372 }
373
mismatch_binary_exception_test()374 void mismatch_binary_exception_test()
375 {
376 test_mismatch_binary_exception<std::random_access_iterator_tag>();
377 test_mismatch_binary_exception<std::forward_iterator_tag>();
378 #if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
379 test_mismatch_binary_exception<std::input_iterator_tag>();
380 #endif
381 }
382
383 /////////////////////////////////////////////////////////////////////////////
384 template <typename ExPolicy, typename IteratorTag>
test_mismatch_binary_bad_alloc(ExPolicy policy,IteratorTag)385 void test_mismatch_binary_bad_alloc(ExPolicy policy, IteratorTag)
386 {
387 static_assert(
388 hpx::parallel::execution::is_execution_policy<ExPolicy>::value,
389 "hpx::parallel::execution::is_execution_policy<ExPolicy>::value");
390
391 typedef std::vector<std::size_t>::iterator base_iterator;
392 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
393
394 typedef std::pair<base_iterator, base_iterator> base_return_type;
395 typedef std::pair<iterator, base_iterator> return_type;
396
397 std::vector<std::size_t> c1(10007);
398 std::vector<std::size_t> c2(c1.size());
399
400 std::size_t first_value = gen(); //-V101
401 std::iota(std::begin(c1), std::end(c1), first_value);
402 std::iota(std::begin(c2), std::end(c2), first_value);
403
404 bool caught_bad_alloc = false;
405 try {
406 hpx::parallel::mismatch(policy,
407 iterator(std::begin(c1)), iterator(std::end(c1)),
408 std::begin(c2), std::end(c2),
409 [](std::size_t v1, std::size_t v2) {
410 return throw std::bad_alloc(), true;
411 });
412
413 HPX_TEST(false);
414 }
415 catch(std::bad_alloc const&) {
416 caught_bad_alloc = true;
417 }
418 catch(...) {
419 HPX_TEST(false);
420 }
421
422 HPX_TEST(caught_bad_alloc);
423 }
424
425 template <typename ExPolicy, typename IteratorTag>
test_mismatch_binary_bad_alloc_async(ExPolicy p,IteratorTag)426 void test_mismatch_binary_bad_alloc_async(ExPolicy p, IteratorTag)
427 {
428 typedef std::vector<std::size_t>::iterator base_iterator;
429 typedef test::test_iterator<base_iterator, IteratorTag> iterator;
430
431 typedef std::pair<base_iterator, base_iterator> base_return_type;
432 typedef std::pair<iterator, base_iterator> return_type;
433
434 std::vector<std::size_t> c1(10007);
435 std::vector<std::size_t> c2(c1.size());
436
437 std::size_t first_value = gen(); //-V101
438 std::iota(std::begin(c1), std::end(c1), first_value);
439 std::iota(std::begin(c2), std::end(c2), first_value);
440
441 bool caught_bad_alloc = false;
442 bool returned_from_algorithm = false;
443 try {
444 hpx::future<return_type> f =
445 hpx::parallel::mismatch(p,
446 iterator(std::begin(c1)), iterator(std::end(c1)),
447 std::begin(c2), std::end(c2),
448 [](std::size_t v1, std::size_t v2) {
449 return throw std::bad_alloc(), true;
450 });
451 returned_from_algorithm = true;
452 f.get();
453
454 HPX_TEST(false);
455 }
456 catch(std::bad_alloc const&) {
457 caught_bad_alloc = true;
458 }
459 catch(...) {
460 HPX_TEST(false);
461 }
462
463 HPX_TEST(caught_bad_alloc);
464 HPX_TEST(returned_from_algorithm);
465 }
466
467 template <typename IteratorTag>
test_mismatch_binary_bad_alloc()468 void test_mismatch_binary_bad_alloc()
469 {
470 using namespace hpx::parallel;
471
472 // If the execution policy object is of type vector_execution_policy,
473 // std::terminate shall be called. therefore we do not test exceptions
474 // with a vector execution policy
475 test_mismatch_binary_bad_alloc(execution::seq, IteratorTag());
476 test_mismatch_binary_bad_alloc(execution::par, IteratorTag());
477
478 test_mismatch_binary_bad_alloc_async(execution::seq(execution::task),
479 IteratorTag());
480 test_mismatch_binary_bad_alloc_async(execution::par(execution::task),
481 IteratorTag());
482 }
483
mismatch_binary_bad_alloc_test()484 void mismatch_binary_bad_alloc_test()
485 {
486 test_mismatch_binary_bad_alloc<std::random_access_iterator_tag>();
487 test_mismatch_binary_bad_alloc<std::forward_iterator_tag>();
488 #if defined(HPX_HAVE_ALGORITHM_INPUT_ITERATOR_SUPPORT)
489 test_mismatch_binary_bad_alloc<std::input_iterator_tag>();
490 #endif
491 }
492
493 ///////////////////////////////////////////////////////////////////////////////
hpx_main(boost::program_options::variables_map & vm)494 int hpx_main(boost::program_options::variables_map& vm)
495 {
496 unsigned int seed = (unsigned int)std::time(nullptr);
497 if (vm.count("seed"))
498 seed = vm["seed"].as<unsigned int>();
499
500 std::cout << "using seed: " << seed << std::endl;
501 gen.seed(seed);
502
503 mismatch_binary_test1();
504 mismatch_binary_test2();
505 mismatch_binary_exception_test();
506 mismatch_binary_bad_alloc_test();
507 return hpx::finalize();
508 }
509
main(int argc,char * argv[])510 int main(int argc, char* argv[])
511 {
512 // add command line option which controls the random number generator seed
513 using namespace boost::program_options;
514 options_description desc_commandline(
515 "Usage: " HPX_APPLICATION_STRING " [options]");
516
517 desc_commandline.add_options()
518 ("seed,s", value<unsigned int>(),
519 "the random number generator seed to use for this run")
520 ;
521
522 // By default this test should run on all available cores
523 std::vector<std::string> const cfg = {
524 "hpx.os_threads=all"
525 };
526
527 // Initialize and run HPX
528 HPX_TEST_EQ_MSG(hpx::init(desc_commandline, argc, argv, cfg), 0,
529 "HPX main exited with non-zero status");
530
531 return hpx::util::report_errors();
532 }
533
534
535