blob: a74bc1decede56bf7c54ea28ca50761528df76d5 [file] [log] [blame]
Jiyong Park7d89fb12019-05-15 19:17:48 +09001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "android-base/expected.h"
18
19#include <cstdio>
20#include <memory>
21#include <string>
22
23#include <gtest/gtest.h>
24
25using android::base::expected;
26using android::base::unexpected;
27
28typedef expected<int, int> exp_int;
29typedef expected<double, double> exp_double;
30typedef expected<std::string, std::string> exp_string;
31typedef expected<std::pair<std::string, int>, int> exp_pair;
Jiyong Parkb2a85c42019-06-05 18:33:01 +090032typedef expected<void, int> exp_void;
Jiyong Park7d89fb12019-05-15 19:17:48 +090033
34struct T {
35 int a;
36 int b;
37 T() = default;
38 T(int a, int b) noexcept : a(a), b(b) {}
39};
40bool operator==(const T& x, const T& y) {
41 return x.a == y.a && x.b == y.b;
42}
43bool operator!=(const T& x, const T& y) {
44 return x.a != y.a || x.b != y.b;
45}
46
47struct E {
48 std::string message;
49 int cause;
50 E(const std::string& message, int cause) : message(message), cause(cause) {}
51};
52
53typedef expected<T,E> exp_complex;
54
55TEST(Expected, testDefaultConstructible) {
56 exp_int e;
57 EXPECT_TRUE(e.has_value());
58 EXPECT_EQ(0, e.value());
59
60 exp_complex e2;
61 EXPECT_TRUE(e2.has_value());
62 EXPECT_EQ(T(0,0), e2.value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +090063
64 exp_void e3;
65 EXPECT_TRUE(e3.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +090066}
67
68TEST(Expected, testCopyConstructible) {
69 exp_int e;
70 exp_int e2 = e;
71
72 EXPECT_TRUE(e.has_value());
73 EXPECT_TRUE(e2.has_value());
74 EXPECT_EQ(0, e.value());
75 EXPECT_EQ(0, e2.value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +090076
77 exp_void e3;
78 exp_void e4 = e3;
79 EXPECT_TRUE(e3.has_value());
80 EXPECT_TRUE(e4.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +090081}
82
83TEST(Expected, testMoveConstructible) {
84 exp_int e;
85 exp_int e2 = std::move(e);
86
87 EXPECT_TRUE(e.has_value());
88 EXPECT_TRUE(e2.has_value());
89 EXPECT_EQ(0, e.value());
90 EXPECT_EQ(0, e2.value());
91
92 exp_string e3(std::string("hello"));
93 exp_string e4 = std::move(e3);
94
95 EXPECT_TRUE(e3.has_value());
96 EXPECT_TRUE(e4.has_value());
97 EXPECT_EQ("", e3.value()); // e3 is moved
98 EXPECT_EQ("hello", e4.value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +090099
100 exp_void e5;
101 exp_void e6 = std::move(e5);
102 EXPECT_TRUE(e5.has_value());
103 EXPECT_TRUE(e6.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900104}
105
106TEST(Expected, testCopyConstructibleFromConvertibleType) {
107 exp_double e = 3.3f;
108 exp_int e2 = e;
109
110 EXPECT_TRUE(e.has_value());
111 EXPECT_TRUE(e2.has_value());
112 EXPECT_EQ(3.3f, e.value());
113 EXPECT_EQ(3, e2.value());
114}
115
116TEST(Expected, testMoveConstructibleFromConvertibleType) {
117 exp_double e = 3.3f;
118 exp_int e2 = std::move(e);
119
120 EXPECT_TRUE(e.has_value());
121 EXPECT_TRUE(e2.has_value());
122 EXPECT_EQ(3.3f, e.value());
123 EXPECT_EQ(3, e2.value());
124}
125
126TEST(Expected, testConstructibleFromValue) {
127 exp_int e = 3;
128 exp_double e2 = 5.5f;
129 exp_string e3 = std::string("hello");
130 exp_complex e4 = T(10, 20);
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900131 exp_void e5 = {};
Jiyong Park7d89fb12019-05-15 19:17:48 +0900132
133 EXPECT_TRUE(e.has_value());
134 EXPECT_TRUE(e2.has_value());
135 EXPECT_TRUE(e3.has_value());
136 EXPECT_TRUE(e4.has_value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900137 EXPECT_TRUE(e5.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900138 EXPECT_EQ(3, e.value());
139 EXPECT_EQ(5.5f, e2.value());
140 EXPECT_EQ("hello", e3.value());
141 EXPECT_EQ(T(10,20), e4.value());
142}
143
144TEST(Expected, testConstructibleFromMovedValue) {
145 std::string hello = "hello";
146 exp_string e = std::move(hello);
147
148 EXPECT_TRUE(e.has_value());
149 EXPECT_EQ("hello", e.value());
150 EXPECT_EQ("", hello);
151}
152
153TEST(Expected, testConstructibleFromConvertibleValue) {
154 exp_int e = 3.3f; // double to int
155 exp_string e2 = "hello"; // char* to std::string
156 EXPECT_TRUE(e.has_value());
157 EXPECT_EQ(3, e.value());
158
159 EXPECT_TRUE(e2.has_value());
160 EXPECT_EQ("hello", e2.value());
161}
162
163TEST(Expected, testConstructibleFromUnexpected) {
164 exp_int::unexpected_type unexp = unexpected(10);
165 exp_int e = unexp;
166
167 exp_double::unexpected_type unexp2 = unexpected(10.5f);
168 exp_double e2 = unexp2;
169
170 exp_string::unexpected_type unexp3 = unexpected(std::string("error"));
171 exp_string e3 = unexp3;
172
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900173 exp_void::unexpected_type unexp4 = unexpected(10);
174 exp_void e4 = unexp4;
175
Jiyong Park7d89fb12019-05-15 19:17:48 +0900176 EXPECT_FALSE(e.has_value());
177 EXPECT_FALSE(e2.has_value());
178 EXPECT_FALSE(e3.has_value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900179 EXPECT_FALSE(e4.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900180 EXPECT_EQ(10, e.error());
181 EXPECT_EQ(10.5f, e2.error());
182 EXPECT_EQ("error", e3.error());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900183 EXPECT_EQ(10, e4.error());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900184}
185
186TEST(Expected, testMoveConstructibleFromUnexpected) {
187 exp_int e = unexpected(10);
188 exp_double e2 = unexpected(10.5f);
189 exp_string e3 = unexpected(std::string("error"));
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900190 exp_void e4 = unexpected(10);
Jiyong Park7d89fb12019-05-15 19:17:48 +0900191
192 EXPECT_FALSE(e.has_value());
193 EXPECT_FALSE(e2.has_value());
194 EXPECT_FALSE(e3.has_value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900195 EXPECT_FALSE(e4.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900196 EXPECT_EQ(10, e.error());
197 EXPECT_EQ(10.5f, e2.error());
198 EXPECT_EQ("error", e3.error());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900199 EXPECT_EQ(10, e4.error());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900200}
201
202TEST(Expected, testConstructibleByForwarding) {
203 exp_string e(std::in_place, 5, 'a');
204 EXPECT_TRUE(e.has_value());
205 EXPECT_EQ("aaaaa", e.value());
206
207 exp_string e2({'a', 'b', 'c'});
208 EXPECT_TRUE(e2.has_value());
209 EXPECT_EQ("abc", e2.value());
210
211 exp_pair e3({"hello", 30});
212 EXPECT_TRUE(e3.has_value());
213 EXPECT_EQ("hello",e3->first);
214 EXPECT_EQ(30,e3->second);
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900215
216 exp_void e4({});
217 EXPECT_TRUE(e4.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900218}
219
220TEST(Expected, testDestructible) {
221 bool destroyed = false;
222 struct T {
223 bool* flag_;
224 T(bool* flag) : flag_(flag) {}
225 ~T() { *flag_ = true; }
226 };
227 {
228 expected<T, int> exp = T(&destroyed);
229 }
230 EXPECT_TRUE(destroyed);
231}
232
233TEST(Expected, testAssignable) {
234 exp_int e = 10;
235 exp_int e2 = 20;
236 e = e2;
237
238 EXPECT_EQ(20, e.value());
239 EXPECT_EQ(20, e2.value());
240
241 exp_int e3 = 10;
242 exp_int e4 = 20;
243 e3 = std::move(e4);
244
245 EXPECT_EQ(20, e3.value());
246 EXPECT_EQ(20, e4.value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900247
248 exp_void e5 = unexpected(10);
249 ASSERT_FALSE(e5.has_value());
250 exp_void e6;
251 e5 = e6;
252
253 EXPECT_TRUE(e5.has_value());
254 EXPECT_TRUE(e6.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900255}
256
257TEST(Expected, testAssignableFromValue) {
258 exp_int e = 10;
259 e = 20;
260 EXPECT_EQ(20, e.value());
261
262 exp_double e2 = 3.5f;
263 e2 = 10.5f;
264 EXPECT_EQ(10.5f, e2.value());
265
266 exp_string e3 = "hello";
267 e3 = "world";
268 EXPECT_EQ("world", e3.value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900269
270 exp_void e4 = unexpected(10);
271 ASSERT_FALSE(e4.has_value());
272 e4 = {};
273 EXPECT_TRUE(e4.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900274}
275
276TEST(Expected, testAssignableFromUnexpected) {
277 exp_int e = 10;
278 e = unexpected(30);
279 EXPECT_FALSE(e.has_value());
280 EXPECT_EQ(30, e.error());
281
282 exp_double e2 = 3.5f;
283 e2 = unexpected(10.5f);
284 EXPECT_FALSE(e2.has_value());
285 EXPECT_EQ(10.5f, e2.error());
286
287 exp_string e3 = "hello";
288 e3 = unexpected("world");
289 EXPECT_FALSE(e3.has_value());
290 EXPECT_EQ("world", e3.error());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900291
292 exp_void e4 = {};
293 e4 = unexpected(10);
294 EXPECT_FALSE(e4.has_value());
295 EXPECT_EQ(10, e4.error());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900296}
297
298TEST(Expected, testAssignableFromMovedValue) {
299 std::string world = "world";
300 exp_string e = "hello";
301 e = std::move(world);
302
303 EXPECT_TRUE(e.has_value());
304 EXPECT_EQ("world", e.value());
305 EXPECT_EQ("", world);
306}
307
308TEST(Expected, testAssignableFromMovedUnexpected) {
309 std::string world = "world";
310 exp_string e = "hello";
311 e = unexpected(std::move(world));
312
313 EXPECT_FALSE(e.has_value());
314 EXPECT_EQ("world", e.error());
315 EXPECT_EQ("", world);
316}
317
318TEST(Expected, testEmplace) {
319 struct T {
320 int a;
321 double b;
322 T() {}
323 T(int a, double b) noexcept : a(a), b(b) {}
324 };
325 expected<T, int> exp;
326 T& t = exp.emplace(3, 10.5f);
327
328 EXPECT_TRUE(exp.has_value());
329 EXPECT_EQ(3, t.a);
330 EXPECT_EQ(10.5f, t.b);
331 EXPECT_EQ(3, exp.value().a);
332 EXPECT_EQ(10.5, exp.value().b);
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900333
334 exp_void e = unexpected(10);
335 ASSERT_FALSE(e.has_value());
336 e.emplace();
337 EXPECT_TRUE(e.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900338}
339
340TEST(Expected, testSwapExpectedExpected) {
341 exp_int e = 10;
342 exp_int e2 = 20;
343 e.swap(e2);
344
345 EXPECT_TRUE(e.has_value());
346 EXPECT_TRUE(e2.has_value());
347 EXPECT_EQ(20, e.value());
348 EXPECT_EQ(10, e2.value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900349
350 exp_void e3;
351 exp_void e4;
352 e3.swap(e4);
353
354 EXPECT_TRUE(e3.has_value());
355 EXPECT_TRUE(e4.has_value());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900356}
357
358TEST(Expected, testSwapUnexpectedUnexpected) {
359 exp_int e = unexpected(10);
360 exp_int e2 = unexpected(20);
361 e.swap(e2);
362 EXPECT_FALSE(e.has_value());
363 EXPECT_FALSE(e2.has_value());
364 EXPECT_EQ(20, e.error());
365 EXPECT_EQ(10, e2.error());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900366
367 exp_void e3 = unexpected(10);
368 exp_void e4 = unexpected(20);
369 e3.swap(e4);
370 EXPECT_FALSE(e3.has_value());
371 EXPECT_FALSE(e4.has_value());
372 EXPECT_EQ(20, e3.error());
373 EXPECT_EQ(10, e4.error());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900374}
375
376TEST(Expected, testSwapExpectedUnepected) {
377 exp_int e = 10;
378 exp_int e2 = unexpected(30);
379 e.swap(e2);
380 EXPECT_FALSE(e.has_value());
381 EXPECT_TRUE(e2.has_value());
382 EXPECT_EQ(30, e.error());
383 EXPECT_EQ(10, e2.value());
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900384
385 exp_void e3;
386 exp_void e4 = unexpected(10);
387 e3.swap(e4);
388 EXPECT_FALSE(e3.has_value());
389 EXPECT_TRUE(e4.has_value());
390 EXPECT_EQ(10, e3.error());
Jiyong Park7d89fb12019-05-15 19:17:48 +0900391}
392
393TEST(Expected, testDereference) {
394 struct T {
395 int a;
396 double b;
397 T() {}
398 T(int a, double b) : a(a), b(b) {}
399 };
400 expected<T, int> exp = T(3, 10.5f);
401
402 EXPECT_EQ(3, exp->a);
403 EXPECT_EQ(10.5f, exp->b);
404
405 EXPECT_EQ(3, (*exp).a);
406 EXPECT_EQ(10.5f, (*exp).b);
407}
408
409TEST(Expected, testTest) {
410 exp_int e = 10;
411 EXPECT_TRUE(e);
412 EXPECT_TRUE(e.has_value());
413
414 exp_int e2 = unexpected(10);
415 EXPECT_FALSE(e2);
416 EXPECT_FALSE(e2.has_value());
417}
418
419TEST(Expected, testGetValue) {
420 exp_int e = 10;
421 EXPECT_EQ(10, e.value());
422 EXPECT_EQ(10, e.value_or(20));
423
424 exp_int e2 = unexpected(10);
425 EXPECT_EQ(10, e2.error());
426 EXPECT_EQ(20, e2.value_or(20));
427}
428
429TEST(Expected, testSameValues) {
430 exp_int e = 10;
431 exp_int e2 = 10;
432 EXPECT_TRUE(e == e2);
433 EXPECT_TRUE(e2 == e);
434 EXPECT_FALSE(e != e2);
435 EXPECT_FALSE(e2 != e);
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900436
437 exp_void e3;
438 exp_void e4;
439 EXPECT_TRUE(e3 == e4);
440 EXPECT_TRUE(e4 == e3);
441 EXPECT_FALSE(e3 != e4);
442 EXPECT_FALSE(e4 != e3);
Jiyong Park7d89fb12019-05-15 19:17:48 +0900443}
444
445TEST(Expected, testDifferentValues) {
446 exp_int e = 10;
447 exp_int e2 = 20;
448 EXPECT_FALSE(e == e2);
449 EXPECT_FALSE(e2 == e);
450 EXPECT_TRUE(e != e2);
451 EXPECT_TRUE(e2 != e);
452}
453
454TEST(Expected, testValueWithError) {
455 exp_int e = 10;
456 exp_int e2 = unexpected(10);
457 EXPECT_FALSE(e == e2);
458 EXPECT_FALSE(e2 == e);
459 EXPECT_TRUE(e != e2);
460 EXPECT_TRUE(e2 != e);
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900461
462 exp_void e3;
463 exp_void e4 = unexpected(10);
464 EXPECT_FALSE(e3 == e4);
465 EXPECT_FALSE(e4 == e3);
466 EXPECT_TRUE(e3 != e4);
467 EXPECT_TRUE(e4 != e3);
Jiyong Park7d89fb12019-05-15 19:17:48 +0900468}
469
470TEST(Expected, testSameErrors) {
471 exp_int e = unexpected(10);
472 exp_int e2 = unexpected(10);
473 EXPECT_TRUE(e == e2);
474 EXPECT_TRUE(e2 == e);
475 EXPECT_FALSE(e != e2);
476 EXPECT_FALSE(e2 != e);
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900477
478 exp_void e3 = unexpected(10);
479 exp_void e4 = unexpected(10);
480 EXPECT_TRUE(e3 == e4);
481 EXPECT_TRUE(e4 == e3);
482 EXPECT_FALSE(e3 != e4);
483 EXPECT_FALSE(e4 != e3);
Jiyong Park7d89fb12019-05-15 19:17:48 +0900484}
485
486TEST(Expected, testDifferentErrors) {
487 exp_int e = unexpected(10);
488 exp_int e2 = unexpected(20);
489 EXPECT_FALSE(e == e2);
490 EXPECT_FALSE(e2 == e);
491 EXPECT_TRUE(e != e2);
492 EXPECT_TRUE(e2 != e);
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900493
494 exp_void e3 = unexpected(10);
495 exp_void e4 = unexpected(20);
496 EXPECT_FALSE(e3 == e4);
497 EXPECT_FALSE(e4 == e3);
498 EXPECT_TRUE(e3 != e4);
499 EXPECT_TRUE(e4 != e3);
Jiyong Park7d89fb12019-05-15 19:17:48 +0900500}
501
502TEST(Expected, testCompareWithSameValue) {
503 exp_int e = 10;
504 int value = 10;
505 EXPECT_TRUE(e == value);
506 EXPECT_TRUE(value == e);
507 EXPECT_FALSE(e != value);
508 EXPECT_FALSE(value != e);
509}
510
511TEST(Expected, testCompareWithDifferentValue) {
512 exp_int e = 10;
513 int value = 20;
514 EXPECT_FALSE(e == value);
515 EXPECT_FALSE(value == e);
516 EXPECT_TRUE(e != value);
517 EXPECT_TRUE(value != e);
518}
519
520TEST(Expected, testCompareWithSameError) {
521 exp_int e = unexpected(10);
522 exp_int::unexpected_type error = 10;
523 EXPECT_TRUE(e == error);
524 EXPECT_TRUE(error == e);
525 EXPECT_FALSE(e != error);
526 EXPECT_FALSE(error != e);
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900527
528 exp_void e2 = unexpected(10);
529 exp_void::unexpected_type error2 = 10;
530 EXPECT_TRUE(e2 == error2);
531 EXPECT_TRUE(error2 == e2);
532 EXPECT_FALSE(e2 != error2);
533 EXPECT_FALSE(error2 != e2);
Jiyong Park7d89fb12019-05-15 19:17:48 +0900534}
535
536TEST(Expected, testCompareWithDifferentError) {
537 exp_int e = unexpected(10);
538 exp_int::unexpected_type error = 20;
539 EXPECT_FALSE(e == error);
540 EXPECT_FALSE(error == e);
541 EXPECT_TRUE(e != error);
542 EXPECT_TRUE(error != e);
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900543
544 exp_void e2 = unexpected(10);
545 exp_void::unexpected_type error2 = 20;
546 EXPECT_FALSE(e2 == error2);
547 EXPECT_FALSE(error2 == e2);
548 EXPECT_TRUE(e2 != error2);
549 EXPECT_TRUE(error2 != e2);
550}
551
552TEST(Expected, testCompareDifferentType) {
553 expected<int,int> e = 10;
554 expected<int32_t, int> e2 = 10;
555 EXPECT_TRUE(e == e2);
556 e2 = 20;
557 EXPECT_FALSE(e == e2);
558
559 expected<std::string_view,int> e3 = "hello";
560 expected<std::string,int> e4 = "hello";
561 EXPECT_TRUE(e3 == e4);
562 e4 = "world";
563 EXPECT_FALSE(e3 == e4);
564
565 expected<void,int> e5;
566 expected<int,int> e6 = 10;
567 EXPECT_FALSE(e5 == e6);
568 EXPECT_FALSE(e6 == e5);
Jiyong Park7d89fb12019-05-15 19:17:48 +0900569}
570
571TEST(Expected, testDivideExample) {
572 struct QR {
573 int quotient;
574 int remainder;
575 QR(int q, int r) noexcept : quotient(q), remainder(r) {}
576 bool operator==(const QR& rhs) const {
577 return quotient == rhs.quotient && remainder == rhs.remainder;
578 }
579 bool operator!=(const QR& rhs) const {
580 return quotient != rhs.quotient || remainder == rhs.remainder;
581 }
582 };
583
584 auto divide = [](int x, int y) -> expected<QR,E> {
585 if (y == 0) {
586 return unexpected(E("divide by zero", -1));
587 } else {
588 return QR(x / y, x % y);
589 }
590 };
591
592 EXPECT_FALSE(divide(10, 0));
593 EXPECT_EQ("divide by zero", divide(10, 0).error().message);
594 EXPECT_EQ(-1, divide(10, 0).error().cause);
595
596 EXPECT_TRUE(divide(10, 3));
597 EXPECT_EQ(QR(3, 1), divide(10, 3));
598}
599
600TEST(Expected, testPair) {
601 auto test = [](bool yes) -> exp_pair {
602 if (yes) {
603 return exp_pair({"yes", 42});
604 } else {
605 return unexpected(42);
606 }
607 };
608
609 auto r = test(true);
610 EXPECT_TRUE(r);
611 EXPECT_EQ("yes", r->first);
612}
613
Jiyong Parkb2a85c42019-06-05 18:33:01 +0900614TEST(Expected, testVoid) {
615 auto test = [](bool ok) -> exp_void {
616 if (ok) {
617 return {};
618 } else {
619 return unexpected(10);
620 }
621 };
622
623 auto r = test(true);
624 EXPECT_TRUE(r);
625 r = test(false);
626 EXPECT_FALSE(r);
627 EXPECT_EQ(10, r.error());
628}
629
Jiyong Park7d89fb12019-05-15 19:17:48 +0900630// copied from result_test.cpp
631struct ConstructorTracker {
632 static size_t constructor_called;
633 static size_t copy_constructor_called;
634 static size_t move_constructor_called;
635 static size_t copy_assignment_called;
636 static size_t move_assignment_called;
637
638 template <typename T,
639 typename std::enable_if_t<std::is_convertible_v<T, std::string>>* = nullptr>
640 ConstructorTracker(T&& string) : string(string) {
641 ++constructor_called;
642 }
643 ConstructorTracker(const ConstructorTracker& ct) {
644 ++copy_constructor_called;
645 string = ct.string;
646 }
647 ConstructorTracker(ConstructorTracker&& ct) noexcept {
648 ++move_constructor_called;
649 string = std::move(ct.string);
650 }
651 ConstructorTracker& operator=(const ConstructorTracker& ct) {
652 ++copy_assignment_called;
653 string = ct.string;
654 return *this;
655 }
656 ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
657 ++move_assignment_called;
658 string = std::move(ct.string);
659 return *this;
660 }
661 static void Reset() {
662 constructor_called = 0;
663 copy_constructor_called = 0;
664 move_constructor_called = 0;
665 copy_assignment_called = 0;
666 move_assignment_called = 0;
667 }
668 std::string string;
669};
670
671size_t ConstructorTracker::constructor_called = 0;
672size_t ConstructorTracker::copy_constructor_called = 0;
673size_t ConstructorTracker::move_constructor_called = 0;
674size_t ConstructorTracker::copy_assignment_called = 0;
675size_t ConstructorTracker::move_assignment_called = 0;
676
677typedef expected<ConstructorTracker, int> exp_track;
678
679TEST(Expected, testNumberOfCopies) {
680 // default constructor
681 ConstructorTracker::Reset();
682 exp_track e("hello");
683 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
684 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
685 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
686 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
687 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
688
689 // copy constructor
690 ConstructorTracker::Reset();
691 exp_track e2 = e;
692 EXPECT_EQ(0U, ConstructorTracker::constructor_called);
693 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
694 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
695 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
696 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
697
698 // move constructor
699 ConstructorTracker::Reset();
700 exp_track e3 = std::move(e);
701 EXPECT_EQ(0U, ConstructorTracker::constructor_called);
702 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
703 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
704 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
705 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
706
707 // construct from lvalue
708 ConstructorTracker::Reset();
709 ConstructorTracker ct = "hello";
710 exp_track e4(ct);
711 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
712 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
713 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
714 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
715 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
716
717 // construct from rvalue
718 ConstructorTracker::Reset();
719 ConstructorTracker ct2 = "hello";
720 exp_track e5(std::move(ct2));
721 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
722 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
723 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
724 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
725 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
726
727 // copy assignment
728 ConstructorTracker::Reset();
729 exp_track e6 = "hello";
730 exp_track e7 = "world";
731 e7 = e6;
732 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
733 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
734 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
735 EXPECT_EQ(1U, ConstructorTracker::copy_assignment_called);
736 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
737
738 // move assignment
739 ConstructorTracker::Reset();
740 exp_track e8 = "hello";
741 exp_track e9 = "world";
742 e9 = std::move(e8);
743 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
744 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
745 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
746 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
747 EXPECT_EQ(1U, ConstructorTracker::move_assignment_called);
748
749 // swap
750 ConstructorTracker::Reset();
751 exp_track e10 = "hello";
752 exp_track e11 = "world";
753 std::swap(e10, e11);
754 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
755 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
756 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
757 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
758 EXPECT_EQ(2U, ConstructorTracker::move_assignment_called);
759}
760
761TEST(Expected, testNoCopyOnReturn) {
762 auto test = [](const std::string& in) -> exp_track {
763 if (in.empty()) {
764 return "literal string";
765 }
766 if (in == "test2") {
767 return ConstructorTracker(in + in + "2");
768 }
769 ConstructorTracker result(in + " " + in);
770 return result;
771 };
772
773 ConstructorTracker::Reset();
774 auto result1 = test("");
775 ASSERT_TRUE(result1);
776 EXPECT_EQ("literal string", result1->string);
777 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
778 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
779 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
780 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
781 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
782
783 ConstructorTracker::Reset();
784 auto result2 = test("test2");
785 ASSERT_TRUE(result2);
786 EXPECT_EQ("test2test22", result2->string);
787 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
788 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
789 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
790 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
791 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
792
793 ConstructorTracker::Reset();
794 auto result3 = test("test3");
795 ASSERT_TRUE(result3);
796 EXPECT_EQ("test3 test3", result3->string);
797 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
798 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
799 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
800 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
801 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
802}
803
804TEST(Expected, testNested) {
805 expected<exp_string, std::string> e = "hello";
806
807 EXPECT_TRUE(e.has_value());
808 EXPECT_TRUE(e.value().has_value());
809 EXPECT_TRUE(e);
810 EXPECT_TRUE(*e);
811 EXPECT_EQ("hello", e.value().value());
812
813 expected<exp_string, std::string> e2 = unexpected("world");
814 EXPECT_FALSE(e2.has_value());
815 EXPECT_FALSE(e2);
816 EXPECT_EQ("world", e2.error());
817
818 expected<exp_string, std::string> e3 = exp_string(unexpected("world"));
819 EXPECT_TRUE(e3.has_value());
820 EXPECT_FALSE(e3.value().has_value());
821 EXPECT_TRUE(e3);
822 EXPECT_FALSE(*e3);
823 EXPECT_EQ("world", e3.value().error());
824}
825
826constexpr bool equals(const char* a, const char* b) {
827 return (a == nullptr && b == nullptr) ||
828 (a != nullptr && b != nullptr && *a == *b &&
829 (*a == '\0' || equals(a + 1, b + 1)));
830}
831
832TEST(Expected, testConstexpr) {
833 // Compliation error will occur if these expressions can't be
834 // evaluated at compile time
835 constexpr exp_int e(3);
836 constexpr exp_int::unexpected_type err(3);
837 constexpr int i = 4;
838
839 // default constructor
840 static_assert(exp_int().value() == 0);
841 // copy constructor
842 static_assert(exp_int(e).value() == 3);
843 // move constructor
844 static_assert(exp_int(exp_int(4)).value() == 4);
845 // copy construct from value
846 static_assert(exp_int(i).value() == 4);
847 // copy construct from unexpected
848 static_assert(exp_int(err).error() == 3);
849 // move costruct from unexpected
850 static_assert(exp_int(unexpected(3)).error() == 3);
851 // observers
852 static_assert(*exp_int(3) == 3);
853 static_assert(exp_int(3).has_value() == true);
854 static_assert(exp_int(3).value_or(4) == 3);
855
856 typedef expected<const char*, int> exp_s;
857 constexpr exp_s s("hello");
858 constexpr const char* c = "hello";
859 static_assert(equals(exp_s().value(), nullptr));
860 static_assert(equals(exp_s(s).value(), "hello"));
861 static_assert(equals(exp_s(exp_s("hello")).value(), "hello"));
862 static_assert(equals(exp_s("hello").value(), "hello"));
863 static_assert(equals(exp_s(c).value(), "hello"));
864}
865
866TEST(Expected, testWithNonConstructible) {
867 struct AssertNotConstructed {
868 AssertNotConstructed() = delete;
869 };
870
871 expected<int, AssertNotConstructed> v(42);
872 EXPECT_TRUE(v.has_value());
873 EXPECT_EQ(42, v.value());
874
875 expected<AssertNotConstructed, int> e(unexpected(42));
876 EXPECT_FALSE(e.has_value());
877 EXPECT_EQ(42, e.error());
878}
879
880TEST(Expected, testWithMoveOnlyType) {
881 typedef expected<std::unique_ptr<int>,std::unique_ptr<int>> exp_ptr;
882 exp_ptr e(std::make_unique<int>(3));
883 exp_ptr e2(unexpected(std::make_unique<int>(4)));
884
885 EXPECT_TRUE(e.has_value());
886 EXPECT_FALSE(e2.has_value());
887 EXPECT_EQ(3, *(e.value()));
888 EXPECT_EQ(4, *(e2.error()));
889
890 e2 = std::move(e);
891 EXPECT_TRUE(e.has_value());
892 EXPECT_TRUE(e2.has_value());
893 EXPECT_EQ(3, *(e2.value()));
894}