27struct ThrowOnMoveOrSwap
29 ThrowOnMoveOrSwap() =
default;
30 ThrowOnMoveOrSwap (ThrowOnMoveOrSwap&&) {
throw std::bad_alloc{}; }
32static void swap (ThrowOnMoveOrSwap&, ThrowOnMoveOrSwap&) {
throw std::bad_alloc{}; }
34class OptionalUnitTest final :
public UnitTest
37 OptionalUnitTest() :
UnitTest (
"Optional", UnitTestCategories::containers) {}
41 beginTest (
"Default-constructed optional is invalid");
47 beginTest (
"Constructing from Nullopt is invalid");
49 Optional<int> o (nullopt);
53 beginTest (
"Optional constructed from value is valid");
60 using Ptr = std::shared_ptr<int>;
61 const auto makePtr = [] {
return std::make_shared<int>(); };
63 beginTest (
"Constructing from a moved optional calls appropriate member functions");
66 Optional<Ptr> original (ptr);
67 expect (ptr.use_count() == 2);
68 auto other = std::move (original);
70 expect (original.hasValue());
72 expect (ptr.use_count() == 2);
75 beginTest (
"Moving an empty optional to a populated one destroys the instance");
78 Optional<Ptr> original (ptr);
79 expect (ptr.use_count() == 2);
80 original = Optional<Ptr>();
81 expect (ptr.use_count() == 1);
84 beginTest (
"Copying an empty optional to a populated one destroys the instance");
87 Optional<Ptr> original (ptr);
88 expect (ptr.use_count() == 2);
91 expect (ptr.use_count() == 1);
94 beginTest (
"Moving a populated optional calls appropriate member functions");
99 Optional<Ptr> aOpt (a);
100 Optional<Ptr> bOpt (b);
102 expect (a.use_count() == 2);
103 expect (b.use_count() == 2);
105 aOpt = std::move (bOpt);
110 expect (a.use_count() == 1);
111 expect (b.use_count() == 2);
114 beginTest (
"Copying a populated optional calls appropriate member functions");
119 Optional<Ptr> aOpt (a);
120 Optional<Ptr> bOpt (b);
122 expect (a.use_count() == 2);
123 expect (b.use_count() == 2);
130 expect (a.use_count() == 1);
131 expect (b.use_count() == 3);
134 beginTest (
"Moving an empty optional to an empty one does nothing");
136 Optional<Ptr> original;
137 original = Optional<Ptr>();
138 expect (! original.hasValue());
141 beginTest (
"Copying an empty optional to an empty one does nothing");
143 Optional<Ptr> original;
146 expect (! original.hasValue());
147 expect (! empty.hasValue());
150 beginTest (
"Moving a populated optional calls appropriate member functions");
154 Optional<Ptr> aOpt (a);
157 expect (a.use_count() == 2);
159 empty = std::move (aOpt);
161 expect (empty.hasValue());
164 expect (a.use_count() == 2);
167 beginTest (
"Copying a populated optional calls appropriate member functions");
171 Optional<Ptr> aOpt (a);
174 expect (a.use_count() == 2);
179 expect (empty.hasValue());
181 expect (a.use_count() == 3);
186 ThrowOnCopy() =
default;
189 ThrowOnCopy (
const ThrowOnCopy&)
192 throw std::bad_alloc{};
196 ThrowOnCopy& operator= (
const ThrowOnCopy&)
199 throw std::bad_alloc{};
202 ThrowOnCopy (ThrowOnCopy&&) noexcept = default;
203 ThrowOnCopy& operator= (ThrowOnCopy&&) noexcept = default;
205 ~ThrowOnCopy() = default;
210 beginTest (
"Strong exception safety is maintained when forwarding over empty object");
213 Optional<ThrowOnCopy> a;
220 catch (
const std::bad_alloc&)
226 expect (! a.hasValue());
229 beginTest (
"Weak exception safety is maintained when forwarding over populated object");
232 Optional<ThrowOnCopy> a = ThrowOnCopy();
240 catch (
const std::bad_alloc&)
246 expect (a.hasValue());
247 expect (a->value == -100);
250 beginTest (
"Strong exception safety is maintained when copying over empty object");
253 Optional<ThrowOnCopy> a;
257 Optional<ThrowOnCopy> t = ThrowOnCopy{};
260 catch (
const std::bad_alloc&)
266 expect (! a.hasValue());
269 beginTest (
"Exception safety of contained type is maintained when copying over populated object");
272 Optional<ThrowOnCopy> a = ThrowOnCopy();
277 Optional<ThrowOnCopy> t = ThrowOnCopy{};
280 catch (
const std::bad_alloc&)
286 expect (a.hasValue());
287 expect (a->value == -100);
290 beginTest (
"Assigning from nullopt clears the instance");
292 auto ptr = makePtr();
293 Optional<Ptr> a (ptr);
294 expect (ptr.use_count() == 2);
296 expect (ptr.use_count() == 1);
300 struct Bar final :
public Foo {};
302 beginTest (
"Can be constructed from compatible type");
304 Optional<std::shared_ptr<Foo>> opt { std::make_shared<Bar>() };
307 beginTest (
"Can be assigned from compatible type");
309 Optional<std::shared_ptr<Foo>> opt;
310 opt = std::make_shared<Bar>();
313 beginTest (
"Can copy from compatible type");
315 auto ptr = std::make_shared<Bar>();
316 Optional<std::shared_ptr<Bar>> bar (ptr);
317 Optional<std::shared_ptr<Foo>> foo (bar);
318 expect (ptr.use_count() == 3);
321 beginTest (
"Can move from compatible type");
323 auto ptr = std::make_shared<Bar>();
324 Optional<std::shared_ptr<Foo>> foo (Optional<std::shared_ptr<Bar>> { ptr });
325 expect (ptr.use_count() == 2);
328 beginTest (
"Can copy assign from compatible type");
330 auto ptr = std::make_shared<Bar>();
331 Optional<std::shared_ptr<Bar>> bar (ptr);
332 Optional<std::shared_ptr<Foo>> foo;
334 expect (ptr.use_count() == 3);
337 beginTest (
"Can move assign from compatible type");
339 auto ptr = std::make_shared<Bar>();
340 Optional<std::shared_ptr<Foo>> foo;
341 foo = Optional<std::shared_ptr<Bar>> (ptr);
342 expect (ptr.use_count() == 2);
345 beginTest (
"An exception thrown during emplace leaves the optional without a value");
347 Optional<ThrowOnCopy> opt { ThrowOnCopy{} };
355 catch (
const std::bad_alloc&)
361 expect (! opt.hasValue());
364 beginTest (
"Swap does nothing to two empty optionals");
367 expect (! a.hasValue());
368 expect (! b.hasValue());
372 expect (! a.hasValue());
373 expect (! b.hasValue());
376 beginTest (
"Swap transfers ownership if one optional contains a value");
380 Optional<Ptr> a, b = ptr;
381 expect (! a.hasValue());
382 expect (b.hasValue());
383 expect (ptr.use_count() == 2);
387 expect (a.hasValue());
388 expect (! b.hasValue());
389 expect (ptr.use_count() == 2);
393 auto ptr = makePtr();
394 Optional<Ptr> a = ptr, b;
395 expect (a.hasValue());
396 expect (! b.hasValue());
397 expect (ptr.use_count() == 2);
401 expect (! a.hasValue());
402 expect (b.hasValue());
403 expect (ptr.use_count() == 2);
407 beginTest (
"Swap calls std::swap to swap two populated optionals");
409 auto x = makePtr(), y = makePtr();
410 Optional<Ptr> a = x, b = y;
411 expect (a.hasValue());
412 expect (b.hasValue());
413 expect (x.use_count() == 2);
414 expect (y.use_count() == 2);
420 expect (a.hasValue());
421 expect (b.hasValue());
422 expect (x.use_count() == 2);
423 expect (y.use_count() == 2);
428 beginTest (
"An exception thrown during a swap leaves both objects in the previous populated state");
431 Optional<ThrowOnMoveOrSwap> a, b;
434 expect (a.hasValue());
435 expect (! b.hasValue());
443 catch (
const std::bad_alloc&)
449 expect (a.hasValue());
450 expect (! b.hasValue());
454 Optional<ThrowOnMoveOrSwap> a, b;
457 expect (! a.hasValue());
458 expect (b.hasValue());
466 catch (
const std::bad_alloc&)
472 expect (! a.hasValue());
473 expect (b.hasValue());
477 Optional<ThrowOnMoveOrSwap> a, b;
481 expect (a.hasValue());
482 expect (b.hasValue());
490 catch (
const std::bad_alloc&)
496 expect (a.hasValue());
497 expect (b.hasValue());
501 beginTest (
"Relational tests");
503 expect (Optional<int> (1) == Optional<int> (1));
504 expect (Optional<int>() == Optional<int>());
505 expect (! (Optional<int> (1) == Optional<int>()));
506 expect (! (Optional<int>() == Optional<int> (1)));
507 expect (! (Optional<int> (1) == Optional<int> (2)));
509 expect (Optional<int> (1) != Optional<int> (2));
510 expect (! (Optional<int>() != Optional<int>()));
511 expect (Optional<int> (1) != Optional<int>());
512 expect (Optional<int>() != Optional<int> (1));
513 expect (! (Optional<int> (1) != Optional<int> (1)));
515 expect (Optional<int>() < Optional<int> (1));
516 expect (! (Optional<int> (1) < Optional<int>()));
517 expect (! (Optional<int>() < Optional<int>()));
518 expect (Optional<int> (1) < Optional<int> (2));
520 expect (Optional<int>() <= Optional<int> (1));
521 expect (! (Optional<int> (1) <= Optional<int>()));
522 expect (Optional<int>() <= Optional<int>());
523 expect (Optional<int> (1) <= Optional<int> (2));
525 expect (! (Optional<int>() > Optional<int> (1)));
526 expect (Optional<int> (1) > Optional<int>());
527 expect (! (Optional<int>() > Optional<int>()));
528 expect (! (Optional<int> (1) > Optional<int> (2)));
530 expect (! (Optional<int>() >= Optional<int> (1)));
531 expect (Optional<int> (1) >= Optional<int>());
532 expect (Optional<int>() >= Optional<int>());
533 expect (! (Optional<int> (1) >= Optional<int> (2)));
535 expect (Optional<int>() == nullopt);
536 expect (! (Optional<int> (1) == nullopt));
537 expect (nullopt == Optional<int>());
538 expect (! (nullopt == Optional<int> (1)));
540 expect (! (Optional<int>() != nullopt));
541 expect (Optional<int> (1) != nullopt);
542 expect (! (nullopt != Optional<int>()));
543 expect (nullopt != Optional<int> (1));
545 expect (! (Optional<int>() < nullopt));
546 expect (! (Optional<int> (1) < nullopt));
548 expect (! (nullopt < Optional<int>()));
549 expect (nullopt < Optional<int> (1));
551 expect (Optional<int>() <= nullopt);
552 expect (! (Optional<int> (1) <= nullopt));
554 expect (nullopt <= Optional<int>());
555 expect (nullopt <= Optional<int> (1));
557 expect (! (Optional<int>() > nullopt));
558 expect (Optional<int> (1) > nullopt);
560 expect (! (nullopt > Optional<int>()));
561 expect (! (nullopt > Optional<int> (1)));
563 expect (Optional<int>() >= nullopt);
564 expect (Optional<int> (1) >= nullopt);
566 expect (nullopt >= Optional<int>());
567 expect (! (nullopt >= Optional<int> (1)));
569 expect (! (Optional<int>() == 5));
570 expect (! (Optional<int> (1) == 5));
571 expect (Optional<int> (1) == 1);
572 expect (! (5 == Optional<int>()));
573 expect (! (5 == Optional<int> (1)));
574 expect (1 == Optional<int> (1));
576 expect (Optional<int>() != 5);
577 expect (Optional<int> (1) != 5);
578 expect (! (Optional<int> (1) != 1));
579 expect (5 != Optional<int>());
580 expect (5 != Optional<int> (1));
581 expect (! (1 != Optional<int> (1)));
583 expect (Optional<int>() < 5);
584 expect (Optional<int> (1) < 5);
585 expect (! (Optional<int> (1) < 1));
586 expect (! (Optional<int> (1) < 0));
588 expect (! (5 < Optional<int>()));
589 expect (! (5 < Optional<int> (1)));
590 expect (! (1 < Optional<int> (1)));
591 expect (0 < Optional<int> (1));
593 expect (Optional<int>() <= 5);
594 expect (Optional<int> (1) <= 5);
595 expect (Optional<int> (1) <= 1);
596 expect (! (Optional<int> (1) <= 0));
598 expect (! (5 <= Optional<int>()));
599 expect (! (5 <= Optional<int> (1)));
600 expect (1 <= Optional<int> (1));
601 expect (0 <= Optional<int> (1));
603 expect (! (Optional<int>() > 5));
604 expect (! (Optional<int> (1) > 5));
605 expect (! (Optional<int> (1) > 1));
606 expect (Optional<int> (1) > 0);
608 expect (5 > Optional<int>());
609 expect (5 > Optional<int> (1));
610 expect (! (1 > Optional<int> (1)));
611 expect (! (0 > Optional<int> (1)));
613 expect (! (Optional<int>() >= 5));
614 expect (! (Optional<int> (1) >= 5));
615 expect (Optional<int> (1) >= 1);
616 expect (Optional<int> (1) >= 0);
618 expect (5 >= Optional<int>());
619 expect (5 >= Optional<int> (1));
620 expect (1 >= Optional<int> (1));
621 expect (! (0 >= Optional<int> (1)));
626static OptionalUnitTest optionalUnitTest;
void expectEquals(ValueType actual, ValueType expected, String failureMessage=String())
UnitTest(const String &name, const String &category=String())
void beginTest(const String &testName)
void expect(bool testResult, const String &failureMessage=String())