LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
test.h
Go to the documentation of this file.
1// -*- LSST-C++ -*-
2/*
3 * This file is part of afw.
4 *
5 * Developed for the LSST Data Management System.
6 * This product includes software developed by the LSST Project
7 * (https://www.lsst.org).
8 * See the COPYRIGHT file at the top-level directory of this distribution
9 * for details of code ownership.
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
25#ifndef LSST_AFW_TYPEHANDLING_TEST_H
26#define LSST_AFW_TYPEHANDLING_TEST_H
27
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
33
34#include <memory>
35#include <numeric>
36#include <set>
37#include <sstream>
38#include <string>
39
40#include <boost/mpl/list.hpp>
41
42#include "lsst/pex/exceptions.h"
43
46
47namespace lsst {
48namespace afw {
49namespace typehandling {
50namespace test {
51
52/*
53 * This include file defines tests that exercise the GenericMap and MutableGenericMap interfaces, and ensures
54 * that any implementation satisfies the requirements of these interfaces. Subclass authors should call either
55 * addGenericMapTestCases or addMutableGenericMapTestCases in a suitable entry point, such as a global fixture
56 * or a module initialization function.
57 */
58
59namespace {
60class SimpleStorable : public Storable {
61public:
62 virtual ~SimpleStorable() = default;
63
64 std::shared_ptr<Storable> cloneStorable() const override { return std::make_unique<SimpleStorable>(); }
65
66 std::string toString() const override { return "Simplest possible representation"; }
67
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); }
71};
72
73class ComplexStorable final : public SimpleStorable {
74public:
75 constexpr ComplexStorable(double storage) : SimpleStorable(), storage(storage) {}
76
77 ComplexStorable& operator=(double newValue) {
78 storage = newValue;
79 return *this;
80 }
81
82 std::shared_ptr<Storable> cloneStorable() const override {
83 return std::make_unique<ComplexStorable>(storage);
84 }
85
86 std::string toString() const override { return "ComplexStorable(" + std::to_string(storage) + ")"; }
87
88 std::size_t hash_value() const noexcept override { return std::hash<double>()(storage); }
89
90 // Warning: violates both substitution and equality symmetry!
91 bool equals(Storable const& other) const noexcept override {
92 auto complexOther = dynamic_cast<ComplexStorable const*>(&other);
93 if (complexOther) {
94 return this->storage == complexOther->storage;
95 } else {
96 return false;
97 }
98 }
99 bool operator==(SimpleStorable const& other) const override { return this->equals(other); }
100
101private:
102 double storage;
103};
104
105template <typename T>
106std::string universalToString(T const& value) {
107 std::stringstream buffer;
108 buffer << value;
109 return buffer.str();
110};
111
112// Would make more sense as static constants in GenericFactory
113// but neither string nor Storable qualify as literal types
114// In anonymous namespace to ensure constants are internal to whatever test includes this header
115auto const KEY0 = makeKey<bool>(0);
116bool const VALUE0 = true;
117auto const KEY1 = makeKey<int>(1);
118int const VALUE1 = 42;
119auto const KEY2 = makeKey<double>(2);
120int const VALUE2 = VALUE1;
121auto const KEY3 = makeKey<std::string>(3);
122std::string const VALUE3 = "How many roads must a man walk down?";
123auto const KEY4 = makeKey<std::shared_ptr<SimpleStorable const>>(4);
124auto const VALUE4 = SimpleStorable();
125auto const KEY5 = makeKey<ComplexStorable>(5);
126auto const VALUE5 = ComplexStorable(-100.0);
127auto const KEY6 = makeKey<std::shared_ptr<Storable const>>(6);
128auto const VALUE6 = std::shared_ptr<Storable const>();
129} // namespace
130
135public:
136 virtual ~GenericFactory() = default;
137
150
153};
154
155BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestConstAt, GenericMapFactory) {
156 static GenericMapFactory const factory;
157 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
158
159 BOOST_TEST(demoMap->at(KEY0) == VALUE0);
160 BOOST_TEST(demoMap->at(KEY1) == VALUE1);
161 BOOST_TEST(demoMap->at(KEY2) == VALUE2);
162 BOOST_TEST(demoMap->at(KEY3) == VALUE3);
163 BOOST_TEST(*(demoMap->at(KEY4)) == VALUE4);
164 BOOST_TEST(demoMap->at(KEY5) == VALUE5);
165 BOOST_TEST(demoMap->at(KEY6) == VALUE6);
166}
167
168BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestAt, GenericMapFactory) {
169 using namespace std::string_literals;
170
171 static GenericMapFactory const factory;
172 std::unique_ptr<GenericMap<int>> demoMap = factory.makeGenericMap();
173
174 BOOST_TEST(demoMap->at(KEY0) == VALUE0);
175 demoMap->at(KEY0) = false;
176 BOOST_TEST(demoMap->at(KEY0) == false);
177 BOOST_CHECK_THROW(demoMap->at(makeKey<int>(KEY0.getId())), pex::exceptions::OutOfRangeError);
178
179 BOOST_TEST(demoMap->at(KEY1) == VALUE1);
180 demoMap->at(KEY1)++;
181 BOOST_TEST(demoMap->at(KEY1) == VALUE1 + 1);
182 BOOST_CHECK_THROW(demoMap->at(makeKey<bool>(KEY1.getId())), pex::exceptions::OutOfRangeError);
183
184 BOOST_TEST(demoMap->at(KEY2) == VALUE2);
185 demoMap->at(KEY2) = 0.0;
186 BOOST_TEST(demoMap->at(KEY2) == 0.0);
187 // VALUE2 is of a different type than KEY2, check that alternate key is absent
188 using Type2 = std::remove_const_t<decltype(VALUE2)>;
189 BOOST_CHECK_THROW(demoMap->at(makeKey<Type2>(KEY2.getId())), pex::exceptions::OutOfRangeError);
190
191 BOOST_TEST(demoMap->at(KEY3) == VALUE3);
192 demoMap->at(KEY3).append(" Oops, wrong question."s);
193 BOOST_TEST(demoMap->at(KEY3) == VALUE3 + " Oops, wrong question."s);
194
195 BOOST_TEST(*(demoMap->at(KEY4)) == VALUE4);
196 // VALUE4 is of a different type than KEY4, check that alternate key is absent
197 using Type4 = std::remove_const_t<decltype(VALUE4)>;
198 BOOST_CHECK_THROW(demoMap->at(makeKey<Type4>(KEY4.getId())), pex::exceptions::OutOfRangeError);
199
200 BOOST_TEST(demoMap->at(KEY5) == VALUE5);
201 BOOST_TEST(demoMap->at(makeKey<SimpleStorable>(KEY5.getId())) == VALUE5);
202
203 ComplexStorable newValue(5.0);
204 demoMap->at(KEY5) = newValue;
205 BOOST_TEST(demoMap->at(KEY5) == newValue);
206
207 BOOST_TEST(demoMap->at(KEY6) == VALUE6);
208}
209
210BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestEquals, GenericMapFactory) {
211 static GenericMapFactory const factory;
212 auto map1 = factory.makeGenericMap();
213
214 // Use BOOST_CHECK to avoid BOOST_TEST bug from GenericMap being unprintable
215 BOOST_CHECK(*map1 == *map1);
216 // Maps are unequal because shared_ptr members point to different objects
217 BOOST_CHECK(*map1 != *(factory.makeGenericMap()));
218}
219
220BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestConstVisitor, GenericMapFactory) {
221 static GenericMapFactory const factory;
222 std::unique_ptr<GenericMap<int> const> const map = factory.makeGenericMap();
223 std::vector<int> mapKeys = map->keys();
224
225 // Visitors return string because it's one of the few operations valid for all types of interest
226 // This lets us test generic lambdas as visitors
227 auto bruteForcePrinter = [&map](int key) {
228 switch (key) {
229 case 0:
230 return universalToString(map->at(KEY0));
231 case 1:
232 return universalToString(map->at(KEY1));
233 case 2:
234 return universalToString(map->at(KEY2));
235 case 3:
236 return universalToString(map->at(KEY3));
237 case 4:
238 return universalToString(map->at(KEY4));
239 case 5:
240 return universalToString(map->at(KEY5));
241 case 6:
242 return universalToString(map->at(KEY6));
243 default:
244 throw std::invalid_argument("Bad key found");
245 };
246 };
248 for (int key : mapKeys) {
249 expected.push_back(bruteForcePrinter(key));
250 }
251
252 // Test local class that returns void
253 class {
254 public:
256
257 // Local classes can't have method templates
258 void operator()(int, bool value) { results.push_back(universalToString(value)); }
259 void operator()(int, int const& value) { results.push_back(universalToString(value)); }
260 void operator()(int, long value) { results.push_back(universalToString(value)); }
261 void operator()(int, long long value) { results.push_back(universalToString(value)); }
262 void operator()(int, float const& value) { results.push_back(universalToString(value)); }
263 void operator()(int, double value) { results.push_back(universalToString(value)); }
264 void operator()(int, std::string const& value) { results.push_back(universalToString(value)); }
265 void operator()(int, Storable const& value) { results.push_back(universalToString(value)); }
266 void operator()(int, std::shared_ptr<Storable const> value) {
267 results.push_back(universalToString(value));
268 }
269 } printer;
270 map->apply(printer);
271 BOOST_REQUIRE(printer.results.size() == expected.size());
272 for (std::size_t i = 0; i < printer.results.size(); ++i) {
273 BOOST_TEST(printer.results[i] == expected[i],
274 printer.results[i] << " != " << expected[i] << ", key = " << mapKeys[i]);
275 }
276
277 // Test lambda that returns string
279 map->apply([](int, auto const& value) { return universalToString(value); });
280 BOOST_REQUIRE(strings.size() == expected.size());
281 for (std::size_t i = 0; i < strings.size(); ++i) {
282 BOOST_TEST(strings[i] == expected[i],
283 strings[i] << " != " << expected[i] << ", key = " << mapKeys[i]);
284 }
285}
286
287BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestModifyingVoidVisitor, GenericMapFactory) {
288 static GenericMapFactory const factory;
289 std::unique_ptr<GenericMap<int>> map = factory.makeGenericMap();
290 std::vector<int> originalKeys = map->keys();
291
292 // Test local class that returns void
293 class {
294 public:
295 // Local classes can't have method templates
296 void operator()(int, bool& value) { value = !value; }
297 void operator()(int, int& value) { value *= 2; }
298 void operator()(int, long& value) { value *= 2; }
299 void operator()(int, long long& value) { value *= 2; }
300 void operator()(int, float& value) { value *= 2; }
301 void operator()(int, double& value) { value *= 2; }
302 void operator()(int, std::string& value) { value += "Appendix"; }
303 void operator()(int, Storable& value) {
304 auto complexStorable = dynamic_cast<ComplexStorable*>(&value);
305 if (complexStorable != nullptr) {
306 *complexStorable = 42;
307 }
308 }
309 void operator()(int, std::shared_ptr<Storable const>) {}
310 } grower;
311 map->apply(grower);
312 std::vector<int> newKeys = map->keys();
313
314 BOOST_TEST(newKeys == originalKeys);
315 BOOST_TEST(map->at(KEY0) == !VALUE0);
316 BOOST_TEST(map->at(KEY1) == 2 * VALUE1);
317 BOOST_TEST(map->at(KEY2) == 2 * VALUE2);
318 BOOST_TEST(map->at(KEY3) == VALUE3 + "Appendix");
319 BOOST_TEST(*(map->at(KEY4)) == VALUE4);
320 BOOST_TEST(map->at(KEY5) != VALUE5);
321 BOOST_TEST(map->at(KEY5) == ComplexStorable(42));
322 BOOST_TEST(map->at(KEY6) == nullptr);
323}
324
325BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestModifyingReturningVisitor, GenericMapFactory) {
326 static GenericMapFactory const factory;
327 std::unique_ptr<GenericMap<int>> map = factory.makeGenericMap();
328 std::vector<int> originalKeys = map->keys();
329
330 // Test local class that returns int
331 class {
332 public:
333 // Local classes can't have method templates
334 int operator()(int key, bool& value) {
335 value = !value;
336 return key;
337 }
338 int operator()(int key, int& value) {
339 value *= 2;
340 return key;
341 }
342 int operator()(int key, long& value) {
343 value *= 2;
344 return key;
345 }
346 int operator()(int key, long long& value) {
347 value *= 2;
348 return key;
349 }
350 int operator()(int key, float& value) {
351 value *= 2;
352 return key;
353 }
354 int operator()(int key, double& value) {
355 value *= 2;
356 return key;
357 }
358 int operator()(int key, std::string& value) {
359 value += "Appendix";
360 return key;
361 }
362 int operator()(int key, Storable& value) {
363 auto complexStorable = dynamic_cast<ComplexStorable*>(&value);
364 if (complexStorable != nullptr) {
365 *complexStorable = 42;
366 }
367 return key;
368 }
369 int operator()(int key, std::shared_ptr<Storable const>) { return key; }
370 } grower;
371 std::vector<int> editedKeys = map->apply(grower);
372 BOOST_TEST(editedKeys == originalKeys);
373
374 std::vector<int> newKeys = map->keys();
375 BOOST_TEST(newKeys == originalKeys);
376 BOOST_TEST(map->at(KEY0) == !VALUE0);
377 BOOST_TEST(map->at(KEY1) == 2 * VALUE1);
378 BOOST_TEST(map->at(KEY2) == 2 * VALUE2);
379 BOOST_TEST(map->at(KEY3) == VALUE3 + "Appendix");
380 BOOST_TEST(*(map->at(KEY4)) == VALUE4);
381 BOOST_TEST(map->at(KEY5) != VALUE5);
382 BOOST_TEST(map->at(KEY5) == ComplexStorable(42));
383 BOOST_TEST(map->at(KEY6) == nullptr);
384}
385
386BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestMutableEquals, GenericMapFactory) {
387 using namespace std::string_literals;
388
389 static GenericMapFactory const factory;
390 auto map1 = factory.makeMutableGenericMap();
391 auto map2 = factory.makeMutableGenericMap();
392
393 // Use BOOST_CHECK to avoid BOOST_TEST bug from GenericMap being unprintable
394 BOOST_CHECK(*map1 == *map2);
395
396 auto primitiveKey = makeKey<int>("primitive"s);
397 map1->insert(primitiveKey, 42);
398 BOOST_CHECK(*map1 != *map2);
399 map2->insert(primitiveKey, 42);
400 BOOST_CHECK(*map1 == *map2);
401
402 auto sharedKey = makeKey<std::shared_ptr<SimpleStorable const>>("shared"s);
403 auto common = std::make_shared<SimpleStorable const>(VALUE4);
404 map1->insert(sharedKey, common);
405 BOOST_CHECK(*map1 != *map2);
406 map2->insert(sharedKey, std::make_shared<SimpleStorable const>(VALUE4));
407 BOOST_CHECK(*map1 != *map2);
408 map2->erase(sharedKey);
409 map2->insert(sharedKey, common);
410 BOOST_CHECK(*map1 == *map2);
411
412 auto storableKey = makeKey<ComplexStorable>("storable"s);
413 map1->insert(storableKey, VALUE5);
414 BOOST_CHECK(*map1 != *map2);
415 map2->insert(storableKey, VALUE5);
416 BOOST_CHECK(*map1 == *map2);
417
418 auto nullKey = makeKey<std::shared_ptr<ComplexStorable const>>("null"s);
419 map1->insert(nullKey, std::static_pointer_cast<ComplexStorable const>(VALUE6));
420 BOOST_CHECK(*map1 != *map2);
421 map2->insert(nullKey, std::static_pointer_cast<ComplexStorable const>(VALUE6));
422 BOOST_CHECK(*map1 == *map2);
423}
424
425BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestSize, GenericMapFactory) {
426 static GenericMapFactory const factory;
427 std::unique_ptr<GenericMap<int>> demoMap = factory.makeGenericMap();
428
429 BOOST_TEST(demoMap->size() == 7);
430 BOOST_TEST(!demoMap->empty());
431}
432
433BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestMutableSize, GenericMapFactory) {
434 using namespace std::string_literals;
435
436 static GenericMapFactory const factory;
437 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
438
439 BOOST_TEST_REQUIRE(demoMap->size() == 0);
440 BOOST_TEST_REQUIRE(demoMap->empty());
441
442 demoMap->insert(makeKey<int>("Negative One"s), -1);
443 BOOST_TEST(demoMap->size() == 1);
444 BOOST_TEST(!demoMap->empty());
445
446 demoMap->erase(makeKey<int>("Negative One"s));
447 BOOST_TEST(demoMap->size() == 0);
448 BOOST_TEST(demoMap->empty());
449}
450
451BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestWeakContains, GenericMapFactory) {
452 using namespace std::string_literals;
453
454 static GenericMapFactory const factory;
455 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
456
457 BOOST_TEST(demoMap->contains(KEY0.getId()));
458 BOOST_TEST(demoMap->contains(KEY1.getId()));
459 BOOST_TEST(demoMap->contains(KEY2.getId()));
460 BOOST_TEST(demoMap->contains(KEY3.getId()));
461 BOOST_TEST(demoMap->contains(KEY4.getId()));
462 BOOST_TEST(demoMap->contains(KEY5.getId()));
463 BOOST_TEST(demoMap->contains(KEY6.getId()));
464}
465
466BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestContains, GenericMapFactory) {
467 static GenericMapFactory const factory;
468 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
469
470 BOOST_TEST(demoMap->contains(KEY0));
471 BOOST_TEST(!demoMap->contains(makeKey<int>(KEY0.getId())));
472
473 BOOST_TEST(demoMap->contains(KEY1));
474 BOOST_TEST(!demoMap->contains(makeKey<bool>(KEY1.getId())));
475
476 BOOST_TEST(demoMap->contains(KEY2));
477 // VALUE2 is of a different type than KEY2, check that alternate key is absent
478 BOOST_TEST(!demoMap->contains(makeKey<decltype(VALUE2)>(KEY2.getId())));
479
480 BOOST_TEST(demoMap->contains(KEY3));
481
482 BOOST_TEST(demoMap->contains(KEY4));
483 // VALUE4 is of a different type than KEY4, check that alternate key is absent
484 BOOST_TEST(!demoMap->contains(makeKey<decltype(VALUE4)>(KEY4.getId())));
485
486 BOOST_TEST(demoMap->contains(KEY5));
487 BOOST_TEST(demoMap->contains(makeKey<SimpleStorable>(KEY5.getId())));
488 BOOST_TEST(demoMap->contains(makeKey<Storable>(KEY5.getId())));
489
490 BOOST_TEST(demoMap->contains(KEY6));
491 BOOST_TEST(demoMap->contains(makeKey<std::shared_ptr<SimpleStorable const>>(KEY6.getId())));
492 BOOST_TEST(demoMap->contains(makeKey<std::shared_ptr<ComplexStorable const>>(KEY6.getId())));
493}
494
495BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestKeys, GenericMapFactory) {
496 static GenericMapFactory const factory;
497 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
498 auto orderedKeys = demoMap->keys();
499 // GenericMap allows keys in any order, so just check they're the same
500 std::set<int> keys(orderedKeys.begin(), orderedKeys.end());
501
502 BOOST_TEST(keys == std::set<int>({KEY0.getId(), KEY1.getId(), KEY2.getId(), KEY3.getId(), KEY4.getId(),
503 KEY5.getId(), KEY6.getId()}));
504}
505
506BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestKeyOrder, GenericMapFactory) {
507 static GenericMapFactory const factory;
508 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
509 auto keys = demoMap->keys();
510
511 std::vector<int> iterOrder;
512 demoMap->apply([&iterOrder](int key, auto value) { iterOrder.push_back(key); });
513 BOOST_TEST(keys == iterOrder);
514}
515
516BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestClearIdempotent, GenericMapFactory) {
517 static GenericMapFactory const factory;
518 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
519
520 BOOST_TEST_REQUIRE(demoMap->empty());
521 demoMap->clear();
522 BOOST_TEST(demoMap->empty());
523}
524
525BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestClear, GenericMapFactory) {
526 using namespace std::string_literals;
527
528 static GenericMapFactory const factory;
529 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
530
531 demoMap->insert(makeKey<int>("prime"s), 3);
532 demoMap->insert(makeKey<std::string>("foo"s), "bar"s);
533
534 BOOST_TEST_REQUIRE(!demoMap->empty());
535 demoMap->clear();
536 BOOST_TEST(demoMap->empty());
537}
538
539BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInsertInt, GenericMapFactory) {
540 using namespace std::string_literals;
541
542 static GenericMapFactory const factory;
543 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
544
545 BOOST_TEST_REQUIRE(demoMap->empty());
546
547 int x = 27;
548 BOOST_TEST(demoMap->insert(makeKey<int>("cube"s), x) == true);
549 BOOST_TEST(demoMap->insert(makeKey<int>("cube"s), 0) == false);
550
551 BOOST_TEST(!demoMap->empty());
552 BOOST_TEST(demoMap->size() == 1);
553 BOOST_TEST(demoMap->contains("cube"s));
554 BOOST_TEST(demoMap->contains(makeKey<int>("cube"s)));
555 BOOST_TEST(!demoMap->contains(makeKey<double>("cube"s)));
556 BOOST_TEST(demoMap->at(makeKey<int>("cube"s)) == x);
557
558 x = 0;
559 BOOST_TEST(demoMap->at(makeKey<int>("cube"s)) != x);
560
561 demoMap->at(makeKey<int>("cube"s)) = 0;
562 BOOST_TEST(demoMap->at(makeKey<int>("cube"s)) == 0);
563}
564
565BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestWeakInsertInt, GenericMapFactory) {
566 using namespace std::string_literals;
567
568 static GenericMapFactory const factory;
569 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
570
571 BOOST_TEST_REQUIRE(demoMap->empty());
572
573 auto insertResult = demoMap->insert("cube"s, 27);
574 BOOST_TEST(insertResult.second == true);
575 BOOST_TEST(demoMap->insert("cube"s, 0).second == false);
576
577 BOOST_TEST(!demoMap->empty());
578 BOOST_TEST(demoMap->size() == 1);
579 BOOST_TEST(demoMap->contains("cube"s));
580 BOOST_TEST(demoMap->contains(insertResult.first));
581 BOOST_TEST(demoMap->contains(makeKey<int>("cube"s)));
582 BOOST_TEST(!demoMap->contains(makeKey<double>("cube"s)));
583 BOOST_TEST(demoMap->at(insertResult.first) == 27);
584 BOOST_TEST(demoMap->at(makeKey<int>("cube"s)) == 27);
585
586 demoMap->at(insertResult.first) = 0;
587 BOOST_TEST(demoMap->at(insertResult.first) == 0);
588}
589
590BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInsertString, GenericMapFactory) {
591 using namespace std::string_literals;
592
593 static GenericMapFactory const factory;
594 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
595
596 BOOST_TEST_REQUIRE(demoMap->empty());
597
598 std::string answer(
599 "I have a most elegant and wonderful proof, but this string is too small to contain it."s);
600 BOOST_TEST(demoMap->insert(makeKey<std::string>("Ultimate answer"s), answer) == true);
601 BOOST_TEST(demoMap->insert(makeKey<std::string>("OK"s), "Ook!"s) == true);
602 BOOST_TEST(demoMap->insert(makeKey<std::string>("Ultimate answer"s), "Something philosophical"s) ==
603 false);
604
605 BOOST_TEST(!demoMap->empty());
606 BOOST_TEST(demoMap->size() == 2);
607 BOOST_TEST(demoMap->contains("OK"s));
608 BOOST_TEST(demoMap->contains(makeKey<std::string>("Ultimate answer"s)));
609 BOOST_TEST(demoMap->at(makeKey<std::string>("Ultimate answer"s)) == answer);
610 BOOST_TEST(demoMap->at(makeKey<std::string>("OK"s)) == "Ook!"s);
611
612 answer = "I don't know"s;
613 BOOST_TEST(demoMap->at(makeKey<std::string>("Ultimate answer"s)) != answer);
614}
615
616BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestWeakInsertString, GenericMapFactory) {
617 using namespace std::string_literals;
618
619 static GenericMapFactory const factory;
620 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
621
622 BOOST_TEST_REQUIRE(demoMap->empty());
623
624 auto insertResult1 = demoMap->insert("Ultimate answer"s, "Something philosophical"s);
625 BOOST_TEST(insertResult1.second == true);
626 auto insertResult2 = demoMap->insert("OK"s, "Ook!"s);
627 BOOST_TEST(insertResult2.second == true);
628
629 BOOST_TEST(!demoMap->empty());
630 BOOST_TEST(demoMap->size() == 2);
631 BOOST_TEST(demoMap->contains(insertResult1.first));
632 BOOST_TEST(demoMap->contains(insertResult2.first));
633 BOOST_TEST(demoMap->contains("OK"s));
634 BOOST_TEST(demoMap->contains(makeKey<std::string>("Ultimate answer"s)));
635 BOOST_TEST(demoMap->at(insertResult1.first) == "Something philosophical"s);
636 BOOST_TEST(demoMap->at(makeKey<std::string>("Ultimate answer"s)) == "Something philosophical"s);
637 BOOST_TEST(demoMap->at(insertResult2.first) == "Ook!"s);
638 BOOST_TEST(demoMap->at(makeKey<std::string>("OK"s)) == "Ook!"s);
639}
640
641BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInsertStorable, GenericMapFactory) {
642 using namespace std::string_literals;
643
644 static GenericMapFactory const factory;
645 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
646
647 BOOST_TEST_REQUIRE(demoMap->empty());
648
649 ComplexStorable object(3.1416);
650 BOOST_TEST(demoMap->insert<Storable>(makeKey<Storable>("foo"s), object) == true);
651 BOOST_TEST(demoMap->insert(makeKey<std::shared_ptr<ComplexStorable const>>("bar"s),
652 std::make_shared<ComplexStorable const>(3.141)) == true);
653 BOOST_TEST(demoMap->insert<Storable>(makeKey<Storable>("foo"s), SimpleStorable()) == false);
654 BOOST_TEST(demoMap->insert(makeKey<std::shared_ptr<SimpleStorable const>>("bar"s),
655 std::make_shared<SimpleStorable const>()) == false);
656 BOOST_TEST(demoMap->insert(makeKey<std::shared_ptr<SimpleStorable const>>("null"s),
657 std::make_shared<SimpleStorable const>()) == true);
658
659 BOOST_TEST(!demoMap->empty());
660 BOOST_TEST(demoMap->size() == 3);
661 BOOST_TEST(demoMap->contains("foo"s));
662 BOOST_TEST(demoMap->contains(makeKey<Storable>("foo"s)));
663 BOOST_TEST(demoMap->contains(makeKey<std::shared_ptr<ComplexStorable const>>("bar"s)));
664 BOOST_TEST(demoMap->contains(makeKey<std::shared_ptr<SimpleStorable const>>("null"s)));
665
666 // ComplexStorable::operator== is asymmetric
667 BOOST_TEST(object == demoMap->at(makeKey<SimpleStorable>("foo"s)));
668 object = ComplexStorable(1.4);
669 BOOST_TEST(object != demoMap->at(makeKey<SimpleStorable>("foo"s)));
670 BOOST_TEST(*(demoMap->at(makeKey<std::shared_ptr<ComplexStorable const>>("bar"s))) ==
671 ComplexStorable(3.141));
672}
673
674BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInterleavedInserts, GenericMapFactory) {
675 using namespace std::string_literals;
676
677 static GenericMapFactory const factory;
678 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
679
680 BOOST_TEST_REQUIRE(demoMap->empty());
681
682 BOOST_TEST(demoMap->insert(makeKey<int>("key1"s), 3) == true);
683 BOOST_TEST(demoMap->insert(makeKey<double>("key1"s), 1.0) == false);
684 BOOST_TEST(demoMap->insert<Storable>(makeKey<Storable>("key2"s), SimpleStorable()) == true);
685 BOOST_TEST(demoMap->insert(makeKey<std::string>("key3"s), "Test value"s) == true);
686 BOOST_TEST(demoMap->insert(makeKey<std::string>("key4"s), "This is some text"s) == true);
687 std::string const message = "Unknown value for key5."s;
688 BOOST_TEST(demoMap->insert(makeKey<std::string>("key5"s), message) == true);
689 BOOST_TEST(demoMap->insert(makeKey<int>("key3"s), 20) == false);
690 BOOST_TEST(demoMap->insert<double>(makeKey<double>("key6"s), 42) == true);
691
692 BOOST_TEST(!demoMap->empty());
693 BOOST_TEST(demoMap->size() == 6);
694 BOOST_TEST(demoMap->at(makeKey<int>("key1"s)) == 3);
695 BOOST_TEST(demoMap->at(makeKey<double>("key6"s)) == 42);
696 BOOST_TEST(demoMap->at(makeKey<SimpleStorable>("key2"s)) == SimpleStorable());
697 BOOST_TEST(demoMap->at(makeKey<std::string>("key3"s)) == "Test value"s);
698 BOOST_TEST(demoMap->at(makeKey<std::string>("key4"s)) == "This is some text"s);
699 BOOST_TEST(demoMap->at(makeKey<std::string>("key5"s)) == message);
700}
701
702BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestErase, GenericMapFactory) {
703 using namespace std::string_literals;
704
705 static GenericMapFactory const factory;
706 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
707
708 demoMap->insert(makeKey<int>("Ultimate answer"s), 42);
709 BOOST_TEST_REQUIRE(demoMap->size() == 1);
710
711 BOOST_TEST(demoMap->erase(makeKey<std::string>("Ultimate answer"s)) == false);
712 BOOST_TEST(demoMap->size() == 1);
713 BOOST_TEST(demoMap->erase(makeKey<int>("Ultimate answer"s)) == true);
714 BOOST_TEST(demoMap->size() == 0);
715}
716
717BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInsertEraseInsert, GenericMapFactory) {
718 using namespace std::string_literals;
719
720 static GenericMapFactory const factory;
721 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
722
723 BOOST_TEST_REQUIRE(demoMap->empty());
724
725 BOOST_TEST(demoMap->insert(makeKey<int>("Ultimate answer"s), 42) == true);
726 BOOST_TEST(demoMap->insert(makeKey<int>("OK"s), 200) == true);
727 BOOST_TEST(demoMap->erase(makeKey<int>("Ultimate answer"s)) == true);
728 BOOST_TEST(demoMap->insert(makeKey<double>("Ultimate answer"s), 3.1415927) == true);
729
730 BOOST_TEST(!demoMap->empty());
731 BOOST_TEST(demoMap->size() == 2);
732 BOOST_TEST(demoMap->contains("OK"s));
733 BOOST_TEST(!demoMap->contains(makeKey<int>("Ultimate answer"s)));
734 BOOST_TEST(demoMap->contains(makeKey<double>("Ultimate answer"s)));
735 BOOST_TEST(demoMap->at(makeKey<double>("Ultimate answer"s)) == 3.1415927);
736}
737
745template <class GenericMapFactory>
746void addGenericMapTestCases(boost::unit_test::test_suite* const suite) {
747 using factories = boost::mpl::list<GenericMapFactory>;
748
749 suite->add(BOOST_TEST_CASE_TEMPLATE(TestConstAt, factories));
750 suite->add(BOOST_TEST_CASE_TEMPLATE(TestAt, factories));
751 suite->add(BOOST_TEST_CASE_TEMPLATE(TestEquals, factories));
752 suite->add(BOOST_TEST_CASE_TEMPLATE(TestSize, factories));
753 suite->add(BOOST_TEST_CASE_TEMPLATE(TestWeakContains, factories));
754 suite->add(BOOST_TEST_CASE_TEMPLATE(TestContains, factories));
755 suite->add(BOOST_TEST_CASE_TEMPLATE(TestKeys, factories));
756 suite->add(BOOST_TEST_CASE_TEMPLATE(TestKeyOrder, factories));
757 suite->add(BOOST_TEST_CASE_TEMPLATE(TestConstVisitor, factories));
758 suite->add(BOOST_TEST_CASE_TEMPLATE(TestModifyingVoidVisitor, factories));
759 suite->add(BOOST_TEST_CASE_TEMPLATE(TestModifyingReturningVisitor, factories));
760}
761
771template <class GenericMapFactory>
772void addMutableGenericMapTestCases(boost::unit_test::test_suite* const suite) {
773 using factories = boost::mpl::list<GenericMapFactory>;
774
775 addGenericMapTestCases<GenericMapFactory>(suite);
776
777 suite->add(BOOST_TEST_CASE_TEMPLATE(TestMutableEquals, factories));
778 suite->add(BOOST_TEST_CASE_TEMPLATE(TestMutableSize, factories));
779 suite->add(BOOST_TEST_CASE_TEMPLATE(TestClear, factories));
780 suite->add(BOOST_TEST_CASE_TEMPLATE(TestClearIdempotent, factories));
781 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertInt, factories));
782 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertString, factories));
783 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertStorable, factories));
784 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInterleavedInserts, factories));
785 suite->add(BOOST_TEST_CASE_TEMPLATE(TestErase, factories));
786 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertEraseInsert, factories));
787}
788
797template <class GenericMapFactory>
799 addGenericMapTestCases<GenericMapFactory>(&(boost::unit_test::framework::master_test_suite()));
800}
801
811template <class GenericMapFactory>
813 addMutableGenericMapTestCases<GenericMapFactory>(&(boost::unit_test::framework::master_test_suite()));
814}
815
816} // namespace test
817} // namespace typehandling
818} // namespace afw
819} // namespace lsst
820
821#endif
double x
Interface supporting iteration over heterogenous containers.
Definition: Storable.h:58
Abstract factory that creates GenericMap and MutableGenericMap instances as needed.
Definition: test.h:134
virtual std::unique_ptr< GenericMap< int > > makeGenericMap() const =0
Create a map containing the following state:
virtual std::unique_ptr< MutableGenericMap< std::string > > makeMutableGenericMap() const =0
Create an empty map.
Reports attempts to access elements outside a valid range of indices.
Definition: Runtime.h:89
void addGenericMapTestCases(boost::unit_test::test_suite *const suite)
Create generic test cases for a specific GenericMap implementation.
Definition: test.h:746
BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestConstAt, GenericMapFactory)
Definition: test.h:155
void addMutableGenericMapTestCases(boost::unit_test::test_suite *const suite)
Create generic test cases for a specific MutableGenericMap implementation.
Definition: test.h:772
constexpr Key< K, V > makeKey(K const &id)
Factory function for Key, to enable type parameter inference.
Definition: Key.h:173
std::size_t hash_value(Extent< T, N > const &extent) noexcept
Definition: Extent.cc:127
A base class for image defects.
T push_back(T... args)
T size(T... args)
T str(T... args)
T to_string(T... args)