25 #ifndef LSST_AFW_TYPEHANDLING_TEST_H 26 #define LSST_AFW_TYPEHANDLING_TEST_H 28 #define BOOST_TEST_DYN_LINK 29 #pragma clang diagnostic push 30 #pragma clang diagnostic ignored "-Wunused-variable" 31 #include "boost/test/unit_test.hpp" 32 #pragma clang diagnostic pop 40 #include <boost/mpl/list.hpp> 49 namespace typehandling {
60 class SimpleStorable :
public Storable {
62 virtual ~SimpleStorable() =
default;
66 std::string toString()
const override {
return "Simplest possible representation"; }
68 bool equals(
Storable const&
other)
const noexcept
override {
return singleClassEquals(*
this, other); }
69 virtual bool operator==(SimpleStorable
const& other)
const {
return true; }
70 bool operator!=(SimpleStorable
const& other)
const {
return !(*
this ==
other); }
73 class ComplexStorable final :
public SimpleStorable {
75 constexpr ComplexStorable(
double storage) : SimpleStorable(), storage(storage) {}
77 ComplexStorable& operator=(
double newValue) {
83 return std::make_unique<ComplexStorable>(storage);
92 auto complexOther =
dynamic_cast<ComplexStorable const*
>(&
other);
94 return this->storage == complexOther->storage;
99 bool operator==(SimpleStorable
const& other)
const override {
return this->equals(other); }
105 template <
typename T>
115 auto const KEY0 = makeKey<bool>(0);
116 bool const VALUE0 =
true;
117 auto const KEY1 = makeKey<int>(1);
118 int const VALUE1 = 42;
119 auto const KEY2 = makeKey<double>(2);
120 int const VALUE2 = VALUE1;
121 auto const KEY3 = makeKey<std::string>(3);
122 std::string const VALUE3 =
"How many roads must a man walk down?";
123 auto const KEY4 = makeKey<std::shared_ptr<SimpleStorable>>(4);
124 auto const VALUE4 = SimpleStorable();
125 auto const KEY5 = makeKey<ComplexStorable>(5);
126 auto const VALUE5 = ComplexStorable(-100.0);
153 static GenericMapFactory
const factory;
156 BOOST_TEST(demoMap->at(KEY0) == VALUE0);
157 BOOST_TEST(demoMap->at(KEY1) == VALUE1);
158 BOOST_TEST(demoMap->at(KEY2) == VALUE2);
159 BOOST_TEST(demoMap->at(KEY3) == VALUE3);
160 BOOST_TEST(*(demoMap->at(KEY4)) == VALUE4);
161 BOOST_TEST(demoMap->at(KEY5) == VALUE5);
167 static GenericMapFactory
const factory;
170 BOOST_TEST(demoMap->at(KEY0) == VALUE0);
171 demoMap->at(KEY0) =
false;
172 BOOST_TEST(demoMap->at(KEY0) ==
false);
175 BOOST_TEST(demoMap->at(KEY1) == VALUE1);
177 BOOST_TEST(demoMap->at(KEY1) == VALUE1 + 1);
180 BOOST_TEST(demoMap->at(KEY2) == VALUE2);
181 demoMap->at(KEY2) = 0.0;
182 BOOST_TEST(demoMap->at(KEY2) == 0.0);
184 using Type2 = std::remove_const_t<decltype(VALUE2)>;
187 BOOST_TEST(demoMap->at(KEY3) == VALUE3);
188 demoMap->at(KEY3).append(
" Oops, wrong question."s);
189 BOOST_TEST(demoMap->at(KEY3) == VALUE3 +
" Oops, wrong question."s);
191 BOOST_TEST(*(demoMap->at(KEY4)) == VALUE4);
193 using Type4 = std::remove_const_t<decltype(VALUE4)>;
196 BOOST_TEST(demoMap->at(KEY5) == VALUE5);
197 BOOST_TEST(demoMap->at(makeKey<SimpleStorable>(KEY5.getId())) == VALUE5);
199 ComplexStorable newValue(5.0);
200 demoMap->at(KEY5) = newValue;
201 BOOST_TEST(demoMap->at(KEY5) == newValue);
205 static GenericMapFactory
const factory;
206 auto map1 = factory.makeGenericMap();
209 BOOST_CHECK(*map1 == *map1);
211 BOOST_CHECK(*map1 != *(factory.makeGenericMap()));
215 static GenericMapFactory
const factory;
221 auto bruteForcePrinter = [&map](
int key) {
224 return universalToString(map->at(KEY0));
226 return universalToString(map->at(KEY1));
228 return universalToString(map->at(KEY2));
230 return universalToString(map->at(KEY3));
232 return universalToString(map->at(KEY4));
234 return universalToString(map->at(KEY5));
240 for (
int key : mapKeys) {
250 void operator()(
int,
bool value) { results.
push_back(universalToString(value)); }
253 void operator()(
int,
float const& value) { results.
push_back(universalToString(value)); }
254 void operator()(
int,
double value) { results.
push_back(universalToString(value)); }
256 void operator()(
int,
Storable const& value) { results.
push_back(universalToString(value)); }
260 BOOST_REQUIRE(printer.results.size() == expected.
size());
261 for (
std::size_t i = 0; i < printer.results.size(); ++i) {
262 BOOST_TEST(printer.results[i] == expected[i], printer.results[i] <<
" != " << expected[i] <<
", key = " << mapKeys[i]);
267 BOOST_REQUIRE(strings.
size() == expected.
size());
269 BOOST_TEST(strings[i] == expected[i], strings[i] <<
" != " << expected[i] <<
", key = " << mapKeys[i]);
274 static GenericMapFactory
const factory;
282 void operator()(
int,
bool& value) { value = !value; }
283 void operator()(
int,
std::int32_t& value) { value *= 2; }
284 void operator()(
int,
std::int64_t& value) { value *= 2; }
285 void operator()(
int,
float& value) { value *= 2; }
286 void operator()(
int,
double& value) { value *= 2; }
287 void operator()(
int,
std::string& value) { value +=
"Appendix"; }
288 void operator()(
int,
Storable& value) {
289 auto complexStorable =
dynamic_cast<ComplexStorable*
>(&value);
290 if (complexStorable !=
nullptr) {
291 *complexStorable = 42;
299 BOOST_TEST(newKeys == originalKeys);
300 BOOST_TEST(map->at(KEY0) == !VALUE0);
301 BOOST_TEST(map->at(KEY1) == 2 * VALUE1);
302 BOOST_TEST(map->at(KEY2) == 2 * VALUE2);
303 BOOST_TEST(map->at(KEY3) == VALUE3 +
"Appendix");
304 BOOST_TEST(*(map->at(KEY4)) == VALUE4);
305 BOOST_TEST(map->at(KEY5) != VALUE5);
306 BOOST_TEST(map->at(KEY5) == ComplexStorable(42));
310 static GenericMapFactory
const factory;
318 int operator()(
int key,
bool& value) {
330 int operator()(
int key,
float& value) {
334 int operator()(
int key,
double& value) {
342 int operator()(
int key,
Storable& value) {
343 auto complexStorable =
dynamic_cast<ComplexStorable*
>(&value);
344 if (complexStorable !=
nullptr) {
345 *complexStorable = 42;
352 BOOST_TEST(editedKeys == originalKeys);
355 BOOST_TEST(newKeys == originalKeys);
356 BOOST_TEST(map->at(KEY0) == !VALUE0);
357 BOOST_TEST(map->at(KEY1) == 2 * VALUE1);
358 BOOST_TEST(map->at(KEY2) == 2 * VALUE2);
359 BOOST_TEST(map->at(KEY3) == VALUE3 +
"Appendix");
360 BOOST_TEST(*(map->at(KEY4)) == VALUE4);
361 BOOST_TEST(map->at(KEY5) != VALUE5);
362 BOOST_TEST(map->at(KEY5) == ComplexStorable(42));
368 static GenericMapFactory
const factory;
369 auto map1 = factory.makeMutableGenericMap();
370 auto map2 = factory.makeMutableGenericMap();
373 BOOST_CHECK(*map1 == *map2);
375 auto primitiveKey = makeKey<int>(
"primitive"s);
376 map1->insert(primitiveKey, 42);
377 BOOST_CHECK(*map1 != *map2);
378 map2->insert(primitiveKey, 42);
379 BOOST_CHECK(*map1 == *map2);
381 auto sharedKey = makeKey<std::shared_ptr<SimpleStorable>>(
"shared"s);
382 auto common = std::make_shared<SimpleStorable>(VALUE4);
383 map1->insert(sharedKey, common);
384 BOOST_CHECK(*map1 != *map2);
385 map2->insert(sharedKey, std::make_shared<SimpleStorable>(VALUE4));
386 BOOST_CHECK(*map1 != *map2);
387 map2->erase(sharedKey);
388 map2->insert(sharedKey, common);
389 BOOST_CHECK(*map1 == *map2);
391 auto storableKey = makeKey<ComplexStorable>(
"storable"s);
392 map1->insert(storableKey, VALUE5);
393 BOOST_CHECK(*map1 != *map2);
394 map2->insert(storableKey, VALUE5);
395 BOOST_CHECK(*map1 == *map2);
399 static GenericMapFactory
const factory;
402 BOOST_TEST(demoMap->size() == 6);
403 BOOST_TEST(!demoMap->empty());
409 static GenericMapFactory
const factory;
412 BOOST_TEST_REQUIRE(demoMap->size() == 0);
413 BOOST_TEST_REQUIRE(demoMap->empty());
415 demoMap->insert(makeKey<int>(
"Negative One"s), -1);
416 BOOST_TEST(demoMap->size() == 1);
417 BOOST_TEST(!demoMap->empty());
419 demoMap->erase(makeKey<int>(
"Negative One"s));
420 BOOST_TEST(demoMap->size() == 0);
421 BOOST_TEST(demoMap->empty());
427 static GenericMapFactory
const factory;
430 BOOST_TEST(demoMap->contains(KEY0.getId()));
431 BOOST_TEST(demoMap->contains(KEY1.getId()));
432 BOOST_TEST(demoMap->contains(KEY2.getId()));
433 BOOST_TEST(demoMap->contains(KEY3.getId()));
434 BOOST_TEST(demoMap->contains(KEY4.getId()));
435 BOOST_TEST(demoMap->contains(KEY5.getId()));
436 BOOST_TEST(!demoMap->contains(6));
440 static GenericMapFactory
const factory;
443 BOOST_TEST(demoMap->contains(KEY0));
444 BOOST_TEST(!demoMap->contains(makeKey<int>(KEY0.getId())));
446 BOOST_TEST(demoMap->contains(KEY1));
447 BOOST_TEST(!demoMap->contains(makeKey<bool>(KEY1.getId())));
449 BOOST_TEST(demoMap->contains(KEY2));
451 BOOST_TEST(!demoMap->contains(
makeKey<decltype(VALUE2)>(KEY2.getId())));
453 BOOST_TEST(demoMap->contains(KEY3));
455 BOOST_TEST(demoMap->contains(KEY4));
457 BOOST_TEST(!demoMap->contains(
makeKey<decltype(VALUE4)>(KEY4.getId())));
459 BOOST_TEST(demoMap->contains(KEY5));
460 BOOST_TEST(demoMap->contains(makeKey<SimpleStorable>(KEY5.getId())));
461 BOOST_TEST(demoMap->contains(makeKey<Storable>(KEY5.getId())));
465 static GenericMapFactory
const factory;
467 auto orderedKeys = demoMap->keys();
471 BOOST_TEST(
keys ==
std::set<int>({KEY0.getId(), KEY1.getId(), KEY2.getId(), KEY3.getId(), KEY4.getId(),
476 static GenericMapFactory
const factory;
479 BOOST_TEST_REQUIRE(demoMap->empty());
481 BOOST_TEST(demoMap->empty());
487 static GenericMapFactory
const factory;
490 demoMap->insert(makeKey<int>(
"prime"s), 3);
491 demoMap->insert(makeKey<std::string>(
"foo"s),
"bar"s);
493 BOOST_TEST_REQUIRE(!demoMap->empty());
495 BOOST_TEST(demoMap->empty());
501 static GenericMapFactory
const factory;
504 BOOST_TEST_REQUIRE(demoMap->empty());
507 BOOST_TEST(demoMap->insert(makeKey<int>(
"cube"s), x) ==
true);
508 BOOST_TEST(demoMap->insert(makeKey<int>(
"cube"s), 0) ==
false);
510 BOOST_TEST(!demoMap->empty());
511 BOOST_TEST(demoMap->size() == 1);
512 BOOST_TEST(demoMap->contains(
"cube"s));
513 BOOST_TEST(demoMap->contains(makeKey<int>(
"cube"s)));
514 BOOST_TEST(!demoMap->contains(makeKey<double>(
"cube"s)));
515 BOOST_TEST(demoMap->at(makeKey<int>(
"cube"s)) ==
x);
518 BOOST_TEST(demoMap->at(makeKey<int>(
"cube"s)) !=
x);
520 demoMap->at(makeKey<int>(
"cube"s)) = 0;
521 BOOST_TEST(demoMap->at(makeKey<int>(
"cube"s)) == 0);
527 static GenericMapFactory
const factory;
530 BOOST_TEST_REQUIRE(demoMap->empty());
532 auto insertResult = demoMap->insert(
"cube"s, 27);
533 BOOST_TEST(insertResult.second ==
true);
534 BOOST_TEST(demoMap->insert(
"cube"s, 0).second ==
false);
536 BOOST_TEST(!demoMap->empty());
537 BOOST_TEST(demoMap->size() == 1);
538 BOOST_TEST(demoMap->contains(
"cube"s));
539 BOOST_TEST(demoMap->contains(insertResult.first));
540 BOOST_TEST(demoMap->contains(makeKey<int>(
"cube"s)));
541 BOOST_TEST(!demoMap->contains(makeKey<double>(
"cube"s)));
542 BOOST_TEST(demoMap->at(insertResult.first) == 27);
543 BOOST_TEST(demoMap->at(makeKey<int>(
"cube"s)) == 27);
545 demoMap->at(insertResult.first) = 0;
546 BOOST_TEST(demoMap->at(insertResult.first) == 0);
552 static GenericMapFactory
const factory;
555 BOOST_TEST_REQUIRE(demoMap->empty());
558 "I have a most elegant and wonderful proof, but this string is too small to contain it."s);
559 BOOST_TEST(demoMap->insert(makeKey<std::string>(
"Ultimate answer"s), answer) ==
true);
560 BOOST_TEST(demoMap->insert(makeKey<std::string>(
"OK"s),
"Ook!"s) ==
true);
561 BOOST_TEST(demoMap->insert(makeKey<std::string>(
"Ultimate answer"s),
"Something philosophical"s) ==
564 BOOST_TEST(!demoMap->empty());
565 BOOST_TEST(demoMap->size() == 2);
566 BOOST_TEST(demoMap->contains(
"OK"s));
567 BOOST_TEST(demoMap->contains(makeKey<std::string>(
"Ultimate answer"s)));
568 BOOST_TEST(demoMap->at(makeKey<std::string>(
"Ultimate answer"s)) == answer);
569 BOOST_TEST(demoMap->at(makeKey<std::string>(
"OK"s)) ==
"Ook!"s);
571 answer =
"I don't know"s;
572 BOOST_TEST(demoMap->at(makeKey<std::string>(
"Ultimate answer"s)) != answer);
578 static GenericMapFactory
const factory;
581 BOOST_TEST_REQUIRE(demoMap->empty());
583 auto insertResult1 = demoMap->insert(
"Ultimate answer"s,
"Something philosophical"s);
584 BOOST_TEST(insertResult1.second ==
true);
585 auto insertResult2 = demoMap->insert(
"OK"s,
"Ook!"s);
586 BOOST_TEST(insertResult2.second ==
true);
588 BOOST_TEST(!demoMap->empty());
589 BOOST_TEST(demoMap->size() == 2);
590 BOOST_TEST(demoMap->contains(insertResult1.first));
591 BOOST_TEST(demoMap->contains(insertResult2.first));
592 BOOST_TEST(demoMap->contains(
"OK"s));
593 BOOST_TEST(demoMap->contains(makeKey<std::string>(
"Ultimate answer"s)));
594 BOOST_TEST(demoMap->at(insertResult1.first) ==
"Something philosophical"s);
595 BOOST_TEST(demoMap->at(makeKey<std::string>(
"Ultimate answer"s)) ==
"Something philosophical"s);
596 BOOST_TEST(demoMap->at(insertResult2.first) ==
"Ook!"s);
597 BOOST_TEST(demoMap->at(makeKey<std::string>(
"OK"s)) ==
"Ook!"s);
603 static GenericMapFactory
const factory;
606 BOOST_TEST_REQUIRE(demoMap->empty());
608 ComplexStorable
object(3.1416);
609 BOOST_TEST(demoMap->insert<
Storable>(makeKey<Storable>(
"foo"s),
object) ==
true);
611 std::make_shared<ComplexStorable>(3.141)) ==
true);
612 BOOST_TEST(demoMap->insert<
Storable>(makeKey<Storable>(
"foo"s), SimpleStorable()) ==
false);
614 std::make_shared<SimpleStorable>()) ==
false);
616 BOOST_TEST(!demoMap->empty());
617 BOOST_TEST(demoMap->size() == 2);
618 BOOST_TEST(demoMap->contains(
"foo"s));
619 BOOST_TEST(demoMap->contains(makeKey<Storable>(
"foo"s)));
624 BOOST_TEST(
object == demoMap->at(makeKey<SimpleStorable>(
"foo"s)));
625 object = ComplexStorable(1.4);
626 BOOST_TEST(
object != demoMap->at(makeKey<SimpleStorable>(
"foo"s)));
633 static GenericMapFactory
const factory;
636 BOOST_TEST_REQUIRE(demoMap->empty());
638 BOOST_TEST(demoMap->insert(makeKey<int>(
"key1"s), 3) ==
true);
639 BOOST_TEST(demoMap->insert(makeKey<double>(
"key1"s), 1.0) ==
false);
640 BOOST_TEST(demoMap->insert<
Storable>(makeKey<Storable>(
"key2"s), SimpleStorable()) ==
true);
641 BOOST_TEST(demoMap->insert(makeKey<std::string>(
"key3"s),
"Test value"s) ==
true);
642 BOOST_TEST(demoMap->insert(makeKey<std::string>(
"key4"s),
"This is some text"s) ==
true);
644 BOOST_TEST(demoMap->insert(makeKey<std::string>(
"key5"s), message) ==
true);
645 BOOST_TEST(demoMap->insert(makeKey<int>(
"key3"s), 20) ==
false);
646 BOOST_TEST(demoMap->insert<
double>(makeKey<double>(
"key6"s), 42) ==
true);
648 BOOST_TEST(!demoMap->empty());
649 BOOST_TEST(demoMap->size() == 6);
650 BOOST_TEST(demoMap->at(makeKey<int>(
"key1"s)) == 3);
651 BOOST_TEST(demoMap->at(makeKey<double>(
"key6"s)) == 42);
652 BOOST_TEST(demoMap->at(makeKey<SimpleStorable>(
"key2"s)) == SimpleStorable());
653 BOOST_TEST(demoMap->at(makeKey<std::string>(
"key3"s)) ==
"Test value"s);
654 BOOST_TEST(demoMap->at(makeKey<std::string>(
"key4"s)) ==
"This is some text"s);
655 BOOST_TEST(demoMap->at(makeKey<std::string>(
"key5"s)) == message);
661 static GenericMapFactory
const factory;
664 demoMap->insert(makeKey<int>(
"Ultimate answer"s), 42);
665 BOOST_TEST_REQUIRE(demoMap->size() == 1);
667 BOOST_TEST(demoMap->erase(makeKey<std::string>(
"Ultimate answer"s)) ==
false);
668 BOOST_TEST(demoMap->size() == 1);
669 BOOST_TEST(demoMap->erase(makeKey<int>(
"Ultimate answer"s)) ==
true);
670 BOOST_TEST(demoMap->size() == 0);
676 static GenericMapFactory
const factory;
679 BOOST_TEST_REQUIRE(demoMap->empty());
681 BOOST_TEST(demoMap->insert(makeKey<int>(
"Ultimate answer"s), 42) ==
true);
682 BOOST_TEST(demoMap->insert(makeKey<int>(
"OK"s), 200) ==
true);
683 BOOST_TEST(demoMap->erase(makeKey<int>(
"Ultimate answer"s)) ==
true);
684 BOOST_TEST(demoMap->insert(makeKey<double>(
"Ultimate answer"s), 3.1415927) ==
true);
686 BOOST_TEST(!demoMap->empty());
687 BOOST_TEST(demoMap->size() == 2);
688 BOOST_TEST(demoMap->contains(
"OK"s));
689 BOOST_TEST(!demoMap->contains(makeKey<int>(
"Ultimate answer"s)));
690 BOOST_TEST(demoMap->contains(makeKey<double>(
"Ultimate answer"s)));
691 BOOST_TEST(demoMap->at(makeKey<double>(
"Ultimate answer"s)) == 3.1415927);
701 template <
class GenericMapFactory>
703 using factories = boost::mpl::list<GenericMapFactory>;
705 suite->add(BOOST_TEST_CASE_TEMPLATE(TestConstAt, factories));
706 suite->add(BOOST_TEST_CASE_TEMPLATE(TestAt, factories));
707 suite->add(BOOST_TEST_CASE_TEMPLATE(TestEquals, factories));
708 suite->add(BOOST_TEST_CASE_TEMPLATE(TestSize, factories));
709 suite->add(BOOST_TEST_CASE_TEMPLATE(TestWeakContains, factories));
710 suite->add(BOOST_TEST_CASE_TEMPLATE(TestContains, factories));
711 suite->add(BOOST_TEST_CASE_TEMPLATE(TestKeys, factories));
712 suite->add(BOOST_TEST_CASE_TEMPLATE(TestConstVisitor, factories));
713 suite->add(BOOST_TEST_CASE_TEMPLATE(TestModifyingVoidVisitor, factories));
714 suite->add(BOOST_TEST_CASE_TEMPLATE(TestModifyingReturningVisitor, factories));
726 template <
class GenericMapFactory>
728 using factories = boost::mpl::list<GenericMapFactory>;
730 addGenericMapTestCases<GenericMapFactory>(suite);
732 suite->add(BOOST_TEST_CASE_TEMPLATE(TestMutableEquals, factories));
733 suite->add(BOOST_TEST_CASE_TEMPLATE(TestMutableSize, factories));
734 suite->add(BOOST_TEST_CASE_TEMPLATE(TestClear, factories));
735 suite->add(BOOST_TEST_CASE_TEMPLATE(TestClearIdempotent, factories));
736 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertInt, factories));
737 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertString, factories));
738 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertStorable, factories));
739 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInterleavedInserts, factories));
740 suite->add(BOOST_TEST_CASE_TEMPLATE(TestErase, factories));
741 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertEraseInsert, factories));
752 template <
class GenericMapFactory>
754 addGenericMapTestCases<GenericMapFactory>(&(boost::unit_test::framework::master_test_suite()));
766 template <
class GenericMapFactory>
768 addMutableGenericMapTestCases<GenericMapFactory>(&(boost::unit_test::framework::master_test_suite()));
Interface supporting iteration over heterogenous containers.
BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestConstAt, GenericMapFactory)
std::size_t hash_value(Extent< T, N > const &extent) noexcept
constexpr Key< K, V > makeKey(K const &id)
Factory function for Key, to enable type parameter inference.
void addMutableGenericMapTestCases(boost::unit_test::test_suite *const suite)
Create generic test cases for a specific MutableGenericMap implementation.
A base class for image defects.
Abstract factory that creates GenericMap and MutableGenericMap instances as needed.
Reports attempts to access elements outside a valid range of indices.
ItemVariant const * other
void addGenericMapTestCases(boost::unit_test::test_suite *const suite)
Create generic test cases for a specific GenericMap implementation.