1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <memory>
6 
7 #include <lib/fit/nullable.h>
8 #include <unittest/unittest.h>
9 
10 namespace {
11 
12 struct null_comparable_struct {
13     int value = 0;
14 
operator ==__anon7307f0470111::null_comparable_struct15     constexpr bool operator==(decltype(nullptr)) const { return value == -1; }
16 };
17 
18 struct nullable_struct {
19     int value = 0;
20 
21     constexpr nullable_struct() = default;
nullable_struct__anon7307f0470111::nullable_struct22     constexpr nullable_struct(int value)
23         : value(value) {}
nullable_struct__anon7307f0470111::nullable_struct24     constexpr explicit nullable_struct(decltype(nullptr))
25         : value(-1) {}
26     nullable_struct(const nullable_struct& other) = default;
27     nullable_struct(nullable_struct&& other) = default;
28 
get__anon7307f0470111::nullable_struct29     constexpr int get() const { return value; }
increment__anon7307f0470111::nullable_struct30     constexpr int increment() { return ++value; }
31 
operator ==__anon7307f0470111::nullable_struct32     constexpr bool operator==(decltype(nullptr)) const { return value == -1; }
operator ==__anon7307f0470111::nullable_struct33     constexpr bool operator==(const nullable_struct& other) const { return value == other.value; }
operator !=__anon7307f0470111::nullable_struct34     constexpr bool operator!=(const nullable_struct& other) const { return value != other.value; }
35 
36     nullable_struct& operator=(const nullable_struct& other) = default;
37     nullable_struct& operator=(nullable_struct&& other) = default;
operator =__anon7307f0470111::nullable_struct38     nullable_struct& operator=(decltype(nullptr)) {
39         value = -1;
40         return *this;
41     }
42 };
43 
44 struct non_nullable_struct_missing_constructor {
45     int value = 0;
46 
47     constexpr non_nullable_struct_missing_constructor() = default;
operator =__anon7307f0470111::non_nullable_struct_missing_constructor48     constexpr non_nullable_struct_missing_constructor& operator=(decltype(nullptr)) {
49         value = -1;
50         return *this;
51     }
52 
operator ==__anon7307f0470111::non_nullable_struct_missing_constructor53     constexpr bool operator==(decltype(nullptr)) const { return value == -1; }
54 };
55 
56 struct non_nullable_struct_missing_assignment {
57     int value = 0;
58 
59     constexpr non_nullable_struct_missing_assignment() = default;
non_nullable_struct_missing_assignment__anon7307f0470111::non_nullable_struct_missing_assignment60     constexpr explicit non_nullable_struct_missing_assignment(decltype(nullptr))
61         : value(-1) {}
62 
operator ==__anon7307f0470111::non_nullable_struct_missing_assignment63     constexpr bool operator==(decltype(nullptr)) const { return value == -1; }
64 };
65 
66 struct non_nullable_struct_missing_comparator {
67     int value = 0;
68 
69     constexpr non_nullable_struct_missing_comparator() = default;
non_nullable_struct_missing_comparator__anon7307f0470111::non_nullable_struct_missing_comparator70     constexpr explicit non_nullable_struct_missing_comparator(decltype(nullptr))
71         : value(-1) {}
72 
operator =__anon7307f0470111::non_nullable_struct_missing_comparator73     non_nullable_struct_missing_comparator& operator=(decltype(nullptr)) {
74         value = -1;
75         return *this;
76     }
77 };
78 
79 struct non_nullable_struct {
80     int value = 0;
81 
82     constexpr non_nullable_struct() = default;
non_nullable_struct__anon7307f0470111::non_nullable_struct83     constexpr non_nullable_struct(int value)
84         : value(value) {}
85     non_nullable_struct(const non_nullable_struct& other) = default;
86     non_nullable_struct(non_nullable_struct&& other) = default;
87 
get__anon7307f0470111::non_nullable_struct88     constexpr int get() const { return value; }
increment__anon7307f0470111::non_nullable_struct89     constexpr int increment() { return ++value; }
90 
operator ==__anon7307f0470111::non_nullable_struct91     constexpr bool operator==(const non_nullable_struct& other) const { return value == other.value; }
operator !=__anon7307f0470111::non_nullable_struct92     constexpr bool operator!=(const non_nullable_struct& other) const { return value != other.value; }
93 
94     non_nullable_struct& operator=(const non_nullable_struct& other) = default;
95     non_nullable_struct& operator=(non_nullable_struct&& other) = default;
96 };
97 
98 struct non_nullable_struct_with_non_bool_comparator {
99     int value = 0;
100 
operator ==__anon7307f0470111::non_nullable_struct_with_non_bool_comparator101     constexpr void operator==(decltype(nullptr)) const {}
102 };
103 
104 // Some values of type void* that we can compare.
105 int item_a = 0;
106 int item_b = 0;
107 constexpr void* void_a = &item_a;
108 constexpr void* void_b = &item_b;
109 constexpr void* void_null = nullptr;
110 
111 // Function and lambda types are never nullable.
function(float,bool)112 void function(float, bool) {}
__anon7307f0470202(float, bool) 113 auto lambda = [](float, bool) { return 0; };
114 
115 // Test is_comparable_with_null.
116 static_assert(!fit::is_comparable_with_null<void>::value, "");
117 static_assert(!fit::is_comparable_with_null<int>::value, "");
118 static_assert(!fit::is_comparable_with_null<non_nullable_struct>::value, "");
119 static_assert(!fit::is_comparable_with_null<non_nullable_struct_missing_comparator>::value, "");
120 static_assert(fit::is_comparable_with_null<decltype(nullptr)>::value, "");
121 static_assert(fit::is_comparable_with_null<void*>::value, "");
122 static_assert(fit::is_comparable_with_null<null_comparable_struct>::value, "");
123 static_assert(fit::is_comparable_with_null<nullable_struct>::value, "");
124 static_assert(fit::is_comparable_with_null<fit::nullable<int>>::value, "");
125 static_assert(fit::is_comparable_with_null<fit::nullable<void*>>::value, "");
126 static_assert(fit::is_comparable_with_null<std::unique_ptr<int>>::value, "");
127 static_assert(fit::is_comparable_with_null<decltype(function)>::value, "");
128 static_assert(fit::is_comparable_with_null<decltype(&function)>::value, "");
129 static_assert(fit::is_comparable_with_null<decltype(lambda)>::value, "");
130 static_assert(fit::is_comparable_with_null<decltype(&lambda)>::value, "");
131 
132 // Test is_nullable.
133 static_assert(!fit::is_nullable<void>::value, "");
134 static_assert(!fit::is_nullable<int>::value, "");
135 static_assert(!fit::is_nullable<non_nullable_struct>::value, "");
136 static_assert(!fit::is_nullable<non_nullable_struct_missing_constructor>::value, "");
137 static_assert(!fit::is_nullable<non_nullable_struct_missing_assignment>::value, "");
138 static_assert(!fit::is_nullable<non_nullable_struct_missing_comparator>::value, "");
139 static_assert(!fit::is_nullable<null_comparable_struct>::value, "");
140 static_assert(fit::is_nullable<decltype(nullptr)>::value, "");
141 static_assert(fit::is_nullable<void*>::value, "");
142 static_assert(fit::is_nullable<nullable_struct>::value, "");
143 static_assert(fit::is_nullable<fit::nullable<int>>::value, "");
144 static_assert(fit::is_nullable<fit::nullable<void*>>::value, "");
145 static_assert(fit::is_nullable<std::unique_ptr<int>>::value, "");
146 static_assert(!fit::is_nullable<decltype(function)>::value, "");
147 static_assert(fit::is_nullable<decltype(&function)>::value, "");
148 static_assert(!fit::is_nullable<decltype(lambda)>::value, "");
149 static_assert(fit::is_nullable<decltype(&lambda)>::value, "");
150 
151 // Test is_null.
152 static_assert(fit::is_null(nullptr), "");
153 static_assert(fit::is_null(void_null), "");
154 static_assert(fit::is_null(fit::nullable<void*>(nullptr)), "");
155 static_assert(!fit::is_null(void_a), "");
156 static_assert(!fit::is_null(fit::nullable<void*>(void_a)), "");
157 static_assert(!fit::is_null(5), "");
158 static_assert(!fit::is_null(function), "");
159 static_assert(!fit::is_null(&function), "");
160 static_assert(!fit::is_null(lambda), "");
161 static_assert(!fit::is_null(&lambda), "");
162 
163 // Test nullable::value_type.
164 static_assert(std::is_same<int, fit::nullable<int>::value_type>::value, "");
165 static_assert(std::is_same<void*, fit::nullable<void*>::value_type>::value, "");
166 static_assert(std::is_same<decltype(&function),
167                            fit::nullable<decltype(&function)>::value_type>::value,
168               "");
169 
170 // Test constexpr comparators for nullable.
171 static_assert(!fit::nullable<void*>(), "");
172 static_assert(!fit::nullable<void*>().has_value(), "");
173 static_assert(fit::nullable<void*>() == nullptr, "");
174 static_assert(!fit::nullable<void*>(nullptr), "");
175 static_assert(!fit::nullable<void*>(nullptr).has_value(), "");
176 static_assert(!fit::nullable<void*>(void_null), "");
177 static_assert(!fit::nullable<void*>(void_null).has_value(), "");
178 static_assert(fit::nullable<void*>(void_a), "");
179 static_assert(fit::nullable<void*>(void_a).has_value(), "");
180 
181 static_assert(fit::nullable<void*>(void_null) == nullptr, "");
182 static_assert(nullptr == fit::nullable<void*>(void_null), "");
183 static_assert(!(fit::nullable<void*>(void_a) == nullptr), "");
184 static_assert(!(nullptr == fit::nullable<void*>(void_a)), "");
185 
186 static_assert(!(fit::nullable<void*>(void_null) != nullptr), "");
187 static_assert(!(nullptr != fit::nullable<void*>(void_null)), "");
188 static_assert(fit::nullable<void*>(void_a) != nullptr, "");
189 static_assert(nullptr != fit::nullable<void*>(void_a), "");
190 
191 static_assert(fit::nullable<void*>(void_a) == fit::nullable<void*>(void_a), "");
192 static_assert(fit::nullable<void*>(void_null) == fit::nullable<void*>(void_null), "");
193 static_assert(!(fit::nullable<void*>(void_a) == fit::nullable<void*>(void_b)), "");
194 static_assert(!(fit::nullable<void*>(void_a) == fit::nullable<void*>(void_null)), "");
195 static_assert(!(fit::nullable<void*>(void_null) == fit::nullable<void*>(void_a)), "");
196 
197 static_assert(!(fit::nullable<void*>(void_a) != fit::nullable<void*>(void_a)), "");
198 static_assert(!(fit::nullable<void*>(void_null) != fit::nullable<void*>(void_null)), "");
199 static_assert(fit::nullable<void*>(void_a) != fit::nullable<void*>(void_b), "");
200 static_assert(fit::nullable<void*>(void_a) != fit::nullable<void*>(void_null), "");
201 static_assert(fit::nullable<void*>(void_null) != fit::nullable<void*>(void_a), "");
202 
203 static_assert(fit::nullable<void*>(void_a) == void_a, "");
204 static_assert(fit::nullable<void*>(void_null) == void_null, "");
205 static_assert(!(fit::nullable<void*>(void_a) == void_b), "");
206 static_assert(!(fit::nullable<void*>(void_a) == void_null), "");
207 static_assert(!(fit::nullable<void*>(void_null) == void_a), "");
208 
209 static_assert(void_a == fit::nullable<void*>(void_a), "");
210 static_assert(void_null == fit::nullable<void*>(void_null), "");
211 static_assert(!(void_a == fit::nullable<void*>(void_b)), "");
212 static_assert(!(void_a == fit::nullable<void*>(void_null)), "");
213 static_assert(!(void_null == fit::nullable<void*>(void_a)), "");
214 
215 static_assert(!(fit::nullable<void*>(void_a) != void_a), "");
216 static_assert(!(fit::nullable<void*>(void_null) != void_null), "");
217 static_assert(fit::nullable<void*>(void_a) != void_b, "");
218 static_assert(fit::nullable<void*>(void_a) != void_null, "");
219 static_assert(fit::nullable<void*>(void_null) != void_a, "");
220 
221 static_assert(!(void_a != fit::nullable<void*>(void_a)), "");
222 static_assert(!(void_null != fit::nullable<void*>(void_null)), "");
223 static_assert(void_a != fit::nullable<void*>(void_b), "");
224 static_assert(void_a != fit::nullable<void*>(void_null), "");
225 static_assert(void_null != fit::nullable<void*>(void_a), "");
226 
227 // TODO(US-90): Unfortunately fit::optional is not a literal type unlike
228 // std::optional so values of type fit::nullable<T> when T is not nullable
229 // are also not literal.  Once we fix fit::optional to allow literal types,
230 // we can add constexpr tests for those types.
231 // e.g. fit::nullable<int>.
232 
is_null()233 bool is_null() {
234     BEGIN_TEST;
235 
236     EXPECT_TRUE(fit::is_null(nullptr));
237 
238     null_comparable_struct ncf;
239     EXPECT_FALSE(fit::is_null(ncf));
240 
241     null_comparable_struct nct{-1};
242     EXPECT_TRUE(fit::is_null(nct));
243 
244     nullable_struct nf;
245     EXPECT_FALSE(fit::is_null(nf));
246 
247     nullable_struct nt(nullptr);
248     EXPECT_TRUE(fit::is_null(nt));
249 
250     fit::nullable<int> nif(1);
251     EXPECT_FALSE(fit::is_null(nif));
252 
253     fit::nullable<int> nit(nullptr);
254     EXPECT_TRUE(fit::is_null(nit));
255 
256     fit::nullable<void*> npf(&nit);
257     EXPECT_FALSE(fit::is_null(npf));
258 
259     fit::nullable<void*> npt(nullptr);
260     EXPECT_TRUE(fit::is_null(npt));
261 
262     non_nullable_struct nn;
263     EXPECT_FALSE(fit::is_null(nn));
264 
265     non_nullable_struct_with_non_bool_comparator nbn;
266     EXPECT_FALSE(fit::is_null(nbn));
267 
268     END_TEST;
269 }
270 
271 template <typename T>
272 struct traits;
273 
274 template <>
275 struct traits<nullable_struct> {
276     static constexpr nullable_struct a{42};
277     static constexpr nullable_struct b{55};
278     static constexpr nullable_struct null{-1};
279 };
280 
281 template <>
282 struct traits<non_nullable_struct> {
283     static constexpr non_nullable_struct a{42};
284     static constexpr non_nullable_struct b{55};
285     static constexpr nullptr_t null = nullptr;
286 };
287 
288 template <typename T>
construct_without_value()289 bool construct_without_value() {
290     BEGIN_TEST;
291 
292     fit::nullable<T> opt;
293     EXPECT_FALSE(opt.has_value());
294     EXPECT_FALSE(!!opt);
295 
296     EXPECT_EQ(42, opt.value_or(traits<T>::a).value);
297 
298     opt.reset();
299     EXPECT_FALSE(opt.has_value());
300 
301     END_TEST;
302 }
303 
304 template <typename T>
construct_with_value()305 bool construct_with_value() {
306     BEGIN_TEST;
307 
308     fit::nullable<T> opt(traits<T>::a);
309     EXPECT_TRUE(opt.has_value());
310     EXPECT_TRUE(!!opt);
311 
312     EXPECT_EQ(42, opt.value().value);
313     EXPECT_EQ(42, opt.value_or(traits<T>::b).value);
314 
315     EXPECT_EQ(42, opt->get());
316     EXPECT_EQ(43, opt->increment());
317     EXPECT_EQ(43, opt->get());
318 
319     opt.reset();
320     EXPECT_FALSE(opt.has_value());
321 
322     END_TEST;
323 }
324 
325 template <typename T>
construct_copy()326 bool construct_copy() {
327     BEGIN_TEST;
328 
329     fit::nullable<T> a(traits<T>::a);
330     fit::nullable<T> b(a);
331     fit::nullable<T> c;
332     fit::nullable<T> d(c);
333     fit::nullable<T> e(traits<T>::null);
334     EXPECT_TRUE(a.has_value());
335     EXPECT_EQ(42, a.value().value);
336     EXPECT_TRUE(b.has_value());
337     EXPECT_EQ(42, b.value().value);
338     EXPECT_FALSE(c.has_value());
339     EXPECT_FALSE(d.has_value());
340     EXPECT_FALSE(e.has_value());
341 
342     END_TEST;
343 }
344 
345 template <typename T>
construct_move()346 bool construct_move() {
347     BEGIN_TEST;
348 
349     fit::nullable<T> a(traits<T>::a);
350     fit::nullable<T> b(std::move(a));
351     fit::nullable<T> c;
352     fit::nullable<T> d(std::move(c));
353     EXPECT_FALSE(a.has_value());
354     EXPECT_TRUE(b.has_value());
355     EXPECT_EQ(42, b.value().value);
356     EXPECT_FALSE(c.has_value());
357     EXPECT_FALSE(d.has_value());
358 
359     END_TEST;
360 }
361 
362 template <typename T>
accessors()363 bool accessors() {
364     BEGIN_TEST;
365 
366     fit::nullable<T> a(traits<T>::a);
367     T& value = a.value();
368     EXPECT_EQ(42, value.value);
369 
370     const T& const_value = const_cast<const decltype(a)&>(a).value();
371     EXPECT_EQ(42, const_value.value);
372 
373     T rvalue = fit::nullable<T>(traits<T>::a).value();
374     EXPECT_EQ(42, rvalue.value);
375 
376     T const_rvalue = const_cast<const fit::nullable<T>&&>(
377                          fit::nullable<T>(traits<T>::a))
378                          .value();
379     EXPECT_EQ(42, const_rvalue.value);
380 
381     END_TEST;
382 }
383 
384 template <typename T>
assign()385 bool assign() {
386     BEGIN_TEST;
387 
388     fit::nullable<T> a(traits<T>::a);
389     EXPECT_TRUE(a.has_value());
390     EXPECT_EQ(42, a.value().value);
391 
392     a = traits<T>::b;
393     EXPECT_TRUE(a.has_value());
394     EXPECT_EQ(55, a.value().value);
395 
396     a.reset();
397     EXPECT_FALSE(a.has_value());
398 
399     a = traits<T>::a;
400     EXPECT_TRUE(a.has_value());
401     EXPECT_EQ(42, a.value().value);
402 
403     a = nullptr;
404     EXPECT_FALSE(a.has_value());
405 
406     a = traits<T>::a;
407     a = traits<T>::null;
408     EXPECT_FALSE(a.has_value());
409 
410     END_TEST;
411 }
412 
413 template <typename T>
assign_copy()414 bool assign_copy() {
415     BEGIN_TEST;
416 
417     fit::nullable<T> a(traits<T>::a);
418     fit::nullable<T> b(traits<T>::b);
419     fit::nullable<T> c;
420     EXPECT_TRUE(a.has_value());
421     EXPECT_EQ(42, a.value().value);
422     EXPECT_TRUE(b.has_value());
423     EXPECT_EQ(55, b.value().value);
424     EXPECT_FALSE(c.has_value());
425 
426     a = b;
427     EXPECT_TRUE(a.has_value());
428     EXPECT_EQ(55, b.value().value);
429     EXPECT_TRUE(b.has_value());
430     EXPECT_EQ(55, b.value().value);
431 
432     b = c;
433     EXPECT_FALSE(b.has_value());
434     EXPECT_FALSE(c.has_value());
435 
436     b = a;
437     EXPECT_TRUE(b.has_value());
438     EXPECT_EQ(55, b.value().value);
439     EXPECT_TRUE(a.has_value());
440     EXPECT_EQ(55, b.value().value);
441 
442 #ifdef __clang__
443 #pragma clang diagnostic push
444 #pragma clang diagnostic ignored "-Wself-assign-overloaded"
445 #endif
446 
447     b = b;
448     EXPECT_TRUE(b.has_value());
449     EXPECT_EQ(55, b.value().value);
450 
451     c = c;
452     EXPECT_FALSE(c.has_value());
453 
454 #ifdef __clang__
455 #pragma clang diagnostic pop
456 #endif
457 
458     b = traits<T>::null;
459     EXPECT_FALSE(b.has_value());
460 
461     END_TEST;
462 }
463 
464 template <typename T>
assign_move()465 bool assign_move() {
466     BEGIN_TEST;
467 
468     fit::nullable<T> a(traits<T>::a);
469     fit::nullable<T> b(traits<T>::b);
470     fit::nullable<T> c;
471     EXPECT_TRUE(a.has_value());
472     EXPECT_EQ(42, a.value().value);
473     EXPECT_TRUE(b.has_value());
474     EXPECT_EQ(55, b.value().value);
475     EXPECT_FALSE(c.has_value());
476 
477     a = std::move(b);
478     EXPECT_TRUE(a.has_value());
479     EXPECT_EQ(55, a.value().value);
480     EXPECT_FALSE(b.has_value());
481 
482     b = std::move(c);
483     EXPECT_FALSE(b.has_value());
484     EXPECT_FALSE(c.has_value());
485 
486     c = std::move(b);
487     EXPECT_FALSE(c.has_value());
488     EXPECT_FALSE(b.has_value());
489 
490     b = std::move(a);
491     EXPECT_TRUE(b.has_value());
492     EXPECT_EQ(55, b.value().value);
493     EXPECT_FALSE(a.has_value());
494 
495     b = std::move(b);
496     EXPECT_TRUE(b.has_value());
497     EXPECT_EQ(55, b.value().value);
498 
499     a = std::move(a);
500     EXPECT_FALSE(a.has_value());
501 
502     END_TEST;
503 }
504 
505 template <typename T>
invoke()506 bool invoke() {
507     BEGIN_TEST;
508 
509     fit::nullable<T> a(traits<T>::a);
510     EXPECT_EQ(42, a->get());
511     EXPECT_EQ(43, a->increment());
512     EXPECT_EQ(43, (*a).value);
513 
514     END_TEST;
515 }
516 
517 template <typename T>
comparisons()518 bool comparisons() {
519     BEGIN_TEST;
520 
521     fit::nullable<T> a(traits<T>::a);
522     fit::nullable<T> b(traits<T>::b);
523     fit::nullable<T> c(traits<T>::a);
524     fit::nullable<T> d;
525     fit::nullable<T> e(traits<T>::null);
526 
527     EXPECT_FALSE(a == b);
528     EXPECT_TRUE(a == c);
529     EXPECT_FALSE(a == d);
530     EXPECT_TRUE(d == e);
531     EXPECT_FALSE(d == a);
532 
533     EXPECT_FALSE(a == nullptr);
534     EXPECT_FALSE(nullptr == a);
535     EXPECT_TRUE(a == traits<T>::a);
536     EXPECT_TRUE(traits<T>::a == a);
537     EXPECT_FALSE(a == traits<T>::b);
538     EXPECT_FALSE(traits<T>::b == a);
539     EXPECT_FALSE(d == traits<T>::a);
540     EXPECT_FALSE(traits<T>::b == d);
541     EXPECT_TRUE(d == nullptr);
542     EXPECT_TRUE(nullptr == d);
543 
544     EXPECT_TRUE(a != b);
545     EXPECT_FALSE(a != c);
546     EXPECT_TRUE(a != d);
547     EXPECT_FALSE(d != e);
548     EXPECT_TRUE(d != a);
549 
550     EXPECT_TRUE(a != nullptr);
551     EXPECT_TRUE(nullptr != a);
552     EXPECT_FALSE(a != traits<T>::a);
553     EXPECT_FALSE(traits<T>::a != a);
554     EXPECT_TRUE(a != traits<T>::b);
555     EXPECT_TRUE(traits<T>::b != a);
556     EXPECT_TRUE(d != traits<T>::a);
557     EXPECT_TRUE(traits<T>::a != d);
558     EXPECT_FALSE(d != nullptr);
559     EXPECT_FALSE(nullptr != d);
560 
561     END_TEST;
562 }
563 
564 template <typename T>
swapping()565 bool swapping() {
566     BEGIN_TEST;
567 
568     fit::nullable<T> a(traits<T>::a);
569     fit::nullable<T> b(traits<T>::b);
570     fit::nullable<T> c;
571     fit::nullable<T> d;
572 
573     swap(a, b);
574     EXPECT_TRUE(a.has_value());
575     EXPECT_EQ(55, a.value().value);
576     EXPECT_TRUE(b.has_value());
577     EXPECT_EQ(42, b.value().value);
578 
579     swap(a, c);
580     EXPECT_FALSE(a.has_value());
581     EXPECT_TRUE(c.has_value());
582     EXPECT_EQ(55, c.value().value);
583 
584     swap(d, c);
585     EXPECT_FALSE(c.has_value());
586     EXPECT_TRUE(d.has_value());
587     EXPECT_EQ(55, d.value().value);
588 
589     swap(c, a);
590     EXPECT_FALSE(c.has_value());
591     EXPECT_FALSE(a.has_value());
592 
593     swap(a, a);
594     EXPECT_FALSE(a.has_value());
595 
596     swap(d, d);
597     EXPECT_TRUE(d.has_value());
598     EXPECT_EQ(55, d.value().value);
599 
600     END_TEST;
601 }
602 
603 } // namespace
604 
605 BEGIN_TEST_CASE(nullable_tests)
606 RUN_TEST(is_null)
607 RUN_TEST(construct_without_value<nullable_struct>)
608 RUN_TEST(construct_without_value<non_nullable_struct>)
609 RUN_TEST(construct_with_value<nullable_struct>)
610 RUN_TEST(construct_with_value<non_nullable_struct>)
611 RUN_TEST(construct_copy<nullable_struct>)
612 RUN_TEST(construct_copy<non_nullable_struct>)
613 RUN_TEST(construct_move<nullable_struct>)
614 RUN_TEST(construct_move<non_nullable_struct>)
615 RUN_TEST(accessors<nullable_struct>)
616 RUN_TEST(accessors<non_nullable_struct>)
617 RUN_TEST(assign<nullable_struct>)
618 RUN_TEST(assign<non_nullable_struct>)
619 RUN_TEST(assign_copy<nullable_struct>)
620 RUN_TEST(assign_copy<non_nullable_struct>)
621 RUN_TEST(assign_move<nullable_struct>)
622 RUN_TEST(assign_move<non_nullable_struct>)
623 RUN_TEST(invoke<nullable_struct>)
624 RUN_TEST(invoke<non_nullable_struct>)
625 RUN_TEST(comparisons<nullable_struct>)
626 RUN_TEST(comparisons<non_nullable_struct>)
627 RUN_TEST(swapping<nullable_struct>)
628 RUN_TEST(swapping<non_nullable_struct>)
629 END_TEST_CASE(nullable_tests)
630