LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
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 {
61friend class ComplexStorable;
62public:
63 ~SimpleStorable() override = default;
64
65 std::shared_ptr<Storable> cloneStorable() const override { return std::make_unique<SimpleStorable>(); }
66
67 std::string toString() const override { return "Simplest possible representation"; }
68
69 bool equals(Storable const& other) const noexcept override { return singleClassEquals(*this, other); }
70 virtual bool operator==(SimpleStorable const& other) const { return true; }
71 bool operator!=(SimpleStorable const& other) const { return !(*this == other); }
72};
73
74class ComplexStorable final : public SimpleStorable {
75public:
76 constexpr ComplexStorable(double storage) : SimpleStorable(), storage(storage) {}
77
78 ComplexStorable& operator=(double newValue) {
79 storage = newValue;
80 return *this;
81 }
82
83 std::shared_ptr<Storable> cloneStorable() const override {
84 return std::make_unique<ComplexStorable>(storage);
85 }
86
87 std::string toString() const override { return "ComplexStorable(" + std::to_string(storage) + ")"; }
88
89 std::size_t hash_value() const noexcept override { return std::hash<double>()(storage); }
90
91 // Fix violation of both substitution and equality symmetry
92 // as the code was broken on gcc with C++20 but passed on clang
93 bool equals(Storable const& other) const noexcept override {
94 if (auto complexOther = dynamic_cast<ComplexStorable const*>(&other)) {
95 return this->storage == complexOther->storage;
96 }
97 return SimpleStorable::equals(other);
98 }
99
100 bool operator==(SimpleStorable const& other) const override {
101 if (auto complexOther = dynamic_cast<ComplexStorable const*>(&other)) {
102 return this->storage == complexOther->storage;
103 }
104 return SimpleStorable::operator==(other);
105 }
106private:
107 double storage;
108};
109
110template <typename T>
111std::string universalToString(T const& value) {
112 std::stringstream buffer;
113 buffer << value;
114 return buffer.str();
115}
116
117// Would make more sense as static constants in GenericFactory
118// but neither string nor Storable qualify as literal types
119// In anonymous namespace to ensure constants are internal to whatever test includes this header
120auto const KEY0 = makeKey<bool>(0);
121bool const VALUE0 = true;
122auto const KEY1 = makeKey<int>(1);
123int const VALUE1 = 42;
124auto const KEY2 = makeKey<double>(2);
125int const VALUE2 = VALUE1;
126auto const KEY3 = makeKey<std::string>(3);
127std::string const VALUE3 = "How many roads must a man walk down?";
128auto const KEY4 = makeKey<std::shared_ptr<SimpleStorable const>>(4);
129auto const VALUE4 = SimpleStorable();
130auto const KEY5 = makeKey<ComplexStorable>(5);
131auto const VALUE5 = ComplexStorable(-100.0);
132auto const KEY6 = makeKey<std::shared_ptr<Storable const>>(6);
133auto const VALUE6 = std::shared_ptr<Storable const>();
134} // namespace
135
159
160BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestConstAt, GenericMapFactory) {
161 static GenericMapFactory const factory;
162 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
163
164 BOOST_TEST(demoMap->at(KEY0) == VALUE0);
165 BOOST_TEST(demoMap->at(KEY1) == VALUE1);
166 BOOST_TEST(demoMap->at(KEY2) == VALUE2);
167 BOOST_TEST(demoMap->at(KEY3) == VALUE3);
168 BOOST_TEST(*(demoMap->at(KEY4)) == VALUE4);
169 BOOST_TEST(demoMap->at(KEY5) == VALUE5);
170 BOOST_TEST(demoMap->at(KEY6) == VALUE6);
171}
172
173BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestAt, GenericMapFactory) {
174 using namespace std::string_literals;
175
176 static GenericMapFactory const factory;
177 std::unique_ptr<GenericMap<int>> demoMap = factory.makeGenericMap();
178
179 BOOST_TEST(demoMap->at(KEY0) == VALUE0);
180 demoMap->at(KEY0) = false;
181 BOOST_TEST(demoMap->at(KEY0) == false);
182 BOOST_CHECK_THROW(demoMap->at(makeKey<int>(KEY0.getId())), pex::exceptions::OutOfRangeError);
183
184 BOOST_TEST(demoMap->at(KEY1) == VALUE1);
185 demoMap->at(KEY1)++;
186 BOOST_TEST(demoMap->at(KEY1) == VALUE1 + 1);
187 BOOST_CHECK_THROW(demoMap->at(makeKey<bool>(KEY1.getId())), pex::exceptions::OutOfRangeError);
188
189 BOOST_TEST(demoMap->at(KEY2) == VALUE2);
190 demoMap->at(KEY2) = 0.0;
191 BOOST_TEST(demoMap->at(KEY2) == 0.0);
192 // VALUE2 is of a different type than KEY2, check that alternate key is absent
193 using Type2 = std::remove_const_t<decltype(VALUE2)>;
194 BOOST_CHECK_THROW(demoMap->at(makeKey<Type2>(KEY2.getId())), pex::exceptions::OutOfRangeError);
195
196 BOOST_TEST(demoMap->at(KEY3) == VALUE3);
197 demoMap->at(KEY3).append(" Oops, wrong question."s);
198 BOOST_TEST(demoMap->at(KEY3) == VALUE3 + " Oops, wrong question."s);
199
200 BOOST_TEST(*(demoMap->at(KEY4)) == VALUE4);
201 // VALUE4 is of a different type than KEY4, check that alternate key is absent
202 using Type4 = std::remove_const_t<decltype(VALUE4)>;
203 BOOST_CHECK_THROW(demoMap->at(makeKey<Type4>(KEY4.getId())), pex::exceptions::OutOfRangeError);
204
205 BOOST_TEST(demoMap->at(KEY5) == VALUE5);
206 BOOST_TEST(demoMap->at(makeKey<SimpleStorable>(KEY5.getId())) == VALUE5);
207
208 ComplexStorable newValue(5.0);
209 demoMap->at(KEY5) = newValue;
210 BOOST_TEST(demoMap->at(KEY5) == newValue);
211
212 BOOST_TEST(demoMap->at(KEY6) == VALUE6);
213}
214
215BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestEquals, GenericMapFactory) {
216 static GenericMapFactory const factory;
217 auto map1 = factory.makeGenericMap();
218
219 // Use BOOST_CHECK to avoid BOOST_TEST bug from GenericMap being unprintable
220 BOOST_CHECK(*map1 == *map1);
221 // Maps are unequal because shared_ptr members point to different objects
222 BOOST_CHECK(*map1 != *(factory.makeGenericMap()));
223}
224
225BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestConstVisitor, GenericMapFactory) {
226 static GenericMapFactory const factory;
227 std::unique_ptr<GenericMap<int> const> const map = factory.makeGenericMap();
228 std::vector<int> mapKeys = map->keys();
229
230 // Visitors return string because it's one of the few operations valid for all types of interest
231 // This lets us test generic lambdas as visitors
232 auto bruteForcePrinter = [&map](int key) {
233 switch (key) {
234 case 0:
235 return universalToString(map->at(KEY0));
236 case 1:
237 return universalToString(map->at(KEY1));
238 case 2:
239 return universalToString(map->at(KEY2));
240 case 3:
241 return universalToString(map->at(KEY3));
242 case 4:
243 return universalToString(map->at(KEY4));
244 case 5:
245 return universalToString(map->at(KEY5));
246 case 6:
247 return universalToString(map->at(KEY6));
248 default:
249 throw std::invalid_argument("Bad key found");
250 }
251 };
253 for (int key : mapKeys) {
254 expected.push_back(bruteForcePrinter(key));
255 }
256
257 // Test local class that returns void
258 class {
259 public:
261
262 // Local classes can't have method templates
263 void operator()(int, bool value) { results.push_back(universalToString(value)); }
264 void operator()(int, int const& value) { results.push_back(universalToString(value)); }
265 void operator()(int, long value) { results.push_back(universalToString(value)); }
266 void operator()(int, long long value) { results.push_back(universalToString(value)); }
267 void operator()(int, float const& value) { results.push_back(universalToString(value)); }
268 void operator()(int, double value) { results.push_back(universalToString(value)); }
269 void operator()(int, std::string const& value) { results.push_back(universalToString(value)); }
270 void operator()(int, Storable const& value) { results.push_back(universalToString(value)); }
271 void operator()(int, std::shared_ptr<Storable const> value) {
272 results.push_back(universalToString(value));
273 }
274 } printer;
275 map->apply(printer);
276 BOOST_REQUIRE(printer.results.size() == expected.size());
277 for (std::size_t i = 0; i < printer.results.size(); ++i) {
278 BOOST_TEST(printer.results[i] == expected[i],
279 printer.results[i] << " != " << expected[i] << ", key = " << mapKeys[i]);
280 }
281
282 // Test lambda that returns string
284 map->apply([](int, auto const& value) { return universalToString(value); });
285 BOOST_REQUIRE(strings.size() == expected.size());
286 for (std::size_t i = 0; i < strings.size(); ++i) {
287 BOOST_TEST(strings[i] == expected[i],
288 strings[i] << " != " << expected[i] << ", key = " << mapKeys[i]);
289 }
290}
291
292BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestModifyingVoidVisitor, GenericMapFactory) {
293 static GenericMapFactory const factory;
294 std::unique_ptr<GenericMap<int>> map = factory.makeGenericMap();
295 std::vector<int> originalKeys = map->keys();
296
297 // Test local class that returns void
298 class {
299 public:
300 // Local classes can't have method templates
301 void operator()(int, bool& value) { value = !value; }
302 void operator()(int, int& value) { value *= 2; }
303 void operator()(int, long& value) { value *= 2; }
304 void operator()(int, long long& value) { value *= 2; }
305 void operator()(int, float& value) { value *= 2; }
306 void operator()(int, double& value) { value *= 2; }
307 void operator()(int, std::string& value) { value += "Appendix"; }
308 void operator()(int, Storable& value) {
309 auto complexStorable = dynamic_cast<ComplexStorable*>(&value);
310 if (complexStorable != nullptr) {
311 *complexStorable = 42;
312 }
313 }
314 void operator()(int, std::shared_ptr<Storable const>) {}
315 } grower;
316 map->apply(grower);
317 std::vector<int> newKeys = map->keys();
318
319 BOOST_TEST(newKeys == originalKeys);
320 BOOST_TEST(map->at(KEY0) == !VALUE0);
321 BOOST_TEST(map->at(KEY1) == 2 * VALUE1);
322 BOOST_TEST(map->at(KEY2) == 2 * VALUE2);
323 BOOST_TEST(map->at(KEY3) == VALUE3 + "Appendix");
324 BOOST_TEST(*(map->at(KEY4)) == VALUE4);
325 BOOST_TEST(map->at(KEY5) != VALUE5);
326 BOOST_TEST(map->at(KEY5) == ComplexStorable(42));
327 BOOST_TEST(map->at(KEY6) == nullptr);
328}
329
330BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestModifyingReturningVisitor, GenericMapFactory) {
331 static GenericMapFactory const factory;
332 std::unique_ptr<GenericMap<int>> map = factory.makeGenericMap();
333 std::vector<int> originalKeys = map->keys();
334
335 // Test local class that returns int
336 class {
337 public:
338 // Local classes can't have method templates
339 int operator()(int key, bool& value) {
340 value = !value;
341 return key;
342 }
343 int operator()(int key, int& value) {
344 value *= 2;
345 return key;
346 }
347 int operator()(int key, long& value) {
348 value *= 2;
349 return key;
350 }
351 int operator()(int key, long long& value) {
352 value *= 2;
353 return key;
354 }
355 int operator()(int key, float& value) {
356 value *= 2;
357 return key;
358 }
359 int operator()(int key, double& value) {
360 value *= 2;
361 return key;
362 }
363 int operator()(int key, std::string& value) {
364 value += "Appendix";
365 return key;
366 }
367 int operator()(int key, Storable& value) {
368 auto complexStorable = dynamic_cast<ComplexStorable*>(&value);
369 if (complexStorable != nullptr) {
370 *complexStorable = 42;
371 }
372 return key;
373 }
374 int operator()(int key, std::shared_ptr<Storable const>) { return key; }
375 } grower;
376 std::vector<int> editedKeys = map->apply(grower);
377 BOOST_TEST(editedKeys == originalKeys);
378
379 std::vector<int> newKeys = map->keys();
380 BOOST_TEST(newKeys == originalKeys);
381 BOOST_TEST(map->at(KEY0) == !VALUE0);
382 BOOST_TEST(map->at(KEY1) == 2 * VALUE1);
383 BOOST_TEST(map->at(KEY2) == 2 * VALUE2);
384 BOOST_TEST(map->at(KEY3) == VALUE3 + "Appendix");
385 BOOST_TEST(*(map->at(KEY4)) == VALUE4);
386 BOOST_TEST(map->at(KEY5) != VALUE5);
387 BOOST_TEST(map->at(KEY5) == ComplexStorable(42));
388 BOOST_TEST(map->at(KEY6) == nullptr);
389}
390
391BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestMutableEquals, GenericMapFactory) {
392 using namespace std::string_literals;
393
394 static GenericMapFactory const factory;
395 auto map1 = factory.makeMutableGenericMap();
396 auto map2 = factory.makeMutableGenericMap();
397
398 // Use BOOST_CHECK to avoid BOOST_TEST bug from GenericMap being unprintable
399 BOOST_CHECK(*map1 == *map2);
400
401 auto primitiveKey = makeKey<int>("primitive"s);
402 map1->insert(primitiveKey, 42);
403 BOOST_CHECK(*map1 != *map2);
404 map2->insert(primitiveKey, 42);
405 BOOST_CHECK(*map1 == *map2);
406
407 auto sharedKey = makeKey<std::shared_ptr<SimpleStorable const>>("shared"s);
408 auto common = std::make_shared<SimpleStorable const>(VALUE4);
409 map1->insert(sharedKey, common);
410 BOOST_CHECK(*map1 != *map2);
411 map2->insert(sharedKey, std::make_shared<SimpleStorable const>(VALUE4));
412 BOOST_CHECK(*map1 != *map2);
413 map2->erase(sharedKey);
414 map2->insert(sharedKey, common);
415 BOOST_CHECK(*map1 == *map2);
416
417 auto storableKey = makeKey<ComplexStorable>("storable"s);
418 map1->insert(storableKey, VALUE5);
419 BOOST_CHECK(*map1 != *map2);
420 map2->insert(storableKey, VALUE5);
421 BOOST_CHECK(*map1 == *map2);
422
423 auto nullKey = makeKey<std::shared_ptr<ComplexStorable const>>("null"s);
424 map1->insert(nullKey, std::static_pointer_cast<ComplexStorable const>(VALUE6));
425 BOOST_CHECK(*map1 != *map2);
426 map2->insert(nullKey, std::static_pointer_cast<ComplexStorable const>(VALUE6));
427 BOOST_CHECK(*map1 == *map2);
428}
429
430BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestSize, GenericMapFactory) {
431 static GenericMapFactory const factory;
432 std::unique_ptr<GenericMap<int>> demoMap = factory.makeGenericMap();
433
434 BOOST_TEST(demoMap->size() == 7);
435 BOOST_TEST(!demoMap->empty());
436}
437
438BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestMutableSize, GenericMapFactory) {
439 using namespace std::string_literals;
440
441 static GenericMapFactory const factory;
442 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
443
444 BOOST_TEST_REQUIRE(demoMap->size() == 0);
445 BOOST_TEST_REQUIRE(demoMap->empty());
446
447 demoMap->insert(makeKey<int>("Negative One"s), -1);
448 BOOST_TEST(demoMap->size() == 1);
449 BOOST_TEST(!demoMap->empty());
450
451 demoMap->erase(makeKey<int>("Negative One"s));
452 BOOST_TEST(demoMap->size() == 0);
453 BOOST_TEST(demoMap->empty());
454}
455
456BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestWeakContains, GenericMapFactory) {
457 using namespace std::string_literals;
458
459 static GenericMapFactory const factory;
460 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
461
462 BOOST_TEST(demoMap->contains(KEY0.getId()));
463 BOOST_TEST(demoMap->contains(KEY1.getId()));
464 BOOST_TEST(demoMap->contains(KEY2.getId()));
465 BOOST_TEST(demoMap->contains(KEY3.getId()));
466 BOOST_TEST(demoMap->contains(KEY4.getId()));
467 BOOST_TEST(demoMap->contains(KEY5.getId()));
468 BOOST_TEST(demoMap->contains(KEY6.getId()));
469}
470
471BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestContains, GenericMapFactory) {
472 static GenericMapFactory const factory;
473 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
474
475 BOOST_TEST(demoMap->contains(KEY0));
476 BOOST_TEST(!demoMap->contains(makeKey<int>(KEY0.getId())));
477
478 BOOST_TEST(demoMap->contains(KEY1));
479 BOOST_TEST(!demoMap->contains(makeKey<bool>(KEY1.getId())));
480
481 BOOST_TEST(demoMap->contains(KEY2));
482 // VALUE2 is of a different type than KEY2, check that alternate key is absent
483 BOOST_TEST(!demoMap->contains(makeKey<decltype(VALUE2)>(KEY2.getId())));
484
485 BOOST_TEST(demoMap->contains(KEY3));
486
487 BOOST_TEST(demoMap->contains(KEY4));
488 // VALUE4 is of a different type than KEY4, check that alternate key is absent
489 BOOST_TEST(!demoMap->contains(makeKey<decltype(VALUE4)>(KEY4.getId())));
490
491 BOOST_TEST(demoMap->contains(KEY5));
492 BOOST_TEST(demoMap->contains(makeKey<SimpleStorable>(KEY5.getId())));
493 BOOST_TEST(demoMap->contains(makeKey<Storable>(KEY5.getId())));
494
495 BOOST_TEST(demoMap->contains(KEY6));
496 BOOST_TEST(demoMap->contains(makeKey<std::shared_ptr<SimpleStorable const>>(KEY6.getId())));
497 BOOST_TEST(demoMap->contains(makeKey<std::shared_ptr<ComplexStorable const>>(KEY6.getId())));
498}
499
500BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestKeys, GenericMapFactory) {
501 static GenericMapFactory const factory;
502 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
503 auto orderedKeys = demoMap->keys();
504 // GenericMap allows keys in any order, so just check they're the same
505 std::set<int> keys(orderedKeys.begin(), orderedKeys.end());
506
507 BOOST_TEST(keys == std::set<int>({KEY0.getId(), KEY1.getId(), KEY2.getId(), KEY3.getId(), KEY4.getId(),
508 KEY5.getId(), KEY6.getId()}));
509}
510
511BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestKeyOrder, GenericMapFactory) {
512 static GenericMapFactory const factory;
513 std::unique_ptr<GenericMap<int> const> demoMap = factory.makeGenericMap();
514 auto keys = demoMap->keys();
515
516 std::vector<int> iterOrder;
517 demoMap->apply([&iterOrder](int key, auto value) { iterOrder.push_back(key); });
518 BOOST_TEST(keys == iterOrder);
519}
520
521BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestClearIdempotent, GenericMapFactory) {
522 static GenericMapFactory const factory;
523 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
524
525 BOOST_TEST_REQUIRE(demoMap->empty());
526 demoMap->clear();
527 BOOST_TEST(demoMap->empty());
528}
529
530BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestClear, GenericMapFactory) {
531 using namespace std::string_literals;
532
533 static GenericMapFactory const factory;
534 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
535
536 demoMap->insert(makeKey<int>("prime"s), 3);
537 demoMap->insert(makeKey<std::string>("foo"s), "bar"s);
538
539 BOOST_TEST_REQUIRE(!demoMap->empty());
540 demoMap->clear();
541 BOOST_TEST(demoMap->empty());
542}
543
544BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInsertInt, GenericMapFactory) {
545 using namespace std::string_literals;
546
547 static GenericMapFactory const factory;
548 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
549
550 BOOST_TEST_REQUIRE(demoMap->empty());
551
552 int x = 27;
553 BOOST_TEST(demoMap->insert(makeKey<int>("cube"s), x) == true);
554 BOOST_TEST(demoMap->insert(makeKey<int>("cube"s), 0) == false);
555
556 BOOST_TEST(!demoMap->empty());
557 BOOST_TEST(demoMap->size() == 1);
558 BOOST_TEST(demoMap->contains("cube"s));
559 BOOST_TEST(demoMap->contains(makeKey<int>("cube"s)));
560 BOOST_TEST(!demoMap->contains(makeKey<double>("cube"s)));
561 BOOST_TEST(demoMap->at(makeKey<int>("cube"s)) == x);
562
563 x = 0;
564 BOOST_TEST(demoMap->at(makeKey<int>("cube"s)) != x);
565
566 demoMap->at(makeKey<int>("cube"s)) = 0;
567 BOOST_TEST(demoMap->at(makeKey<int>("cube"s)) == 0);
568}
569
570BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestWeakInsertInt, GenericMapFactory) {
571 using namespace std::string_literals;
572
573 static GenericMapFactory const factory;
574 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
575
576 BOOST_TEST_REQUIRE(demoMap->empty());
577
578 auto insertResult = demoMap->insert("cube"s, 27);
579 BOOST_TEST(insertResult.second == true);
580 BOOST_TEST(demoMap->insert("cube"s, 0).second == false);
581
582 BOOST_TEST(!demoMap->empty());
583 BOOST_TEST(demoMap->size() == 1);
584 BOOST_TEST(demoMap->contains("cube"s));
585 BOOST_TEST(demoMap->contains(insertResult.first));
586 BOOST_TEST(demoMap->contains(makeKey<int>("cube"s)));
587 BOOST_TEST(!demoMap->contains(makeKey<double>("cube"s)));
588 BOOST_TEST(demoMap->at(insertResult.first) == 27);
589 BOOST_TEST(demoMap->at(makeKey<int>("cube"s)) == 27);
590
591 demoMap->at(insertResult.first) = 0;
592 BOOST_TEST(demoMap->at(insertResult.first) == 0);
593}
594
595BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInsertString, GenericMapFactory) {
596 using namespace std::string_literals;
597
598 static GenericMapFactory const factory;
599 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
600
601 BOOST_TEST_REQUIRE(demoMap->empty());
602
603 std::string answer(
604 "I have a most elegant and wonderful proof, but this string is too small to contain it."s);
605 BOOST_TEST(demoMap->insert(makeKey<std::string>("Ultimate answer"s), answer) == true);
606 BOOST_TEST(demoMap->insert(makeKey<std::string>("OK"s), "Ook!"s) == true);
607 BOOST_TEST(demoMap->insert(makeKey<std::string>("Ultimate answer"s), "Something philosophical"s) ==
608 false);
609
610 BOOST_TEST(!demoMap->empty());
611 BOOST_TEST(demoMap->size() == 2);
612 BOOST_TEST(demoMap->contains("OK"s));
613 BOOST_TEST(demoMap->contains(makeKey<std::string>("Ultimate answer"s)));
614 BOOST_TEST(demoMap->at(makeKey<std::string>("Ultimate answer"s)) == answer);
615 BOOST_TEST(demoMap->at(makeKey<std::string>("OK"s)) == "Ook!"s);
616
617 answer = "I don't know"s;
618 BOOST_TEST(demoMap->at(makeKey<std::string>("Ultimate answer"s)) != answer);
619}
620
621BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestWeakInsertString, GenericMapFactory) {
622 using namespace std::string_literals;
623
624 static GenericMapFactory const factory;
625 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
626
627 BOOST_TEST_REQUIRE(demoMap->empty());
628
629 auto insertResult1 = demoMap->insert("Ultimate answer"s, "Something philosophical"s);
630 BOOST_TEST(insertResult1.second == true);
631 auto insertResult2 = demoMap->insert("OK"s, "Ook!"s);
632 BOOST_TEST(insertResult2.second == true);
633
634 BOOST_TEST(!demoMap->empty());
635 BOOST_TEST(demoMap->size() == 2);
636 BOOST_TEST(demoMap->contains(insertResult1.first));
637 BOOST_TEST(demoMap->contains(insertResult2.first));
638 BOOST_TEST(demoMap->contains("OK"s));
639 BOOST_TEST(demoMap->contains(makeKey<std::string>("Ultimate answer"s)));
640 BOOST_TEST(demoMap->at(insertResult1.first) == "Something philosophical"s);
641 BOOST_TEST(demoMap->at(makeKey<std::string>("Ultimate answer"s)) == "Something philosophical"s);
642 BOOST_TEST(demoMap->at(insertResult2.first) == "Ook!"s);
643 BOOST_TEST(demoMap->at(makeKey<std::string>("OK"s)) == "Ook!"s);
644}
645
646BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInsertStorable, GenericMapFactory) {
647 using namespace std::string_literals;
648
649 static GenericMapFactory const factory;
650 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
651
652 BOOST_TEST_REQUIRE(demoMap->empty());
653
654 ComplexStorable object(3.1416);
655 BOOST_TEST(demoMap->insert<Storable>(makeKey<Storable>("foo"s), object) == true);
656 BOOST_TEST(demoMap->insert(makeKey<std::shared_ptr<ComplexStorable const>>("bar"s),
657 std::make_shared<ComplexStorable const>(3.141)) == true);
658 BOOST_TEST(demoMap->insert<Storable>(makeKey<Storable>("foo"s), SimpleStorable()) == false);
659 BOOST_TEST(demoMap->insert(makeKey<std::shared_ptr<SimpleStorable const>>("bar"s),
660 std::make_shared<SimpleStorable const>()) == false);
661 BOOST_TEST(demoMap->insert(makeKey<std::shared_ptr<SimpleStorable const>>("null"s),
662 std::make_shared<SimpleStorable const>()) == true);
663
664 BOOST_TEST(!demoMap->empty());
665 BOOST_TEST(demoMap->size() == 3);
666 BOOST_TEST(demoMap->contains("foo"s));
667 BOOST_TEST(demoMap->contains(makeKey<Storable>("foo"s)));
668 BOOST_TEST(demoMap->contains(makeKey<std::shared_ptr<ComplexStorable const>>("bar"s)));
669 BOOST_TEST(demoMap->contains(makeKey<std::shared_ptr<SimpleStorable const>>("null"s)));
670
671 // ComplexStorable::operator== is asymmetric
672 BOOST_TEST(object == demoMap->at(makeKey<SimpleStorable>("foo"s)));
673 object = ComplexStorable(1.4);
674 BOOST_TEST(object != demoMap->at(makeKey<SimpleStorable>("foo"s)));
675 BOOST_TEST(*(demoMap->at(makeKey<std::shared_ptr<ComplexStorable const>>("bar"s))) ==
676 ComplexStorable(3.141));
677}
678
679BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInterleavedInserts, GenericMapFactory) {
680 using namespace std::string_literals;
681
682 static GenericMapFactory const factory;
683 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
684
685 BOOST_TEST_REQUIRE(demoMap->empty());
686
687 BOOST_TEST(demoMap->insert(makeKey<int>("key1"s), 3) == true);
688 BOOST_TEST(demoMap->insert(makeKey<double>("key1"s), 1.0) == false);
689 BOOST_TEST(demoMap->insert<Storable>(makeKey<Storable>("key2"s), SimpleStorable()) == true);
690 BOOST_TEST(demoMap->insert(makeKey<std::string>("key3"s), "Test value"s) == true);
691 BOOST_TEST(demoMap->insert(makeKey<std::string>("key4"s), "This is some text"s) == true);
692 std::string const message = "Unknown value for key5."s;
693 BOOST_TEST(demoMap->insert(makeKey<std::string>("key5"s), message) == true);
694 BOOST_TEST(demoMap->insert(makeKey<int>("key3"s), 20) == false);
695 BOOST_TEST(demoMap->insert<double>(makeKey<double>("key6"s), 42) == true);
696
697 BOOST_TEST(!demoMap->empty());
698 BOOST_TEST(demoMap->size() == 6);
699 BOOST_TEST(demoMap->at(makeKey<int>("key1"s)) == 3);
700 BOOST_TEST(demoMap->at(makeKey<double>("key6"s)) == 42);
701 BOOST_TEST(demoMap->at(makeKey<SimpleStorable>("key2"s)) == SimpleStorable());
702 BOOST_TEST(demoMap->at(makeKey<std::string>("key3"s)) == "Test value"s);
703 BOOST_TEST(demoMap->at(makeKey<std::string>("key4"s)) == "This is some text"s);
704 BOOST_TEST(demoMap->at(makeKey<std::string>("key5"s)) == message);
705}
706
707BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestErase, GenericMapFactory) {
708 using namespace std::string_literals;
709
710 static GenericMapFactory const factory;
711 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
712
713 demoMap->insert(makeKey<int>("Ultimate answer"s), 42);
714 BOOST_TEST_REQUIRE(demoMap->size() == 1);
715
716 BOOST_TEST(demoMap->erase(makeKey<std::string>("Ultimate answer"s)) == false);
717 BOOST_TEST(demoMap->size() == 1);
718 BOOST_TEST(demoMap->erase(makeKey<int>("Ultimate answer"s)) == true);
719 BOOST_TEST(demoMap->size() == 0);
720}
721
722BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestInsertEraseInsert, GenericMapFactory) {
723 using namespace std::string_literals;
724
725 static GenericMapFactory const factory;
726 std::unique_ptr<MutableGenericMap<std::string>> demoMap = factory.makeMutableGenericMap();
727
728 BOOST_TEST_REQUIRE(demoMap->empty());
729
730 BOOST_TEST(demoMap->insert(makeKey<int>("Ultimate answer"s), 42) == true);
731 BOOST_TEST(demoMap->insert(makeKey<int>("OK"s), 200) == true);
732 BOOST_TEST(demoMap->erase(makeKey<int>("Ultimate answer"s)) == true);
733 BOOST_TEST(demoMap->insert(makeKey<double>("Ultimate answer"s), 3.1415927) == true);
734
735 BOOST_TEST(!demoMap->empty());
736 BOOST_TEST(demoMap->size() == 2);
737 BOOST_TEST(demoMap->contains("OK"s));
738 BOOST_TEST(!demoMap->contains(makeKey<int>("Ultimate answer"s)));
739 BOOST_TEST(demoMap->contains(makeKey<double>("Ultimate answer"s)));
740 BOOST_TEST(demoMap->at(makeKey<double>("Ultimate answer"s)) == 3.1415927);
741}
742
750template <class GenericMapFactory>
751void addGenericMapTestCases(boost::unit_test::test_suite* const suite) {
752 using factories = boost::mpl::list<GenericMapFactory>;
753
754 suite->add(BOOST_TEST_CASE_TEMPLATE(TestConstAt, factories));
755 suite->add(BOOST_TEST_CASE_TEMPLATE(TestAt, factories));
756 suite->add(BOOST_TEST_CASE_TEMPLATE(TestEquals, factories));
757 suite->add(BOOST_TEST_CASE_TEMPLATE(TestSize, factories));
758 suite->add(BOOST_TEST_CASE_TEMPLATE(TestWeakContains, factories));
759 suite->add(BOOST_TEST_CASE_TEMPLATE(TestContains, factories));
760 suite->add(BOOST_TEST_CASE_TEMPLATE(TestKeys, factories));
761 suite->add(BOOST_TEST_CASE_TEMPLATE(TestKeyOrder, factories));
762 suite->add(BOOST_TEST_CASE_TEMPLATE(TestConstVisitor, factories));
763 suite->add(BOOST_TEST_CASE_TEMPLATE(TestModifyingVoidVisitor, factories));
764 suite->add(BOOST_TEST_CASE_TEMPLATE(TestModifyingReturningVisitor, factories));
765}
766
776template <class GenericMapFactory>
777void addMutableGenericMapTestCases(boost::unit_test::test_suite* const suite) {
778 using factories = boost::mpl::list<GenericMapFactory>;
779
780 addGenericMapTestCases<GenericMapFactory>(suite);
781
782 suite->add(BOOST_TEST_CASE_TEMPLATE(TestMutableEquals, factories));
783 suite->add(BOOST_TEST_CASE_TEMPLATE(TestMutableSize, factories));
784 suite->add(BOOST_TEST_CASE_TEMPLATE(TestClear, factories));
785 suite->add(BOOST_TEST_CASE_TEMPLATE(TestClearIdempotent, factories));
786 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertInt, factories));
787 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertString, factories));
788 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertStorable, factories));
789 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInterleavedInserts, factories));
790 suite->add(BOOST_TEST_CASE_TEMPLATE(TestErase, factories));
791 suite->add(BOOST_TEST_CASE_TEMPLATE(TestInsertEraseInsert, factories));
792}
793
802template <class GenericMapFactory>
804 addGenericMapTestCases<GenericMapFactory>(&(boost::unit_test::framework::master_test_suite()));
805}
806
816template <class GenericMapFactory>
818 addMutableGenericMapTestCases<GenericMapFactory>(&(boost::unit_test::framework::master_test_suite()));
819}
820
821} // namespace test
822} // namespace typehandling
823} // namespace afw
824} // namespace lsst
825
826#endif
table::Key< std::string > object
Definition VisitInfo.cc:232
Interface supporting iteration over heterogenous containers.
Definition Storable.h:58
Abstract factory that creates GenericMap and MutableGenericMap instances as needed.
Definition test.h:139
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 addMutableGenericMapTestCases()
Create generic test cases for a specific MutableGenericMap implementation.
Definition test.h:817
void addGenericMapTestCases()
Create generic test cases for a specific GenericMap implementation.
Definition test.h:803
BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestConstAt, GenericMapFactory)
Definition test.h:160
constexpr Key< K, V > makeKey(K const &id)
Factory function for Key, to enable type parameter inference.
Definition Key.h:173
T push_back(T... args)
T size(T... args)
T str(T... args)
T to_string(T... args)