lsst.afw
g3a5ebb7d8a+28b83bf6a5
Toggle main menu visibility
Loading...
Searching...
No Matches
include
lsst
afw
typehandling
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
44
#include "
lsst/afw/typehandling/GenericMap.h
"
45
#include "
lsst/afw/typehandling/Storable.h
"
46
47
namespace
lsst
{
48
namespace
afw {
49
namespace
typehandling {
50
namespace
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
59
namespace
{
60
class
SimpleStorable :
public
Storable
{
61
friend
class
ComplexStorable;
62
public
:
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
74
class
ComplexStorable final :
public
SimpleStorable {
75
public
:
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
}
106
private
:
107
double
storage;
108
};
109
110
template
<
typename
T>
111
std::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
120
auto
const
KEY0 =
makeKey<bool>
(0);
121
bool
const
VALUE0 =
true
;
122
auto
const
KEY1 =
makeKey<int>
(1);
123
int
const
VALUE1 = 42;
124
auto
const
KEY2 =
makeKey<double>
(2);
125
int
const
VALUE2 = VALUE1;
126
auto
const
KEY3 =
makeKey<std::string>
(3);
127
std::string
const
VALUE3 =
"How many roads must a man walk down?"
;
128
auto
const
KEY4 =
makeKey<std::shared_ptr<SimpleStorable const>
>(4);
129
auto
const
VALUE4 = SimpleStorable();
130
auto
const
KEY5 =
makeKey<ComplexStorable>
(5);
131
auto
const
VALUE5 = ComplexStorable(-100.0);
132
auto
const
KEY6 =
makeKey<std::shared_ptr<Storable const>
>(6);
133
auto
const
VALUE6 =
std::shared_ptr<Storable const>
();
134
}
// namespace
135
139
class
GenericFactory
{
140
public
:
141
virtual
~GenericFactory
() =
default
;
142
154
virtual
std::unique_ptr<GenericMap<int>
>
makeGenericMap
()
const
= 0;
155
157
virtual
std::unique_ptr<MutableGenericMap<std::string>
>
makeMutableGenericMap
()
const
= 0;
158
};
159
160
BOOST_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
173
BOOST_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
215
BOOST_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
225
BOOST_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
};
252
std::vector<std::string>
expected;
253
for
(
int
key : mapKeys) {
254
expected.
push_back
(bruteForcePrinter(key));
255
}
256
257
// Test local class that returns void
258
class
{
259
public
:
260
std::vector<std::string>
results;
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
283
std::vector<std::string>
strings =
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
292
BOOST_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
330
BOOST_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
391
BOOST_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
430
BOOST_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
438
BOOST_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
456
BOOST_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
471
BOOST_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
500
BOOST_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
511
BOOST_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
521
BOOST_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
530
BOOST_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
544
BOOST_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
570
BOOST_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
595
BOOST_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
621
BOOST_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
646
BOOST_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
679
BOOST_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
707
BOOST_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
722
BOOST_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
750
template
<
class
GenericMapFactory>
751
void
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
776
template
<
class
GenericMapFactory>
777
void
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
802
template
<
class
GenericMapFactory>
803
inline
void
addGenericMapTestCases
() {
804
addGenericMapTestCases<GenericMapFactory>
(&(boost::unit_test::framework::master_test_suite()));
805
}
806
816
template
<
class
GenericMapFactory>
817
inline
void
addMutableGenericMapTestCases
() {
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
GenericMap.h
Storable.h
std::string
std::stringstream
lsst::afw::typehandling::Storable
Interface supporting iteration over heterogenous containers.
Definition
Storable.h:58
lsst::afw::typehandling::test::GenericFactory
Abstract factory that creates GenericMap and MutableGenericMap instances as needed.
Definition
test.h:139
lsst::afw::typehandling::test::GenericFactory::makeGenericMap
virtual std::unique_ptr< GenericMap< int > > makeGenericMap() const =0
Create a map containing the following state:
lsst::afw::typehandling::test::GenericFactory::makeMutableGenericMap
virtual std::unique_ptr< MutableGenericMap< std::string > > makeMutableGenericMap() const =0
Create an empty map.
lsst::afw::typehandling::test::GenericFactory::~GenericFactory
virtual ~GenericFactory()=default
lsst::pex::exceptions::OutOfRangeError
exceptions.h
std::hash
std::invalid_argument
std::make_shared
T make_shared(T... args)
lsst::afw::typehandling::test
Definition
test.h:50
lsst::afw::typehandling::test::addMutableGenericMapTestCases
void addMutableGenericMapTestCases()
Create generic test cases for a specific MutableGenericMap implementation.
Definition
test.h:817
lsst::afw::typehandling::test::addGenericMapTestCases
void addGenericMapTestCases()
Create generic test cases for a specific GenericMap implementation.
Definition
test.h:803
lsst::afw::typehandling::test::BOOST_TEST_CASE_TEMPLATE_FUNCTION
BOOST_TEST_CASE_TEMPLATE_FUNCTION(TestConstAt, GenericMapFactory)
Definition
test.h:160
lsst::afw::typehandling::makeKey
constexpr Key< K, V > makeKey(K const &id)
Factory function for Key, to enable type parameter inference.
Definition
Key.h:173
lsst
std::static_pointer_cast
T static_pointer_cast(T... args)
std::vector::push_back
T push_back(T... args)
std::set
std::shared_ptr
std::vector::size
T size(T... args)
std::size_t
std::stringstream::str
T str(T... args)
std::to_string
T to_string(T... args)
std::unique_ptr
std::vector
Generated on
for lsst.afw by
1.17.0