1 /* Copyright 2017-2021 PaGMO development team
2
3 This file is part of the PaGMO library.
4
5 The PaGMO library is free software; you can redistribute it and/or modify
6 it under the terms of either:
7
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 or
13
14 * the GNU General Public License as published by the Free Software
15 Foundation; either version 3 of the License, or (at your option) any
16 later version.
17
18 or both in parallel, as here.
19
20 The PaGMO library is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
24
25 You should have received copies of the GNU General Public License and the
26 GNU Lesser General Public License along with the PaGMO library. If not,
27 see https://www.gnu.org/licenses/. */
28
29 #if defined(_MSC_VER)
30
31 // Disable warnings from MSVC.
32 #pragma warning(disable : 4822)
33
34 #endif
35
36 #define BOOST_TEST_MODULE r_policy_test
37 #define BOOST_TEST_DYN_LINK
38 #include <boost/test/unit_test.hpp>
39
40 #include <initializer_list>
41 #include <iostream>
42 #include <limits>
43 #include <memory>
44 #include <sstream>
45 #include <stdexcept>
46 #include <string>
47 #include <type_traits>
48 #include <typeindex>
49 #include <typeinfo>
50 #include <utility>
51
52 #include <boost/algorithm/string/predicate.hpp>
53 #include <boost/lexical_cast.hpp>
54
55 #include <pagmo/detail/type_name.hpp>
56 #include <pagmo/r_policies/fair_replace.hpp>
57 #include <pagmo/r_policy.hpp>
58 #include <pagmo/s11n.hpp>
59 #include <pagmo/types.hpp>
60
61 using namespace pagmo;
62
BOOST_AUTO_TEST_CASE(type_traits_tests)63 BOOST_AUTO_TEST_CASE(type_traits_tests)
64 {
65 BOOST_CHECK(!is_udrp<void>::value);
66 BOOST_CHECK(!is_udrp<int>::value);
67 BOOST_CHECK(!is_udrp<double>::value);
68
69 struct udrp00 {
70 individuals_group_t replace(const individuals_group_t &, const vector_double::size_type &,
71 const vector_double::size_type &, const vector_double::size_type &,
72 const vector_double::size_type &, const vector_double::size_type &,
73 const vector_double &, const individuals_group_t &) const;
74 };
75
76 BOOST_CHECK(is_udrp<udrp00>::value);
77 BOOST_CHECK(!is_udrp<const udrp00>::value);
78 BOOST_CHECK(!is_udrp<const udrp00 &>::value);
79 BOOST_CHECK(!is_udrp<udrp00 &>::value);
80
81 struct no_udrp00 {
82 void replace(const individuals_group_t &, const vector_double::size_type &, const vector_double::size_type &,
83 const vector_double::size_type &, const vector_double::size_type &,
84 const vector_double::size_type &, const vector_double &, const individuals_group_t &) const;
85 };
86
87 BOOST_CHECK(!is_udrp<no_udrp00>::value);
88
89 struct no_udrp01 {
90 individuals_group_t replace(const individuals_group_t &, const vector_double::size_type &,
91 const vector_double::size_type &, const vector_double::size_type &,
92 const vector_double::size_type &, const vector_double::size_type &,
93 const vector_double &, const individuals_group_t &);
94 };
95
96 BOOST_CHECK(!is_udrp<no_udrp01>::value);
97
98 struct no_udrp02 {
99 no_udrp02() = delete;
100 individuals_group_t replace(const individuals_group_t &, const vector_double::size_type &,
101 const vector_double::size_type &, const vector_double::size_type &,
102 const vector_double::size_type &, const vector_double::size_type &,
103 const vector_double &, const individuals_group_t &) const;
104 };
105
106 BOOST_CHECK(!is_udrp<no_udrp02>::value);
107 }
108
109 struct udrp1 {
replaceudrp1110 individuals_group_t replace(const individuals_group_t &inds, const vector_double::size_type &,
111 const vector_double::size_type &, const vector_double::size_type &,
112 const vector_double::size_type &, const vector_double::size_type &,
113 const vector_double &, const individuals_group_t &) const
114 {
115 return inds;
116 }
117 std::string foo = "hello world";
118 };
119
120 struct udrp2 {
121 udrp2() = default;
udrp2udrp2122 udrp2(const udrp2 &other) : foo{new std::string{*other.foo}} {}
123 udrp2(udrp2 &&) = default;
replaceudrp2124 individuals_group_t replace(const individuals_group_t &inds, const vector_double::size_type &,
125 const vector_double::size_type &, const vector_double::size_type &,
126 const vector_double::size_type &, const vector_double::size_type &,
127 const vector_double &, const individuals_group_t &) const
128 {
129 return inds;
130 }
get_nameudrp2131 std::string get_name() const
132 {
133 return "frobniz";
134 }
135 std::unique_ptr<std::string> foo = std::unique_ptr<std::string>{new std::string{"hello world"}};
136 };
137
BOOST_AUTO_TEST_CASE(basic_tests)138 BOOST_AUTO_TEST_CASE(basic_tests)
139 {
140 r_policy r;
141
142 BOOST_CHECK(r.is<fair_replace>());
143 BOOST_CHECK(!r.is<udrp1>());
144
145 BOOST_CHECK(r.extract<fair_replace>() != nullptr);
146 BOOST_CHECK(r.extract<udrp1>() == nullptr);
147
148 BOOST_CHECK(static_cast<const r_policy &>(r).extract<fair_replace>() != nullptr);
149 BOOST_CHECK(static_cast<const r_policy &>(r).extract<udrp1>() == nullptr);
150
151 BOOST_CHECK(r.get_name() == "Fair replace");
152 BOOST_CHECK(!r.get_extra_info().empty());
153
154 BOOST_CHECK(r_policy(udrp1{}).get_extra_info().empty());
155 BOOST_CHECK(r_policy(udrp1{}).get_name() == detail::type_name<udrp1>());
156
157 // Constructors, assignments.
158 // Generic constructor with copy.
159 udrp1 r1;
160 r_policy r_pol1{r1};
161 BOOST_CHECK(r1.foo == "hello world");
162 BOOST_CHECK(r_pol1.extract<udrp1>()->foo == "hello world");
163 // Generic constructor with move.
164 udrp2 r2;
165 r_policy r_pol2{std::move(r2)};
166 BOOST_CHECK(r2.foo.get() == nullptr);
167 BOOST_CHECK(r_pol2.extract<udrp2>()->foo.get() != nullptr);
168 BOOST_CHECK(*r_pol2.extract<udrp2>()->foo == "hello world");
169 // Copy constructor.
170 udrp2 r3;
171 r_policy r_pol3{r3}, r_pol4{r_pol3};
172 BOOST_CHECK(*r_pol4.extract<udrp2>()->foo == "hello world");
173 BOOST_CHECK(r_pol4.extract<udrp2>()->foo.get() != r_pol3.extract<udrp2>()->foo.get());
174 BOOST_CHECK(r_pol4.get_name() == "frobniz");
175 // Move constructor.
176 r_policy r_pol5{std::move(r_pol4)};
177 BOOST_CHECK(*r_pol5.extract<udrp2>()->foo == "hello world");
178 BOOST_CHECK(r_pol5.get_name() == "frobniz");
179 // Revive r_pol4 via copy assignment.
180 r_pol4 = r_pol5;
181 BOOST_CHECK(*r_pol4.extract<udrp2>()->foo == "hello world");
182 BOOST_CHECK(r_pol4.get_name() == "frobniz");
183 // Revive r_pol4 via move assignment.
184 r_policy r_pol6{std::move(r_pol4)};
185 r_pol4 = std::move(r_pol5);
186 BOOST_CHECK(*r_pol4.extract<udrp2>()->foo == "hello world");
187 BOOST_CHECK(r_pol4.get_name() == "frobniz");
188 // Self move-assignment.
189 r_pol4 = std::move(*&r_pol4);
190 BOOST_CHECK(*r_pol4.extract<udrp2>()->foo == "hello world");
191 BOOST_CHECK(r_pol4.get_name() == "frobniz");
192
193 // Minimal iostream test.
194 {
195 std::ostringstream oss;
196 oss << r;
197 BOOST_CHECK(!oss.str().empty());
198 }
199
200 // Minimal serialization test.
201 {
202 std::string before;
203 std::stringstream ss;
204 {
205 before = boost::lexical_cast<std::string>(r);
206 boost::archive::binary_oarchive oarchive(ss);
207 oarchive << r;
208 }
209 r = r_policy{udrp1{}};
210 BOOST_CHECK(r.is<udrp1>());
211 BOOST_CHECK(before != boost::lexical_cast<std::string>(r));
212 {
213 boost::archive::binary_iarchive iarchive(ss);
214 iarchive >> r;
215 }
216 BOOST_CHECK(before == boost::lexical_cast<std::string>(r));
217 BOOST_CHECK(r.is<fair_replace>());
218 }
219
220 std::cout << r_policy{} << '\n';
221 }
222
BOOST_AUTO_TEST_CASE(optional_tests)223 BOOST_AUTO_TEST_CASE(optional_tests)
224 {
225 // get_name().
226 struct udrp_00 {
227 individuals_group_t replace(const individuals_group_t &inds, const vector_double::size_type &,
228 const vector_double::size_type &, const vector_double::size_type &,
229 const vector_double::size_type &, const vector_double::size_type &,
230 const vector_double &, const individuals_group_t &) const
231 {
232 return inds;
233 }
234 std::string get_name() const
235 {
236 return "frobniz";
237 }
238 };
239 BOOST_CHECK_EQUAL(r_policy{udrp_00{}}.get_name(), "frobniz");
240 struct udrp_01 {
241 individuals_group_t replace(const individuals_group_t &inds, const vector_double::size_type &,
242 const vector_double::size_type &, const vector_double::size_type &,
243 const vector_double::size_type &, const vector_double::size_type &,
244 const vector_double &, const individuals_group_t &) const
245 {
246 return inds;
247 }
248 // Missing const.
249 std::string get_name()
250 {
251 return "frobniz";
252 }
253 };
254 BOOST_CHECK(r_policy{udrp_01{}}.get_name() != "frobniz");
255
256 // get_extra_info().
257 struct udrp_02 {
258 individuals_group_t replace(const individuals_group_t &inds, const vector_double::size_type &,
259 const vector_double::size_type &, const vector_double::size_type &,
260 const vector_double::size_type &, const vector_double::size_type &,
261 const vector_double &, const individuals_group_t &) const
262 {
263 return inds;
264 }
265 std::string get_extra_info() const
266 {
267 return "frobniz";
268 }
269 };
270 BOOST_CHECK_EQUAL(r_policy{udrp_02{}}.get_extra_info(), "frobniz");
271 struct udrp_03 {
272 individuals_group_t replace(const individuals_group_t &inds, const vector_double::size_type &,
273 const vector_double::size_type &, const vector_double::size_type &,
274 const vector_double::size_type &, const vector_double::size_type &,
275 const vector_double &, const individuals_group_t &) const
276 {
277 return inds;
278 }
279 // Missing const.
280 std::string get_extra_info()
281 {
282 return "frobniz";
283 }
284 };
285 BOOST_CHECK(r_policy{udrp_03{}}.get_extra_info().empty());
286 }
287
BOOST_AUTO_TEST_CASE(stream_operator)288 BOOST_AUTO_TEST_CASE(stream_operator)
289 {
290 struct udrp_00 {
291 individuals_group_t replace(const individuals_group_t &inds, const vector_double::size_type &,
292 const vector_double::size_type &, const vector_double::size_type &,
293 const vector_double::size_type &, const vector_double::size_type &,
294 const vector_double &, const individuals_group_t &) const
295 {
296 return inds;
297 }
298 };
299 {
300 std::ostringstream oss;
301 oss << r_policy{udrp_00{}};
302 BOOST_CHECK(!oss.str().empty());
303 }
304 struct udrp_01 {
305 individuals_group_t replace(const individuals_group_t &inds, const vector_double::size_type &,
306 const vector_double::size_type &, const vector_double::size_type &,
307 const vector_double::size_type &, const vector_double::size_type &,
308 const vector_double &, const individuals_group_t &) const
309 {
310 return inds;
311 }
312 std::string get_extra_info() const
313 {
314 return "bartoppo";
315 }
316 };
317 {
318 std::ostringstream oss;
319 oss << r_policy{udrp_01{}};
320 const auto st = oss.str();
321 BOOST_CHECK(boost::contains(st, "bartoppo"));
322 BOOST_CHECK(boost::contains(st, "Extra info:"));
323 }
324 }
325
BOOST_AUTO_TEST_CASE(replace)326 BOOST_AUTO_TEST_CASE(replace)
327 {
328 r_policy r0;
329
330 BOOST_CHECK_EXCEPTION(r0.replace(individuals_group_t{{0}, {}, {}}, 0, 0, 0, 0, 0, {}, individuals_group_t{}),
331 std::invalid_argument, [](const std::invalid_argument &ia) {
332 return boost::contains(
333 ia.what(),
334 "an invalid group of individuals was passed to a replacement policy of type 'Fair "
335 "replace': the sets of individuals IDs, decision vectors and fitness vectors "
336 "must all have the same sizes, but instead their sizes are 1, 0 and 0");
337 });
338
339 BOOST_CHECK_EXCEPTION(r0.replace(individuals_group_t{{0}, {{1.}}, {{1.}}}, 0, 0, 0, 0, 0, {},
340 individuals_group_t{{0}, {{1.}, {1.}}, {{1.}}}),
341 std::invalid_argument, [](const std::invalid_argument &ia) {
342 return boost::contains(
343 ia.what(),
344 "an invalid group of migrants was passed to a replacement policy of type 'Fair "
345 "replace': the sets of migrants IDs, decision vectors and fitness vectors "
346 "must all have the same sizes, but instead their sizes are 1, 2 and 1");
347 });
348
349 BOOST_CHECK_EXCEPTION(
350 r0.replace(individuals_group_t{{0}, {{1.}}, {{1.}}}, 0, 0, 0, 0, 0, {},
351 individuals_group_t{{0}, {{1.}}, {{1.}}}),
352 std::invalid_argument, [](const std::invalid_argument &ia) {
353 return boost::contains(
354 ia.what(), "a problem dimension of zero was passed to a replacement policy of type 'Fair replace'");
355 });
356
357 BOOST_CHECK_EXCEPTION(r0.replace(individuals_group_t{{0}, {{1.}}, {{1.}}}, 1, 2, 0, 0, 0, {},
358 individuals_group_t{{0}, {{1.}}, {{1.}}}),
359 std::invalid_argument, [](const std::invalid_argument &ia) {
360 return boost::contains(
361 ia.what(), "the integer dimension (2) passed to a replacement policy of type "
362 "'Fair replace' is larger than the supplied problem dimension (1)");
363 });
364
365 BOOST_CHECK_EXCEPTION(
366 r0.replace(individuals_group_t{{0}, {{1.}}, {{1.}}}, 1, 0, 0, 0, 0, {},
367 individuals_group_t{{0}, {{1.}}, {{1.}}}),
368 std::invalid_argument, [](const std::invalid_argument &ia) {
369 return boost::contains(
370 ia.what(),
371 "an invalid number of objectives (0) was passed to a replacement policy of type 'Fair replace'");
372 });
373
374 BOOST_CHECK_EXCEPTION(
375 r0.replace(individuals_group_t{{0}, {{1.}}, {{1.}}}, 1, 0, std::numeric_limits<vector_double::size_type>::max(),
376 0, 0, {}, individuals_group_t{{0}, {{1.}}, {{1.}}}),
377 std::invalid_argument, [](const std::invalid_argument &ia) {
378 return boost::contains(ia.what(),
379 "the number of objectives ("
380 + std::to_string(std::numeric_limits<vector_double::size_type>::max())
381 + ") passed to a replacement policy of type 'Fair replace' is too large");
382 });
383
384 BOOST_CHECK_EXCEPTION(r0.replace(individuals_group_t{{0}, {{1.}}, {{1.}}}, 1, 0, 1,
385 std::numeric_limits<vector_double::size_type>::max(), 0, {},
386 individuals_group_t{{0}, {{1.}}, {{1.}}}),
387 std::invalid_argument, [](const std::invalid_argument &ia) {
388 return boost::contains(
389 ia.what(),
390 "the number of equality constraints ("
391 + std::to_string(std::numeric_limits<vector_double::size_type>::max())
392 + ") passed to a replacement policy of type 'Fair replace' is too large");
393 });
394
395 BOOST_CHECK_EXCEPTION(
396 r0.replace(individuals_group_t{{0}, {{1.}}, {{1.}}}, 1, 0, 1, 0,
397 std::numeric_limits<vector_double::size_type>::max(), {}, individuals_group_t{{0}, {{1.}}, {{1.}}}),
398 std::invalid_argument, [](const std::invalid_argument &ia) {
399 return boost::contains(ia.what(),
400 "the number of inequality constraints ("
401 + std::to_string(std::numeric_limits<vector_double::size_type>::max())
402 + ") passed to a replacement policy of type 'Fair replace' is too large");
403 });
404
405 BOOST_CHECK_EXCEPTION(r0.replace(individuals_group_t{{0}, {{1.}}, {{1.}}}, 1, 0, 1, 1, 1, {},
406 individuals_group_t{{0}, {{1.}}, {{1.}}}),
407 std::invalid_argument, [](const std::invalid_argument &ia) {
408 return boost::contains(
409 ia.what(),
410 "the vector of tolerances passed to a replacement policy of type 'Fair replace' has "
411 "a dimension (0) which is inconsistent with the total number of constraints (2)");
412 });
413
414 BOOST_CHECK_EXCEPTION(r0.replace(individuals_group_t{{0, 1}, {{1.}, {}}, {{1.}, {1.}}}, 1, 0, 1, 0, 0, {},
415 individuals_group_t{{0}, {{1.}}, {{1.}}}),
416 std::invalid_argument, [](const std::invalid_argument &ia) {
417 return boost::contains(
418 ia.what(), "not all the individuals passed to a replacement policy of type 'Fair "
419 "replace' have the expected dimension (1)");
420 });
421
422 BOOST_CHECK_EXCEPTION(r0.replace(individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {}}}, 1, 0, 1, 0, 0, {},
423 individuals_group_t{{0}, {{1.}}, {{1.}}}),
424 std::invalid_argument, [](const std::invalid_argument &ia) {
425 return boost::contains(
426 ia.what(), "not all the individuals passed to a replacement policy of type 'Fair "
427 "replace' have the expected fitness dimension (1)");
428 });
429
430 BOOST_CHECK_EXCEPTION(r0.replace(individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {1.}}}, 1, 0, 1, 0, 0, {},
431 individuals_group_t{{0, 1}, {{1.}, {}}, {{1.}, {1.}}}),
432 std::invalid_argument, [](const std::invalid_argument &ia) {
433 return boost::contains(ia.what(),
434 "not all the migrants passed to a replacement policy of type "
435 "'Fair replace' have the expected dimension (1)");
436 });
437
438 BOOST_CHECK_EXCEPTION(r0.replace(individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {1.}}}, 1, 0, 1, 0, 0, {},
439 individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {}}}),
440 std::invalid_argument, [](const std::invalid_argument &ia) {
441 return boost::contains(ia.what(),
442 "not all the migrants passed to a replacement policy of type "
443 "'Fair replace' have the expected fitness dimension (1)");
444 });
445
446 struct fail_0 {
447 individuals_group_t replace(const individuals_group_t &, const vector_double::size_type &,
448 const vector_double::size_type &, const vector_double::size_type &,
449 const vector_double::size_type &, const vector_double::size_type &,
450 const vector_double &, const individuals_group_t &) const
451 {
452 return individuals_group_t{{0}, {}, {}};
453 }
454 std::string get_name() const
455 {
456 return "fail_0";
457 }
458 };
459
460 BOOST_CHECK_EXCEPTION(r_policy{fail_0{}}.replace(individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {1.}}}, 1, 0, 1,
461 0, 0, {}, individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {1.}}}),
462 std::invalid_argument, [](const std::invalid_argument &ia) {
463 return boost::contains(
464 ia.what(),
465 "an invalid group of individuals was returned by a replacement policy of type "
466 "'fail_0': the sets of individuals IDs, decision vectors and fitness vectors "
467 "must all have the same sizes, but instead their sizes are 1, 0 and 0");
468 });
469
470 struct fail_1 {
471 individuals_group_t replace(const individuals_group_t &, const vector_double::size_type &,
472 const vector_double::size_type &, const vector_double::size_type &,
473 const vector_double::size_type &, const vector_double::size_type &,
474 const vector_double &, const individuals_group_t &) const
475 {
476 return individuals_group_t{{0, 1}, {{1}, {}}, {{1}, {1}}};
477 }
478 std::string get_name() const
479 {
480 return "fail_1";
481 }
482 };
483
484 BOOST_CHECK_EXCEPTION(r_policy{fail_1{}}.replace(individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {1.}}}, 1, 0, 1,
485 0, 0, {}, individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {1.}}}),
486 std::invalid_argument, [](const std::invalid_argument &ia) {
487 return boost::contains(ia.what(),
488 "not all the individuals returned by a replacement "
489 "policy of type 'fail_1' have the expected dimension (1)");
490 });
491
492 struct fail_2 {
493 individuals_group_t replace(const individuals_group_t &, const vector_double::size_type &,
494 const vector_double::size_type &, const vector_double::size_type &,
495 const vector_double::size_type &, const vector_double::size_type &,
496 const vector_double &, const individuals_group_t &) const
497 {
498 return individuals_group_t{{0, 1}, {{1}, {1}}, {{1}, {}}};
499 }
500 std::string get_name() const
501 {
502 return "fail_2";
503 }
504 };
505
506 BOOST_CHECK_EXCEPTION(r_policy{fail_2{}}.replace(individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {1.}}}, 1, 0, 1,
507 0, 0, {}, individuals_group_t{{0, 1}, {{1.}, {1.}}, {{1.}, {1.}}}),
508 std::invalid_argument, [](const std::invalid_argument &ia) {
509 return boost::contains(ia.what(),
510 "not all the individuals returned by a replacement policy of type "
511 "'fail_2' have the expected fitness dimension (1)");
512 });
513 }
514
515 struct udrp_a {
replaceudrp_a516 individuals_group_t replace(const individuals_group_t &inds, const vector_double::size_type &,
517 const vector_double::size_type &, const vector_double::size_type &,
518 const vector_double::size_type &, const vector_double::size_type &,
519 const vector_double &, const individuals_group_t &) const
520 {
521 return inds;
522 }
get_nameudrp_a523 std::string get_name() const
524 {
525 return "abba";
526 }
get_extra_infoudrp_a527 std::string get_extra_info() const
528 {
529 return "dabba";
530 }
531 template <typename Archive>
serializeudrp_a532 void serialize(Archive &ar, unsigned)
533 {
534 ar &state;
535 }
536 int state = 42;
537 };
538
539 PAGMO_S11N_R_POLICY_EXPORT(udrp_a)
540
541 // Serialization tests.
BOOST_AUTO_TEST_CASE(s11n)542 BOOST_AUTO_TEST_CASE(s11n)
543 {
544 r_policy r_pol0{udrp_a{}};
545 BOOST_CHECK(r_pol0.extract<udrp_a>()->state == 42);
546 r_pol0.extract<udrp_a>()->state = -42;
547 // Store the string representation.
548 std::stringstream ss;
549 auto before = boost::lexical_cast<std::string>(r_pol0);
550 // Now serialize, deserialize and compare the result.
551 {
552 boost::archive::binary_oarchive oarchive(ss);
553 oarchive << r_pol0;
554 }
555 // Change the content of p before deserializing.
556 r_pol0 = r_policy{};
557 {
558 boost::archive::binary_iarchive iarchive(ss);
559 iarchive >> r_pol0;
560 }
561 auto after = boost::lexical_cast<std::string>(r_pol0);
562 BOOST_CHECK_EQUAL(before, after);
563 BOOST_CHECK(r_pol0.is<udrp_a>());
564 BOOST_CHECK(r_pol0.extract<udrp_a>()->state = -42);
565 }
566
BOOST_AUTO_TEST_CASE(is_valid)567 BOOST_AUTO_TEST_CASE(is_valid)
568 {
569 r_policy p0;
570 BOOST_CHECK(p0.is_valid());
571 r_policy p1(std::move(p0));
572 BOOST_CHECK(!p0.is_valid());
573 p0 = r_policy{udrp_a{}};
574 BOOST_CHECK(p0.is_valid());
575 p1 = std::move(p0);
576 BOOST_CHECK(!p0.is_valid());
577 p0 = r_policy{udrp_a{}};
578 BOOST_CHECK(p0.is_valid());
579 }
580
BOOST_AUTO_TEST_CASE(generic_assignment)581 BOOST_AUTO_TEST_CASE(generic_assignment)
582 {
583 r_policy p0;
584 BOOST_CHECK(p0.is<fair_replace>());
585 BOOST_CHECK(&(p0 = udrp_a{}) == &p0);
586 BOOST_CHECK(p0.is_valid());
587 BOOST_CHECK(p0.is<udrp_a>());
588 p0 = udrp1{};
589 BOOST_CHECK(p0.is<udrp1>());
590 BOOST_CHECK((!std::is_assignable<r_policy, void>::value));
591 BOOST_CHECK((!std::is_assignable<r_policy, int &>::value));
592 BOOST_CHECK((!std::is_assignable<r_policy, const int &>::value));
593 BOOST_CHECK((!std::is_assignable<r_policy, int &&>::value));
594 }
595
BOOST_AUTO_TEST_CASE(type_index)596 BOOST_AUTO_TEST_CASE(type_index)
597 {
598 r_policy p0;
599 BOOST_CHECK(p0.get_type_index() == std::type_index(typeid(fair_replace)));
600 p0 = r_policy{udrp1{}};
601 BOOST_CHECK(p0.get_type_index() == std::type_index(typeid(udrp1)));
602 }
603
BOOST_AUTO_TEST_CASE(get_ptr)604 BOOST_AUTO_TEST_CASE(get_ptr)
605 {
606 r_policy p0;
607 BOOST_CHECK(p0.get_ptr() == p0.extract<fair_replace>());
608 BOOST_CHECK(static_cast<const r_policy &>(p0).get_ptr()
609 == static_cast<const r_policy &>(p0).extract<fair_replace>());
610 p0 = r_policy{udrp1{}};
611 BOOST_CHECK(p0.get_ptr() == p0.extract<udrp1>());
612 BOOST_CHECK(static_cast<const r_policy &>(p0).get_ptr() == static_cast<const r_policy &>(p0).extract<udrp1>());
613 }
614