blob: 47e396a2260cb683dee85246407d25acaf33028f [file] [log] [blame]
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +090032typedef expected<void, int> exp_void;
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +090063
64 exp_void e3;
65 EXPECT_TRUE(e3.has_value());
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +0900131 exp_void e5 = {};
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +0900137 EXPECT_TRUE(e5.has_value());
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +0900173 exp_void::unexpected_type unexp4 = unexpected(10);
174 exp_void e4 = unexp4;
175
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900176 EXPECT_FALSE(e.has_value());
177 EXPECT_FALSE(e2.has_value());
178 EXPECT_FALSE(e3.has_value());
Jiyong Parkbdf42dc2019-06-05 18:33:01 +0900179 EXPECT_FALSE(e4.has_value());
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +0900183 EXPECT_EQ(10, e4.error());
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +0900190 exp_void e4 = unexpected(10);
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +0900195 EXPECT_FALSE(e4.has_value());
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +0900199 EXPECT_EQ(10, e4.error());
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-06-05 18:33:01 +0900215
216 exp_void e4({});
217 EXPECT_TRUE(e4.has_value());
Jiyong Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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;
Bernie Innocenti96912b12020-02-06 03:49:33 +0900411 EXPECT_TRUE(e.ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900412 EXPECT_TRUE(e.has_value());
413
414 exp_int e2 = unexpected(10);
Bernie Innocenti96912b12020-02-06 03:49:33 +0900415 EXPECT_FALSE(e2.ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900416 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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-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 Parkbdf42dc2019-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 Parkde84d4a2019-05-15 19:17:48 +0900500}
501
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900502TEST(Expected, testCompareWithSameError) {
503 exp_int e = unexpected(10);
504 exp_int::unexpected_type error = 10;
505 EXPECT_TRUE(e == error);
506 EXPECT_TRUE(error == e);
507 EXPECT_FALSE(e != error);
508 EXPECT_FALSE(error != e);
Jiyong Parkbdf42dc2019-06-05 18:33:01 +0900509
510 exp_void e2 = unexpected(10);
511 exp_void::unexpected_type error2 = 10;
512 EXPECT_TRUE(e2 == error2);
513 EXPECT_TRUE(error2 == e2);
514 EXPECT_FALSE(e2 != error2);
515 EXPECT_FALSE(error2 != e2);
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900516}
517
518TEST(Expected, testCompareWithDifferentError) {
519 exp_int e = unexpected(10);
520 exp_int::unexpected_type error = 20;
521 EXPECT_FALSE(e == error);
522 EXPECT_FALSE(error == e);
523 EXPECT_TRUE(e != error);
524 EXPECT_TRUE(error != e);
Jiyong Parkbdf42dc2019-06-05 18:33:01 +0900525
526 exp_void e2 = unexpected(10);
527 exp_void::unexpected_type error2 = 20;
528 EXPECT_FALSE(e2 == error2);
529 EXPECT_FALSE(error2 == e2);
530 EXPECT_TRUE(e2 != error2);
531 EXPECT_TRUE(error2 != e2);
532}
533
534TEST(Expected, testCompareDifferentType) {
535 expected<int,int> e = 10;
536 expected<int32_t, int> e2 = 10;
537 EXPECT_TRUE(e == e2);
538 e2 = 20;
539 EXPECT_FALSE(e == e2);
540
541 expected<std::string_view,int> e3 = "hello";
542 expected<std::string,int> e4 = "hello";
543 EXPECT_TRUE(e3 == e4);
544 e4 = "world";
545 EXPECT_FALSE(e3 == e4);
546
547 expected<void,int> e5;
548 expected<int,int> e6 = 10;
549 EXPECT_FALSE(e5 == e6);
550 EXPECT_FALSE(e6 == e5);
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900551}
552
553TEST(Expected, testDivideExample) {
554 struct QR {
555 int quotient;
556 int remainder;
557 QR(int q, int r) noexcept : quotient(q), remainder(r) {}
558 bool operator==(const QR& rhs) const {
559 return quotient == rhs.quotient && remainder == rhs.remainder;
560 }
561 bool operator!=(const QR& rhs) const {
562 return quotient != rhs.quotient || remainder == rhs.remainder;
563 }
564 };
565
566 auto divide = [](int x, int y) -> expected<QR,E> {
567 if (y == 0) {
568 return unexpected(E("divide by zero", -1));
569 } else {
570 return QR(x / y, x % y);
571 }
572 };
573
Bernie Innocenti96912b12020-02-06 03:49:33 +0900574 EXPECT_FALSE(divide(10, 0).ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900575 EXPECT_EQ("divide by zero", divide(10, 0).error().message);
576 EXPECT_EQ(-1, divide(10, 0).error().cause);
577
Bernie Innocenti96912b12020-02-06 03:49:33 +0900578 EXPECT_TRUE(divide(10, 3).ok());
Bernie Innocenti939d6a82020-02-03 23:54:02 +0900579 EXPECT_EQ(QR(3, 1), *divide(10, 3));
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900580}
581
582TEST(Expected, testPair) {
583 auto test = [](bool yes) -> exp_pair {
584 if (yes) {
585 return exp_pair({"yes", 42});
586 } else {
587 return unexpected(42);
588 }
589 };
590
591 auto r = test(true);
Bernie Innocenti96912b12020-02-06 03:49:33 +0900592 EXPECT_TRUE(r.ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900593 EXPECT_EQ("yes", r->first);
594}
595
Jiyong Parkbdf42dc2019-06-05 18:33:01 +0900596TEST(Expected, testVoid) {
597 auto test = [](bool ok) -> exp_void {
598 if (ok) {
599 return {};
600 } else {
601 return unexpected(10);
602 }
603 };
604
605 auto r = test(true);
Bernie Innocenti96912b12020-02-06 03:49:33 +0900606 EXPECT_TRUE(r.ok());
Jiyong Parkbdf42dc2019-06-05 18:33:01 +0900607 r = test(false);
Bernie Innocenti96912b12020-02-06 03:49:33 +0900608 EXPECT_FALSE(r.ok());
Jiyong Parkbdf42dc2019-06-05 18:33:01 +0900609 EXPECT_EQ(10, r.error());
610}
611
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900612// copied from result_test.cpp
613struct ConstructorTracker {
614 static size_t constructor_called;
615 static size_t copy_constructor_called;
616 static size_t move_constructor_called;
617 static size_t copy_assignment_called;
618 static size_t move_assignment_called;
619
620 template <typename T,
621 typename std::enable_if_t<std::is_convertible_v<T, std::string>>* = nullptr>
622 ConstructorTracker(T&& string) : string(string) {
623 ++constructor_called;
624 }
625 ConstructorTracker(const ConstructorTracker& ct) {
626 ++copy_constructor_called;
627 string = ct.string;
628 }
629 ConstructorTracker(ConstructorTracker&& ct) noexcept {
630 ++move_constructor_called;
631 string = std::move(ct.string);
632 }
633 ConstructorTracker& operator=(const ConstructorTracker& ct) {
634 ++copy_assignment_called;
635 string = ct.string;
636 return *this;
637 }
638 ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
639 ++move_assignment_called;
640 string = std::move(ct.string);
641 return *this;
642 }
643 static void Reset() {
644 constructor_called = 0;
645 copy_constructor_called = 0;
646 move_constructor_called = 0;
647 copy_assignment_called = 0;
648 move_assignment_called = 0;
649 }
650 std::string string;
651};
652
653size_t ConstructorTracker::constructor_called = 0;
654size_t ConstructorTracker::copy_constructor_called = 0;
655size_t ConstructorTracker::move_constructor_called = 0;
656size_t ConstructorTracker::copy_assignment_called = 0;
657size_t ConstructorTracker::move_assignment_called = 0;
658
659typedef expected<ConstructorTracker, int> exp_track;
660
661TEST(Expected, testNumberOfCopies) {
662 // default constructor
663 ConstructorTracker::Reset();
664 exp_track e("hello");
665 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
666 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
667 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
668 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
669 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
670
671 // copy constructor
672 ConstructorTracker::Reset();
673 exp_track e2 = e;
674 EXPECT_EQ(0U, ConstructorTracker::constructor_called);
675 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
676 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
677 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
678 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
679
680 // move constructor
681 ConstructorTracker::Reset();
682 exp_track e3 = std::move(e);
683 EXPECT_EQ(0U, ConstructorTracker::constructor_called);
684 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
685 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
686 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
687 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
688
689 // construct from lvalue
690 ConstructorTracker::Reset();
691 ConstructorTracker ct = "hello";
692 exp_track e4(ct);
693 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
694 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
695 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
696 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
697 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
698
699 // construct from rvalue
700 ConstructorTracker::Reset();
701 ConstructorTracker ct2 = "hello";
702 exp_track e5(std::move(ct2));
703 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
704 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
705 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
706 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
707 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
708
709 // copy assignment
710 ConstructorTracker::Reset();
711 exp_track e6 = "hello";
712 exp_track e7 = "world";
713 e7 = e6;
714 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
715 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
716 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
717 EXPECT_EQ(1U, ConstructorTracker::copy_assignment_called);
718 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
719
720 // move assignment
721 ConstructorTracker::Reset();
722 exp_track e8 = "hello";
723 exp_track e9 = "world";
724 e9 = std::move(e8);
725 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
726 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
727 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
728 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
729 EXPECT_EQ(1U, ConstructorTracker::move_assignment_called);
730
731 // swap
732 ConstructorTracker::Reset();
733 exp_track e10 = "hello";
734 exp_track e11 = "world";
735 std::swap(e10, e11);
736 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
737 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
738 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
739 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
740 EXPECT_EQ(2U, ConstructorTracker::move_assignment_called);
741}
742
743TEST(Expected, testNoCopyOnReturn) {
744 auto test = [](const std::string& in) -> exp_track {
745 if (in.empty()) {
746 return "literal string";
747 }
748 if (in == "test2") {
749 return ConstructorTracker(in + in + "2");
750 }
751 ConstructorTracker result(in + " " + in);
752 return result;
753 };
754
755 ConstructorTracker::Reset();
756 auto result1 = test("");
Bernie Innocenti96912b12020-02-06 03:49:33 +0900757 ASSERT_TRUE(result1.ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900758 EXPECT_EQ("literal string", result1->string);
759 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
760 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
761 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
762 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
763 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
764
765 ConstructorTracker::Reset();
766 auto result2 = test("test2");
Bernie Innocenti96912b12020-02-06 03:49:33 +0900767 ASSERT_TRUE(result2.ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900768 EXPECT_EQ("test2test22", result2->string);
769 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
770 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
771 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
772 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
773 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
774
775 ConstructorTracker::Reset();
776 auto result3 = test("test3");
Bernie Innocenti96912b12020-02-06 03:49:33 +0900777 ASSERT_TRUE(result3.ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900778 EXPECT_EQ("test3 test3", result3->string);
779 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
780 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
781 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
782 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
783 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
784}
785
786TEST(Expected, testNested) {
787 expected<exp_string, std::string> e = "hello";
788
Bernie Innocenti96912b12020-02-06 03:49:33 +0900789 EXPECT_TRUE(e.ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900790 EXPECT_TRUE(e.has_value());
791 EXPECT_TRUE(e.value().has_value());
Bernie Innocenti96912b12020-02-06 03:49:33 +0900792 EXPECT_TRUE(e->ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900793 EXPECT_EQ("hello", e.value().value());
794
795 expected<exp_string, std::string> e2 = unexpected("world");
796 EXPECT_FALSE(e2.has_value());
Bernie Innocenti96912b12020-02-06 03:49:33 +0900797 EXPECT_FALSE(e2.ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900798 EXPECT_EQ("world", e2.error());
799
800 expected<exp_string, std::string> e3 = exp_string(unexpected("world"));
801 EXPECT_TRUE(e3.has_value());
802 EXPECT_FALSE(e3.value().has_value());
Bernie Innocenti96912b12020-02-06 03:49:33 +0900803 EXPECT_TRUE(e3.ok());
804 EXPECT_FALSE(e3->ok());
Jiyong Parkde84d4a2019-05-15 19:17:48 +0900805 EXPECT_EQ("world", e3.value().error());
806}
807
808constexpr bool equals(const char* a, const char* b) {
809 return (a == nullptr && b == nullptr) ||
810 (a != nullptr && b != nullptr && *a == *b &&
811 (*a == '\0' || equals(a + 1, b + 1)));
812}
813
814TEST(Expected, testConstexpr) {
815 // Compliation error will occur if these expressions can't be
816 // evaluated at compile time
817 constexpr exp_int e(3);
818 constexpr exp_int::unexpected_type err(3);
819 constexpr int i = 4;
820
821 // default constructor
822 static_assert(exp_int().value() == 0);
823 // copy constructor
824 static_assert(exp_int(e).value() == 3);
825 // move constructor
826 static_assert(exp_int(exp_int(4)).value() == 4);
827 // copy construct from value
828 static_assert(exp_int(i).value() == 4);
829 // copy construct from unexpected
830 static_assert(exp_int(err).error() == 3);
831 // move costruct from unexpected
832 static_assert(exp_int(unexpected(3)).error() == 3);
833 // observers
834 static_assert(*exp_int(3) == 3);
835 static_assert(exp_int(3).has_value() == true);
836 static_assert(exp_int(3).value_or(4) == 3);
837
838 typedef expected<const char*, int> exp_s;
839 constexpr exp_s s("hello");
840 constexpr const char* c = "hello";
841 static_assert(equals(exp_s().value(), nullptr));
842 static_assert(equals(exp_s(s).value(), "hello"));
843 static_assert(equals(exp_s(exp_s("hello")).value(), "hello"));
844 static_assert(equals(exp_s("hello").value(), "hello"));
845 static_assert(equals(exp_s(c).value(), "hello"));
846}
847
848TEST(Expected, testWithNonConstructible) {
849 struct AssertNotConstructed {
850 AssertNotConstructed() = delete;
851 };
852
853 expected<int, AssertNotConstructed> v(42);
854 EXPECT_TRUE(v.has_value());
855 EXPECT_EQ(42, v.value());
856
857 expected<AssertNotConstructed, int> e(unexpected(42));
858 EXPECT_FALSE(e.has_value());
859 EXPECT_EQ(42, e.error());
860}
861
862TEST(Expected, testWithMoveOnlyType) {
863 typedef expected<std::unique_ptr<int>,std::unique_ptr<int>> exp_ptr;
864 exp_ptr e(std::make_unique<int>(3));
865 exp_ptr e2(unexpected(std::make_unique<int>(4)));
866
867 EXPECT_TRUE(e.has_value());
868 EXPECT_FALSE(e2.has_value());
869 EXPECT_EQ(3, *(e.value()));
870 EXPECT_EQ(4, *(e2.error()));
871
872 e2 = std::move(e);
873 EXPECT_TRUE(e.has_value());
874 EXPECT_TRUE(e2.has_value());
875 EXPECT_EQ(3, *(e2.value()));
876}