1 // Copyright 2022 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 // These tests are a modified version of the tests for absl::StatusOr:
16 // inclusive-language: disable
17 // https://github.com/abseil/abseil-cpp/blob/master/absl/status/statusor_test.cc
18 // inclusive-language: enable
19
20 #include <any>
21 #include <array>
22 #include <initializer_list>
23 #include <map>
24 #include <memory>
25 #include <string>
26 #include <string_view>
27 #include <type_traits>
28 #include <utility>
29 #include <variant>
30 #include <vector>
31
32 #include "pw_result/result.h"
33 #include "pw_unit_test/framework.h"
34
35 namespace {
36
37 struct CopyDetector {
38 CopyDetector() = default;
CopyDetector__anondd8dd5070111::CopyDetector39 explicit CopyDetector(int xx) : x(xx) {}
CopyDetector__anondd8dd5070111::CopyDetector40 CopyDetector(CopyDetector&& d) noexcept
41 : x(d.x), copied(false), moved(true) {}
CopyDetector__anondd8dd5070111::CopyDetector42 CopyDetector(const CopyDetector& d) : x(d.x), copied(true), moved(false) {}
operator =__anondd8dd5070111::CopyDetector43 CopyDetector& operator=(const CopyDetector& c) {
44 x = c.x;
45 copied = true;
46 moved = false;
47 return *this;
48 }
operator =__anondd8dd5070111::CopyDetector49 CopyDetector& operator=(CopyDetector&& c) noexcept {
50 x = c.x;
51 copied = false;
52 moved = true;
53 return *this;
54 }
55 int x = 0;
56 bool copied = false;
57 bool moved = false;
58 };
59
60 // Define custom macros instead of the CopyDetectorHas matcher.
61 #define EXPECT_COPY_DETECTOR_HAS( \
62 value, expected_x, expected_moved, expected_copied) \
63 EXPECT_EQ(value.x, expected_x); \
64 EXPECT_EQ(value.moved, expected_moved); \
65 EXPECT_EQ(value.copied, expected_copied)
66
67 #define EXPECT_OK_AND_COPY_DETECTOR_HAS( \
68 statusor_expr, expected_x, expected_moved, expected_copied) \
69 do { \
70 auto&& temp_status_or = statusor_expr; \
71 ASSERT_EQ(::pw::OkStatus(), temp_status_or.status()); \
72 EXPECT_COPY_DETECTOR_HAS( \
73 temp_status_or.value(), expected_x, expected_moved, expected_copied); \
74 } while (0)
75
76 #define EXPECT_OK_AND_ANY_WITH_COPY_DETECTOR_HAS( \
77 statusor_expr, expected_x, expected_moved, expected_copied) \
78 do { \
79 auto&& temp_status_or = statusor_expr; \
80 ASSERT_EQ(::pw::OkStatus(), temp_status_or.status()); \
81 const auto& temp_any_value = \
82 std::any_cast<const CopyDetector&>(temp_status_or.value()); \
83 EXPECT_COPY_DETECTOR_HAS( \
84 temp_any_value, expected_x, expected_moved, expected_copied); \
85 } while (0)
86
87 class Base1 {
88 public:
~Base1()89 virtual ~Base1() {}
90 int pad;
91 };
92
93 class Base2 {
94 public:
~Base2()95 virtual ~Base2() {}
96 int yetotherpad;
97 };
98
99 class Derived : public Base1, public Base2 {
100 public:
~Derived()101 ~Derived() override {}
102 int evenmorepad;
103 };
104
105 class CopyNoAssign {
106 public:
CopyNoAssign(int value)107 explicit CopyNoAssign(int value) : foo(value) {}
CopyNoAssign(const CopyNoAssign & other)108 CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
109 const CopyNoAssign& operator=(const CopyNoAssign&) = delete;
110
111 int foo;
112 };
113
ReturnUniquePtr()114 pw::Result<std::unique_ptr<int>> ReturnUniquePtr() {
115 // Uses implicit constructor from T&&
116 return std::make_unique<int>(0);
117 }
118
TEST(Result,ElementType)119 TEST(Result, ElementType) {
120 static_assert(std::is_same<pw::Result<int>::value_type, int>());
121 static_assert(std::is_same<pw::Result<char>::value_type, char>());
122 }
123
TEST(Result,TestMoveOnlyInitialization)124 TEST(Result, TestMoveOnlyInitialization) {
125 pw::Result<std::unique_ptr<int>> thing(ReturnUniquePtr());
126 ASSERT_TRUE(thing.ok());
127 EXPECT_EQ(0, **thing);
128 int* previous = thing->get();
129
130 thing = ReturnUniquePtr();
131 EXPECT_TRUE(thing.ok());
132 EXPECT_EQ(0, **thing);
133 EXPECT_NE(previous, thing->get());
134 }
135
TEST(Result,TestMoveOnlyValueExtraction)136 TEST(Result, TestMoveOnlyValueExtraction) {
137 pw::Result<std::unique_ptr<int>> thing(ReturnUniquePtr());
138 ASSERT_TRUE(thing.ok());
139 std::unique_ptr<int> ptr = *std::move(thing);
140 EXPECT_EQ(0, *ptr);
141
142 thing = std::move(ptr);
143 ptr = std::move(*thing);
144 EXPECT_EQ(0, *ptr);
145 }
146
TEST(Result,TestMoveOnlyInitializationFromTemporaryByValueOrDie)147 TEST(Result, TestMoveOnlyInitializationFromTemporaryByValueOrDie) {
148 std::unique_ptr<int> ptr(*ReturnUniquePtr());
149 EXPECT_EQ(0, *ptr);
150 }
151
TEST(Result,TestValueOrDieOverloadForConstTemporary)152 TEST(Result, TestValueOrDieOverloadForConstTemporary) {
153 static_assert(
154 std::is_same<const int&&,
155 decltype(std::declval<const pw::Result<int>&&>().value())>(),
156 "value() for const temporaries should return const T&&");
157 }
158
TEST(Result,TestMoveOnlyConversion)159 TEST(Result, TestMoveOnlyConversion) {
160 pw::Result<std::unique_ptr<const int>> const_thing(ReturnUniquePtr());
161 EXPECT_TRUE(const_thing.ok());
162 EXPECT_EQ(0, **const_thing);
163
164 // Test rvalue converting assignment
165 const int* const_previous = const_thing->get();
166 const_thing = ReturnUniquePtr();
167 EXPECT_TRUE(const_thing.ok());
168 EXPECT_EQ(0, **const_thing);
169 EXPECT_NE(const_previous, const_thing->get());
170 }
171
TEST(Result,TestMoveOnlyVector)172 TEST(Result, TestMoveOnlyVector) {
173 // Check that pw::Result<MoveOnly> works in vector.
174 std::vector<pw::Result<std::unique_ptr<int>>> vec;
175 vec.push_back(ReturnUniquePtr());
176 vec.resize(2);
177 auto another_vec = std::move(vec);
178 EXPECT_EQ(0, **another_vec[0]);
179 EXPECT_EQ(pw::Status::Unknown(), another_vec[1].status());
180 }
181
TEST(Result,TestDefaultCtor)182 TEST(Result, TestDefaultCtor) {
183 pw::Result<int> thing;
184 EXPECT_FALSE(thing.ok());
185 EXPECT_EQ(thing.status().code(), pw::Status::Unknown().code());
186 }
187
TEST(Result,StatusCtorForwards)188 TEST(Result, StatusCtorForwards) {
189 pw::Status status = pw::Status::Internal();
190
191 EXPECT_EQ(pw::Result<int>(status).status(), pw::Status::Internal());
192
193 EXPECT_EQ(pw::Result<int>(std::move(status)).status(),
194 pw::Status::Internal());
195 }
196
197 #define EXPECT_DEATH_OR_THROW(statement, status) \
198 EXPECT_DEATH_IF_SUPPORTED(statement, ".*");
199
TEST(ResultDeathTest,TestDefaultCtorValue)200 TEST(ResultDeathTest, TestDefaultCtorValue) {
201 pw::Result<int> thing;
202 EXPECT_DEATH_OR_THROW(thing.value(), pw::Status::Unknown());
203 const pw::Result<int> thing2;
204 EXPECT_DEATH_OR_THROW(thing2.value(), pw::Status::Unknown());
205 }
206
TEST(ResultDeathTest,TestValueNotOk)207 TEST(ResultDeathTest, TestValueNotOk) {
208 pw::Result<int> thing(pw::Status::Cancelled());
209 EXPECT_DEATH_OR_THROW(thing.value(), pw::Status::Cancelled());
210 }
211
TEST(ResultDeathTest,TestValueNotOkConst)212 TEST(ResultDeathTest, TestValueNotOkConst) {
213 const pw::Result<int> thing(pw::Status::Unknown());
214 EXPECT_DEATH_OR_THROW(thing.value(), pw::Status::Unknown());
215 }
216
TEST(ResultDeathTest,TestPointerDefaultCtorValue)217 TEST(ResultDeathTest, TestPointerDefaultCtorValue) {
218 pw::Result<int*> thing;
219 EXPECT_DEATH_OR_THROW(thing.value(), pw::Status::Unknown());
220 }
221
TEST(ResultDeathTest,TestPointerValueNotOk)222 TEST(ResultDeathTest, TestPointerValueNotOk) {
223 pw::Result<int*> thing(pw::Status::Cancelled());
224 EXPECT_DEATH_OR_THROW(thing.value(), pw::Status::Cancelled());
225 }
226
TEST(ResultDeathTest,TestPointerValueNotOkConst)227 TEST(ResultDeathTest, TestPointerValueNotOkConst) {
228 const pw::Result<int*> thing(pw::Status::Cancelled());
229 EXPECT_DEATH_OR_THROW(thing.value(), pw::Status::Cancelled());
230 }
231
232 #if GTEST_HAS_DEATH_TEST
TEST(ResultDeathTest,TestStatusCtorStatusOk)233 TEST(ResultDeathTest, TestStatusCtorStatusOk) {
234 EXPECT_DEBUG_DEATH(
235 {
236 // This will DCHECK
237 pw::Result<int> thing(pw::OkStatus());
238 // In optimized mode, we are actually going to get error::INTERNAL for
239 // status here, rather than crashing, so check that.
240 EXPECT_FALSE(thing.ok());
241 EXPECT_EQ(thing.status().code(), pw::Status::Internal().code());
242 },
243 ".*");
244 }
245
TEST(ResultDeathTest,TestPointerStatusCtorStatusOk)246 TEST(ResultDeathTest, TestPointerStatusCtorStatusOk) {
247 EXPECT_DEBUG_DEATH(
248 {
249 pw::Result<int*> thing(pw::OkStatus());
250 // In optimized mode, we are actually going to get error::INTERNAL for
251 // status here, rather than crashing, so check that.
252 EXPECT_FALSE(thing.ok());
253 EXPECT_EQ(thing.status().code(), pw::Status::Internal().code());
254 },
255 ".*");
256 }
257 #endif
258
TEST(Result,ValueAccessor)259 TEST(Result, ValueAccessor) {
260 const int kIntValue = 110;
261 {
262 pw::Result<int> status_or(kIntValue);
263 EXPECT_EQ(kIntValue, status_or.value());
264 EXPECT_EQ(kIntValue, std::move(status_or).value());
265 }
266 {
267 pw::Result<CopyDetector> status_or(kIntValue);
268 EXPECT_OK_AND_COPY_DETECTOR_HAS(status_or, kIntValue, false, false);
269 CopyDetector copy_detector = status_or.value();
270 EXPECT_COPY_DETECTOR_HAS(copy_detector, kIntValue, false, true);
271 copy_detector = std::move(status_or).value();
272 EXPECT_COPY_DETECTOR_HAS(copy_detector, kIntValue, true, false);
273 }
274 }
275
TEST(Result,BadValueAccess)276 TEST(Result, BadValueAccess) {
277 const pw::Status kError = pw::Status::Cancelled();
278 pw::Result<int> status_or(kError);
279 EXPECT_DEATH_OR_THROW(status_or.value(), kError);
280 }
281
TEST(Result,TestStatusCtor)282 TEST(Result, TestStatusCtor) {
283 pw::Result<int> thing(pw::Status::Cancelled());
284 EXPECT_FALSE(thing.ok());
285 EXPECT_EQ(thing.status().code(), pw::Status::Cancelled().code());
286 }
287
TEST(Result,TestValueCtor)288 TEST(Result, TestValueCtor) {
289 const int kI = 4;
290 const pw::Result<int> thing(kI);
291 EXPECT_TRUE(thing.ok());
292 EXPECT_EQ(kI, *thing);
293 }
294
295 struct Foo {
296 const int x;
Foo__anondd8dd5070111::Foo297 explicit Foo(int y) : x(y) {}
298 };
299
TEST(Result,InPlaceConstruction)300 TEST(Result, InPlaceConstruction) {
301 pw::Result<Foo> status_or(std::in_place, 10);
302 ASSERT_TRUE(status_or.ok());
303 EXPECT_EQ(status_or->x, 10);
304 }
305
306 struct InPlaceHelper {
InPlaceHelper__anondd8dd5070111::InPlaceHelper307 InPlaceHelper(std::initializer_list<int> xs, std::unique_ptr<int> yy)
308 : x(xs), y(std::move(yy)) {}
309 const std::vector<int> x;
310 std::unique_ptr<int> y;
311 };
312
TEST(Result,InPlaceInitListConstruction)313 TEST(Result, InPlaceInitListConstruction) {
314 pw::Result<InPlaceHelper> status_or(
315 std::in_place, {10, 11, 12}, std::make_unique<int>(13));
316 ASSERT_TRUE(status_or.ok());
317 ASSERT_EQ(status_or->x.size(), 3u);
318 EXPECT_EQ(status_or->x[0], 10);
319 EXPECT_EQ(status_or->x[1], 11);
320 EXPECT_EQ(status_or->x[2], 12);
321 EXPECT_EQ(*(status_or->y), 13);
322 }
323
TEST(Result,Emplace)324 TEST(Result, Emplace) {
325 pw::Result<Foo> status_or_foo(10);
326 status_or_foo.emplace(20);
327
328 ASSERT_TRUE(status_or_foo.ok());
329 EXPECT_EQ(status_or_foo->x, 20);
330
331 status_or_foo = pw::Status::InvalidArgument();
332 EXPECT_FALSE(status_or_foo.ok());
333 EXPECT_EQ(status_or_foo.status().code(),
334 pw::Status::InvalidArgument().code());
335 status_or_foo.emplace(20);
336 ASSERT_TRUE(status_or_foo.ok());
337 EXPECT_EQ(status_or_foo->x, 20);
338 }
339
TEST(Result,EmplaceInitializerList)340 TEST(Result, EmplaceInitializerList) {
341 pw::Result<InPlaceHelper> status_or(
342 std::in_place, {10, 11, 12}, std::make_unique<int>(13));
343 status_or.emplace({1, 2, 3}, std::make_unique<int>(4));
344 ASSERT_TRUE(status_or.ok());
345 ASSERT_EQ(status_or->x.size(), 3u);
346 EXPECT_EQ(status_or->x[0], 1);
347 EXPECT_EQ(status_or->x[1], 2);
348 EXPECT_EQ(status_or->x[2], 3);
349 EXPECT_EQ(*(status_or->y), 4);
350
351 status_or = pw::Status::InvalidArgument();
352 EXPECT_FALSE(status_or.ok());
353 EXPECT_EQ(status_or.status().code(), pw::Status::InvalidArgument().code());
354
355 status_or.emplace({1, 2, 3}, std::make_unique<int>(4));
356 ASSERT_TRUE(status_or.ok());
357 ASSERT_EQ(status_or->x.size(), 3u);
358 EXPECT_EQ(status_or->x[0], 1);
359 EXPECT_EQ(status_or->x[1], 2);
360 EXPECT_EQ(status_or->x[2], 3);
361 EXPECT_EQ(*(status_or->y), 4);
362 }
363
TEST(Result,TestCopyCtorStatusOk)364 TEST(Result, TestCopyCtorStatusOk) {
365 const int kI = 4;
366 const pw::Result<int> original(kI);
367 const pw::Result<int> copy(original);
368 PW_TEST_EXPECT_OK(copy.status());
369 EXPECT_EQ(*original, *copy);
370 }
371
TEST(Result,TestCopyCtorStatusNotOk)372 TEST(Result, TestCopyCtorStatusNotOk) {
373 pw::Result<int> original(pw::Status::Cancelled());
374 pw::Result<int> copy(original);
375 EXPECT_EQ(copy.status().code(), pw::Status::Cancelled().code());
376 }
377
TEST(Result,TestCopyCtorNonAssignable)378 TEST(Result, TestCopyCtorNonAssignable) {
379 const int kI = 4;
380 CopyNoAssign value(kI);
381 pw::Result<CopyNoAssign> original(value);
382 pw::Result<CopyNoAssign> copy(original);
383 PW_TEST_EXPECT_OK(copy.status());
384 EXPECT_EQ(original->foo, copy->foo);
385 }
386
TEST(Result,TestCopyCtorStatusOKConverting)387 TEST(Result, TestCopyCtorStatusOKConverting) {
388 const int kI = 4;
389 pw::Result<int> original(kI);
390 pw::Result<double> copy(original);
391 PW_TEST_EXPECT_OK(copy.status());
392 EXPECT_EQ(*original, *copy);
393 }
394
TEST(Result,TestCopyCtorStatusNotOkConverting)395 TEST(Result, TestCopyCtorStatusNotOkConverting) {
396 pw::Result<int> original(pw::Status::Cancelled());
397 pw::Result<double> copy(original);
398 EXPECT_EQ(copy.status(), original.status());
399 }
400
TEST(Result,TestAssignmentStatusOk)401 TEST(Result, TestAssignmentStatusOk) {
402 // Copy assignmment
403 {
404 const auto p = std::make_shared<int>(17);
405 pw::Result<std::shared_ptr<int>> source(p);
406
407 pw::Result<std::shared_ptr<int>> target;
408 target = source;
409
410 ASSERT_TRUE(target.ok());
411 PW_TEST_EXPECT_OK(target.status());
412 EXPECT_EQ(p, *target);
413
414 ASSERT_TRUE(source.ok());
415 PW_TEST_EXPECT_OK(source.status());
416 EXPECT_EQ(p, *source);
417 }
418
419 // Move asssignment
420 {
421 const auto p = std::make_shared<int>(17);
422 pw::Result<std::shared_ptr<int>> source(p);
423
424 pw::Result<std::shared_ptr<int>> target;
425 target = std::move(source);
426
427 ASSERT_TRUE(target.ok());
428 PW_TEST_EXPECT_OK(target.status());
429 EXPECT_EQ(p, *target);
430
431 ASSERT_TRUE(source.ok()); // NOLINT(bugprone-use-after-move)
432 PW_TEST_EXPECT_OK(source.status());
433 EXPECT_EQ(nullptr, *source);
434 }
435 }
436
TEST(Result,TestAssignmentStatusNotOk)437 TEST(Result, TestAssignmentStatusNotOk) {
438 // Copy assignment
439 {
440 const pw::Status expected = pw::Status::Cancelled();
441 pw::Result<int> source(expected);
442
443 pw::Result<int> target;
444 target = source;
445
446 EXPECT_FALSE(target.ok());
447 EXPECT_EQ(expected, target.status());
448
449 EXPECT_FALSE(source.ok());
450 EXPECT_EQ(expected, source.status());
451 }
452
453 // Move assignment
454 {
455 const pw::Status expected = pw::Status::Cancelled();
456 pw::Result<int> source(expected);
457
458 pw::Result<int> target;
459 target = std::move(source);
460
461 EXPECT_FALSE(target.ok());
462 EXPECT_EQ(expected, target.status());
463
464 EXPECT_FALSE(source.ok()); // NOLINT(bugprone-use-after-move)
465 // absl::Status sets itself to INTERNAL when moved, but pw::Status does not.
466 // EXPECT_EQ(source.status().code(), pw::Status::Internal().code());
467 }
468 }
469
TEST(Result,TestAssignmentStatusOKConverting)470 TEST(Result, TestAssignmentStatusOKConverting) {
471 // Copy assignment
472 {
473 const int kI = 4;
474 pw::Result<int> source(kI);
475
476 pw::Result<double> target;
477 target = source;
478
479 ASSERT_TRUE(target.ok());
480 PW_TEST_EXPECT_OK(target.status());
481 EXPECT_EQ(kI, *target);
482
483 ASSERT_TRUE(source.ok());
484 PW_TEST_EXPECT_OK(source.status());
485 EXPECT_EQ(kI, *source);
486 }
487
488 // Move assignment
489 {
490 const auto p = new int(17);
491 pw::Result<std::unique_ptr<int>> source(p);
492
493 pw::Result<std::shared_ptr<int>> target;
494 target = std::move(source);
495
496 ASSERT_TRUE(target.ok());
497 PW_TEST_EXPECT_OK(target.status());
498 EXPECT_EQ(p, target->get());
499
500 ASSERT_TRUE(source.ok()); // NOLINT(bugprone-use-after-move)
501 PW_TEST_EXPECT_OK(source.status());
502 EXPECT_EQ(nullptr, source->get());
503 }
504 }
505
506 // implicit_cast
507 template <class T>
508 struct type_identity {
509 using type = T;
510 };
511
512 template <typename To>
implicit_cast(typename type_identity<To>::type to)513 constexpr To implicit_cast(typename type_identity<To>::type to) {
514 return to;
515 }
516
517 struct A {
518 int x;
519 };
520
521 struct ImplicitConstructibleFromA {
522 int x;
523 bool moved;
ImplicitConstructibleFromA__anondd8dd5070111::ImplicitConstructibleFromA524 ImplicitConstructibleFromA(const A& a) // NOLINT
525 : x(a.x), moved(false) {}
ImplicitConstructibleFromA__anondd8dd5070111::ImplicitConstructibleFromA526 ImplicitConstructibleFromA(A&& a) // NOLINT
527 : x(a.x), moved(true) {}
528 };
529
TEST(Result,ImplicitConvertingConstructor)530 TEST(Result, ImplicitConvertingConstructor) {
531 auto status_or = implicit_cast<pw::Result<ImplicitConstructibleFromA>>(
532 pw::Result<A>(A{11}));
533 PW_TEST_ASSERT_OK(status_or.status());
534 EXPECT_EQ(status_or->x, 11);
535 EXPECT_TRUE(status_or->moved);
536
537 pw::Result<A> a(A{12});
538 auto status_or_2 = implicit_cast<pw::Result<ImplicitConstructibleFromA>>(a);
539 PW_TEST_ASSERT_OK(status_or_2.status());
540 EXPECT_EQ(status_or_2->x, 12);
541 EXPECT_FALSE(status_or_2->moved);
542 }
543
544 struct ExplicitConstructibleFromA {
545 int x;
546 bool moved;
ExplicitConstructibleFromA__anondd8dd5070111::ExplicitConstructibleFromA547 explicit ExplicitConstructibleFromA(const A& a) : x(a.x), moved(false) {}
ExplicitConstructibleFromA__anondd8dd5070111::ExplicitConstructibleFromA548 explicit ExplicitConstructibleFromA(A&& a) : x(a.x), moved(true) {}
549 };
550
TEST(Result,ExplicitConvertingConstructor)551 TEST(Result, ExplicitConvertingConstructor) {
552 EXPECT_FALSE(
553 (std::is_convertible<const pw::Result<A>&,
554 pw::Result<ExplicitConstructibleFromA>>::value));
555 EXPECT_FALSE(
556 (std::is_convertible<pw::Result<A>&&,
557 pw::Result<ExplicitConstructibleFromA>>::value));
558 auto a1 = pw::Result<ExplicitConstructibleFromA>(pw::Result<A>(A{11}));
559 PW_TEST_ASSERT_OK(a1.status());
560 EXPECT_EQ(a1->x, 11);
561 EXPECT_TRUE(a1->moved);
562
563 pw::Result<A> a(A{12});
564 auto a2 = pw::Result<ExplicitConstructibleFromA>(a);
565 PW_TEST_ASSERT_OK(a2.status());
566 EXPECT_EQ(a2->x, 12);
567 EXPECT_FALSE(a2->moved);
568 }
569
570 struct ImplicitConstructibleFromBool {
ImplicitConstructibleFromBool__anondd8dd5070111::ImplicitConstructibleFromBool571 ImplicitConstructibleFromBool(bool y) : x(y) {} // NOLINT
572 bool x = false;
573 };
574
575 struct ConvertibleToBool {
ConvertibleToBool__anondd8dd5070111::ConvertibleToBool576 explicit ConvertibleToBool(bool y) : x(y) {}
operator bool__anondd8dd5070111::ConvertibleToBool577 operator bool() const { return x; } // NOLINT
578 bool x = false;
579 };
580
TEST(Result,ImplicitBooleanConstructionWithImplicitCasts)581 TEST(Result, ImplicitBooleanConstructionWithImplicitCasts) {
582 auto a = pw::Result<bool>(pw::Result<ConvertibleToBool>(true));
583 PW_TEST_ASSERT_OK(a.status());
584 EXPECT_TRUE(*a);
585
586 auto b = pw::Result<bool>(pw::Result<ConvertibleToBool>(false));
587 PW_TEST_ASSERT_OK(b.status());
588 EXPECT_FALSE(*b);
589
590 auto c = pw::Result<ImplicitConstructibleFromBool>(pw::Result<bool>(false));
591 PW_TEST_ASSERT_OK(c.status());
592 EXPECT_EQ(c->x, false);
593 EXPECT_FALSE(
594 (std::is_convertible<pw::Result<ConvertibleToBool>,
595 pw::Result<ImplicitConstructibleFromBool>>::value));
596 }
597
TEST(Result,BooleanConstructionWithImplicitCasts)598 TEST(Result, BooleanConstructionWithImplicitCasts) {
599 auto a = pw::Result<bool>(pw::Result<ConvertibleToBool>(true));
600 PW_TEST_ASSERT_OK(a.status());
601 EXPECT_TRUE(*a);
602
603 auto b = pw::Result<bool>(pw::Result<ConvertibleToBool>(false));
604 PW_TEST_ASSERT_OK(b.status());
605 EXPECT_FALSE(*b);
606
607 auto c = pw::Result<ImplicitConstructibleFromBool>{pw::Result<bool>(false)};
608 PW_TEST_ASSERT_OK(c.status());
609 EXPECT_FALSE(c->x);
610
611 auto d = pw::Result<ImplicitConstructibleFromBool>{
612 pw::Result<bool>(pw::Status::InvalidArgument())};
613 EXPECT_FALSE(d.ok());
614
615 auto e = pw::Result<ImplicitConstructibleFromBool>{
616 pw::Result<ConvertibleToBool>(ConvertibleToBool{false})};
617 PW_TEST_ASSERT_OK(e.status());
618 EXPECT_FALSE(e->x);
619
620 auto f = pw::Result<ImplicitConstructibleFromBool>{
621 pw::Result<ConvertibleToBool>(pw::Status::InvalidArgument())};
622 EXPECT_FALSE(f.ok());
623 }
624
TEST(Result,ConstImplicitCast)625 TEST(Result, ConstImplicitCast) {
626 auto a = implicit_cast<pw::Result<bool>>(pw::Result<const bool>(true));
627 PW_TEST_ASSERT_OK(a.status());
628 EXPECT_TRUE(*a);
629 auto b = implicit_cast<pw::Result<bool>>(pw::Result<const bool>(false));
630 PW_TEST_ASSERT_OK(b.status());
631 EXPECT_FALSE(*b);
632 auto c = implicit_cast<pw::Result<const bool>>(pw::Result<bool>(true));
633 PW_TEST_ASSERT_OK(c.status());
634 EXPECT_TRUE(*c);
635 auto d = implicit_cast<pw::Result<const bool>>(pw::Result<bool>(false));
636 PW_TEST_ASSERT_OK(d.status());
637 EXPECT_FALSE(*d);
638 auto e = implicit_cast<pw::Result<const std::string>>(
639 pw::Result<std::string>("foo"));
640 PW_TEST_ASSERT_OK(e.status());
641 EXPECT_EQ(*e, "foo");
642 auto f = implicit_cast<pw::Result<std::string>>(
643 pw::Result<const std::string>("foo"));
644 PW_TEST_ASSERT_OK(f.status());
645 EXPECT_EQ(*f, "foo");
646 auto g = implicit_cast<pw::Result<std::shared_ptr<const std::string>>>(
647 pw::Result<std::shared_ptr<std::string>>(
648 std::make_shared<std::string>("foo")));
649 PW_TEST_ASSERT_OK(g.status());
650 EXPECT_EQ(*(*g), "foo");
651 }
652
TEST(Result,ConstExplicitConstruction)653 TEST(Result, ConstExplicitConstruction) {
654 auto a = pw::Result<bool>(pw::Result<const bool>(true));
655 PW_TEST_ASSERT_OK(a.status());
656 EXPECT_TRUE(*a);
657 auto b = pw::Result<bool>(pw::Result<const bool>(false));
658 PW_TEST_ASSERT_OK(b.status());
659 EXPECT_FALSE(*b);
660 auto c = pw::Result<const bool>(pw::Result<bool>(true));
661 PW_TEST_ASSERT_OK(c.status());
662 EXPECT_TRUE(*c);
663 auto d = pw::Result<const bool>(pw::Result<bool>(false));
664 PW_TEST_ASSERT_OK(d.status());
665 EXPECT_FALSE(*d);
666 }
667
668 struct ExplicitConstructibleFromInt {
669 int x;
ExplicitConstructibleFromInt__anondd8dd5070111::ExplicitConstructibleFromInt670 explicit ExplicitConstructibleFromInt(int y) : x(y) {}
671 };
672
TEST(Result,ExplicitConstruction)673 TEST(Result, ExplicitConstruction) {
674 auto a = pw::Result<ExplicitConstructibleFromInt>(10);
675 PW_TEST_ASSERT_OK(a.status());
676 EXPECT_EQ(a->x, 10);
677 }
678
TEST(Result,ImplicitConstruction)679 TEST(Result, ImplicitConstruction) {
680 // Check implicit casting works.
681 auto status_or =
682 implicit_cast<pw::Result<std::variant<int, std::string>>>(10);
683 PW_TEST_ASSERT_OK(status_or.status());
684 EXPECT_EQ(std::get<int>(*status_or), 10);
685 }
686
TEST(Result,ImplicitConstructionFromInitliazerList)687 TEST(Result, ImplicitConstructionFromInitliazerList) {
688 // Note: dropping the explicit std::initializer_list<int> is not supported
689 // by pw::Result or std::optional.
690 auto status_or = implicit_cast<pw::Result<std::vector<int>>>({{10, 20, 30}});
691 PW_TEST_ASSERT_OK(status_or.status());
692 ASSERT_EQ(status_or->size(), 3u);
693 EXPECT_EQ((*status_or)[0], 10);
694 EXPECT_EQ((*status_or)[1], 20);
695 EXPECT_EQ((*status_or)[2], 30);
696 }
697
TEST(Result,UniquePtrImplicitConstruction)698 TEST(Result, UniquePtrImplicitConstruction) {
699 auto status_or = implicit_cast<pw::Result<std::unique_ptr<Base1>>>(
700 std::make_unique<Derived>());
701 PW_TEST_ASSERT_OK(status_or.status());
702 EXPECT_NE(status_or->get(), nullptr);
703 }
704
TEST(Result,NestedResultCopyAndMoveConstructorTests)705 TEST(Result, NestedResultCopyAndMoveConstructorTests) {
706 pw::Result<pw::Result<CopyDetector>> status_or = CopyDetector(10);
707 pw::Result<pw::Result<CopyDetector>> status_error =
708 pw::Status::InvalidArgument();
709 PW_TEST_ASSERT_OK(status_or.status());
710 EXPECT_OK_AND_COPY_DETECTOR_HAS(*status_or, 10, true, false);
711 pw::Result<pw::Result<CopyDetector>> a = status_or;
712 EXPECT_OK_AND_COPY_DETECTOR_HAS(*a, 10, false, true);
713 pw::Result<pw::Result<CopyDetector>> a_err = status_error;
714 EXPECT_FALSE(a_err.ok());
715
716 const pw::Result<pw::Result<CopyDetector>>& cref = status_or;
717 pw::Result<pw::Result<CopyDetector>> b = cref; // NOLINT
718 PW_TEST_ASSERT_OK(b.status());
719 EXPECT_OK_AND_COPY_DETECTOR_HAS(*b, 10, false, true);
720 const pw::Result<pw::Result<CopyDetector>>& cref_err = status_error;
721 pw::Result<pw::Result<CopyDetector>> b_err = cref_err; // NOLINT
722 EXPECT_FALSE(b_err.ok());
723
724 pw::Result<pw::Result<CopyDetector>> c = std::move(status_or);
725 PW_TEST_ASSERT_OK(c.status());
726 EXPECT_OK_AND_COPY_DETECTOR_HAS(*c, 10, true, false);
727 pw::Result<pw::Result<CopyDetector>> c_err = std::move(status_error);
728 EXPECT_FALSE(c_err.ok());
729 }
730
TEST(Result,NestedResultCopyAndMoveAssignment)731 TEST(Result, NestedResultCopyAndMoveAssignment) {
732 pw::Result<pw::Result<CopyDetector>> status_or = CopyDetector(10);
733 pw::Result<pw::Result<CopyDetector>> status_error =
734 pw::Status::InvalidArgument();
735 pw::Result<pw::Result<CopyDetector>> a;
736 a = status_or;
737 ASSERT_TRUE(a.ok());
738 EXPECT_OK_AND_COPY_DETECTOR_HAS(*a, 10, false, true);
739 a = status_error;
740 EXPECT_FALSE(a.ok());
741
742 const pw::Result<pw::Result<CopyDetector>>& cref = status_or;
743 a = cref;
744 ASSERT_TRUE(a.ok());
745 EXPECT_OK_AND_COPY_DETECTOR_HAS(*a, 10, false, true);
746 const pw::Result<pw::Result<CopyDetector>>& cref_err = status_error;
747 a = cref_err;
748 EXPECT_FALSE(a.ok());
749 a = std::move(status_or);
750 ASSERT_TRUE(a.ok());
751 EXPECT_OK_AND_COPY_DETECTOR_HAS(*a, 10, true, false);
752 a = std::move(status_error);
753 EXPECT_FALSE(a.ok());
754 }
755
756 struct Copyable {
Copyable__anondd8dd5070111::Copyable757 Copyable() {}
Copyable__anondd8dd5070111::Copyable758 Copyable(const Copyable&) {}
operator =__anondd8dd5070111::Copyable759 Copyable& operator=(const Copyable&) { return *this; }
760 };
761
762 struct MoveOnly {
MoveOnly__anondd8dd5070111::MoveOnly763 MoveOnly() {}
MoveOnly__anondd8dd5070111::MoveOnly764 MoveOnly(MoveOnly&&) {}
operator =__anondd8dd5070111::MoveOnly765 MoveOnly& operator=(MoveOnly&&) { return *this; }
766 };
767
768 struct NonMovable {
NonMovable__anondd8dd5070111::NonMovable769 NonMovable() {}
770 NonMovable(const NonMovable&) = delete;
771 NonMovable(NonMovable&&) = delete;
772 NonMovable& operator=(const NonMovable&) = delete;
773 NonMovable& operator=(NonMovable&&) = delete;
774 };
775
TEST(Result,CopyAndMoveAbility)776 TEST(Result, CopyAndMoveAbility) {
777 EXPECT_TRUE(std::is_copy_constructible<Copyable>::value);
778 EXPECT_TRUE(std::is_copy_assignable<Copyable>::value);
779 EXPECT_TRUE(std::is_move_constructible<Copyable>::value);
780 EXPECT_TRUE(std::is_move_assignable<Copyable>::value);
781 EXPECT_FALSE(std::is_copy_constructible<MoveOnly>::value);
782 EXPECT_FALSE(std::is_copy_assignable<MoveOnly>::value);
783 EXPECT_TRUE(std::is_move_constructible<MoveOnly>::value);
784 EXPECT_TRUE(std::is_move_assignable<MoveOnly>::value);
785 EXPECT_FALSE(std::is_copy_constructible<NonMovable>::value);
786 EXPECT_FALSE(std::is_copy_assignable<NonMovable>::value);
787 EXPECT_FALSE(std::is_move_constructible<NonMovable>::value);
788 EXPECT_FALSE(std::is_move_assignable<NonMovable>::value);
789 }
790
TEST(Result,ResultAnyCopyAndMoveConstructorTests)791 TEST(Result, ResultAnyCopyAndMoveConstructorTests) {
792 pw::Result<std::any> status_or = CopyDetector(10);
793 pw::Result<std::any> status_error = pw::Status::InvalidArgument();
794 EXPECT_OK_AND_ANY_WITH_COPY_DETECTOR_HAS(status_or, 10, true, false);
795 pw::Result<std::any> a = status_or;
796 EXPECT_OK_AND_ANY_WITH_COPY_DETECTOR_HAS(a, 10, false, true);
797 pw::Result<std::any> a_err = status_error;
798 EXPECT_FALSE(a_err.ok());
799
800 const pw::Result<std::any>& cref = status_or;
801 // No lint for no-change copy.
802 pw::Result<std::any> b = cref; // NOLINT
803 EXPECT_OK_AND_ANY_WITH_COPY_DETECTOR_HAS(b, 10, false, true);
804 const pw::Result<std::any>& cref_err = status_error;
805 // No lint for no-change copy.
806 pw::Result<std::any> b_err = cref_err; // NOLINT
807 EXPECT_FALSE(b_err.ok());
808
809 pw::Result<std::any> c = std::move(status_or);
810 EXPECT_OK_AND_ANY_WITH_COPY_DETECTOR_HAS(c, 10, true, false);
811 pw::Result<std::any> c_err = std::move(status_error);
812 EXPECT_FALSE(c_err.ok());
813 }
814
TEST(Result,ResultAnyCopyAndMoveAssignment)815 TEST(Result, ResultAnyCopyAndMoveAssignment) {
816 pw::Result<std::any> status_or = CopyDetector(10);
817 pw::Result<std::any> status_error = pw::Status::InvalidArgument();
818 pw::Result<std::any> a;
819 a = status_or;
820 EXPECT_OK_AND_ANY_WITH_COPY_DETECTOR_HAS(a, 10, false, true);
821 a = status_error;
822 EXPECT_FALSE(a.ok());
823
824 const pw::Result<std::any>& cref = status_or;
825 a = cref;
826 EXPECT_OK_AND_ANY_WITH_COPY_DETECTOR_HAS(a, 10, false, true);
827 const pw::Result<std::any>& cref_err = status_error;
828 a = cref_err;
829 EXPECT_FALSE(a.ok());
830 a = std::move(status_or);
831 EXPECT_OK_AND_ANY_WITH_COPY_DETECTOR_HAS(a, 10, true, false);
832 a = std::move(status_error);
833 EXPECT_FALSE(a.ok());
834 }
835
TEST(Result,ResultCopyAndMoveTestsConstructor)836 TEST(Result, ResultCopyAndMoveTestsConstructor) {
837 pw::Result<CopyDetector> status_or(10);
838 EXPECT_OK_AND_COPY_DETECTOR_HAS(status_or, 10, false, false);
839 pw::Result<CopyDetector> a(status_or);
840 EXPECT_OK_AND_COPY_DETECTOR_HAS(a, 10, false, true);
841 const pw::Result<CopyDetector>& cref = status_or;
842 pw::Result<CopyDetector> b(cref); // NOLINT
843 EXPECT_OK_AND_COPY_DETECTOR_HAS(b, 10, false, true);
844 pw::Result<CopyDetector> c(std::move(status_or));
845 EXPECT_OK_AND_COPY_DETECTOR_HAS(c, 10, true, false);
846 }
847
TEST(Result,ResultCopyAndMoveTestsAssignment)848 TEST(Result, ResultCopyAndMoveTestsAssignment) {
849 pw::Result<CopyDetector> status_or(10);
850 EXPECT_OK_AND_COPY_DETECTOR_HAS(status_or, 10, false, false);
851 pw::Result<CopyDetector> a;
852 a = status_or;
853 EXPECT_OK_AND_COPY_DETECTOR_HAS(a, 10, false, true);
854 const pw::Result<CopyDetector>& cref = status_or;
855 pw::Result<CopyDetector> b;
856 b = cref;
857 EXPECT_OK_AND_COPY_DETECTOR_HAS(b, 10, false, true);
858 pw::Result<CopyDetector> c;
859 c = std::move(status_or);
860 EXPECT_OK_AND_COPY_DETECTOR_HAS(c, 10, true, false);
861 }
862
TEST(Result,StdAnyAssignment)863 TEST(Result, StdAnyAssignment) {
864 EXPECT_FALSE(
865 (std::is_assignable<pw::Result<std::any>, pw::Result<int>>::value));
866 pw::Result<std::any> status_or;
867 status_or = pw::Status::InvalidArgument();
868 EXPECT_FALSE(status_or.ok());
869 }
870
TEST(Result,ImplicitAssignment)871 TEST(Result, ImplicitAssignment) {
872 pw::Result<std::variant<int, std::string>> status_or;
873 status_or = 10;
874 PW_TEST_ASSERT_OK(status_or.status());
875 EXPECT_EQ(std::get<int>(*status_or), 10);
876 }
877
TEST(Result,SelfDirectInitAssignment)878 TEST(Result, SelfDirectInitAssignment) {
879 pw::Result<std::vector<int>> status_or = {{10, 20, 30}};
880 status_or = *status_or;
881 PW_TEST_ASSERT_OK(status_or.status());
882 ASSERT_EQ(status_or->size(), 3u);
883 EXPECT_EQ((*status_or)[0], 10);
884 EXPECT_EQ((*status_or)[1], 20);
885 EXPECT_EQ((*status_or)[2], 30);
886 }
887
TEST(Result,ImplicitCastFromInitializerList)888 TEST(Result, ImplicitCastFromInitializerList) {
889 pw::Result<std::vector<int>> status_or = {{10, 20, 30}};
890 PW_TEST_ASSERT_OK(status_or.status());
891 ASSERT_EQ(status_or->size(), 3u);
892 EXPECT_EQ((*status_or)[0], 10);
893 EXPECT_EQ((*status_or)[1], 20);
894 EXPECT_EQ((*status_or)[2], 30);
895 }
896
TEST(Result,UniquePtrImplicitAssignment)897 TEST(Result, UniquePtrImplicitAssignment) {
898 pw::Result<std::unique_ptr<Base1>> status_or;
899 status_or = std::make_unique<Derived>();
900 PW_TEST_ASSERT_OK(status_or.status());
901 EXPECT_NE(status_or->get(), nullptr);
902 }
903
TEST(Result,Pointer)904 TEST(Result, Pointer) {
905 struct Base {};
906 struct B : public Base {};
907 struct C : private Base {};
908
909 EXPECT_TRUE((std::is_constructible<pw::Result<Base*>, B*>::value));
910 EXPECT_TRUE((std::is_convertible<B*, pw::Result<Base*>>::value));
911 EXPECT_FALSE((std::is_constructible<pw::Result<Base*>, C*>::value));
912 EXPECT_FALSE((std::is_convertible<C*, pw::Result<Base*>>::value));
913 }
914
TEST(Result,TestAssignmentStatusNotOkConverting)915 TEST(Result, TestAssignmentStatusNotOkConverting) {
916 // Copy assignment
917 {
918 const pw::Status expected = pw::Status::Cancelled();
919 pw::Result<int> source(expected);
920
921 pw::Result<double> target;
922 target = source;
923
924 EXPECT_FALSE(target.ok());
925 EXPECT_EQ(expected, target.status());
926
927 EXPECT_FALSE(source.ok());
928 EXPECT_EQ(expected, source.status());
929 }
930
931 // Move assignment
932 {
933 const pw::Status expected = pw::Status::Cancelled();
934 pw::Result<int> source(expected);
935
936 pw::Result<double> target;
937 target = std::move(source);
938
939 EXPECT_FALSE(target.ok());
940 EXPECT_EQ(expected, target.status());
941
942 EXPECT_FALSE(source.ok()); // NOLINT(bugprone-use-after-move)
943
944 // absl::Status sets itself to INTERNAL when moved, but pw::Status does not.
945 // EXPECT_EQ(source.status().code(), pw::Status::Internal().code());
946 }
947 }
948
TEST(Result,SelfAssignment)949 TEST(Result, SelfAssignment) {
950 // Copy-assignment, status OK
951 {
952 // A string long enough that it's likely to defeat any inline representation
953 // optimization.
954 const std::string long_str(128, 'a');
955
956 pw::Result<std::string> so = long_str;
957 so = *&so;
958
959 ASSERT_TRUE(so.ok());
960 PW_TEST_EXPECT_OK(so.status());
961 EXPECT_EQ(long_str, *so);
962 }
963
964 // Copy-assignment, error status
965 {
966 pw::Result<int> so = pw::Status::NotFound();
967 so = *&so;
968
969 EXPECT_FALSE(so.ok());
970 EXPECT_EQ(so.status().code(), pw::Status::NotFound().code());
971 }
972
973 // Move-assignment with copyable type, status OK
974 {
975 pw::Result<int> so = 17;
976
977 // Fool the compiler, which otherwise complains.
978 auto& same = so;
979 so = std::move(same);
980
981 ASSERT_TRUE(so.ok());
982 PW_TEST_EXPECT_OK(so.status());
983 EXPECT_EQ(17, *so);
984 }
985
986 // Move-assignment with copyable type, error status
987 {
988 pw::Result<int> so = pw::Status::NotFound();
989
990 // Fool the compiler, which otherwise complains.
991 auto& same = so;
992 so = std::move(same);
993
994 EXPECT_FALSE(so.ok());
995 EXPECT_EQ(so.status().code(), pw::Status::NotFound().code());
996 }
997
998 // Move-assignment with non-copyable type, status OK
999 {
1000 const auto raw = new int(17);
1001 pw::Result<std::unique_ptr<int>> so = std::unique_ptr<int>(raw);
1002
1003 // Fool the compiler, which otherwise complains.
1004 auto& same = so;
1005 so = std::move(same);
1006
1007 ASSERT_TRUE(so.ok());
1008 PW_TEST_EXPECT_OK(so.status());
1009 EXPECT_EQ(raw, so->get());
1010 }
1011
1012 // Move-assignment with non-copyable type, error status
1013 {
1014 pw::Result<std::unique_ptr<int>> so = pw::Status::NotFound();
1015
1016 // Fool the compiler, which otherwise complains.
1017 auto& same = so;
1018 so = std::move(same);
1019
1020 EXPECT_FALSE(so.ok());
1021 EXPECT_EQ(so.status().code(), pw::Status::NotFound().code());
1022 }
1023 }
1024
1025 // These types form the overload sets of the constructors and the assignment
1026 // operators of `MockValue`. They distinguish construction from assignment,
1027 // lvalue from rvalue.
1028 struct FromConstructibleAssignableLvalue {};
1029 struct FromConstructibleAssignableRvalue {};
1030 struct FromImplicitConstructibleOnly {};
1031 struct FromAssignableOnly {};
1032
1033 // This class is for testing the forwarding value assignments of `Result`.
1034 // `from_rvalue` indicates whether the constructor or the assignment taking
1035 // rvalue reference is called. `from_assignment` indicates whether any
1036 // assignment is called.
1037 struct MockValue {
1038 // Constructs `MockValue` from `FromConstructibleAssignableLvalue`.
MockValue__anondd8dd5070111::MockValue1039 MockValue(const FromConstructibleAssignableLvalue&) // NOLINT
1040 : from_rvalue(false), assigned(false) {}
1041 // Constructs `MockValue` from `FromConstructibleAssignableRvalue`.
MockValue__anondd8dd5070111::MockValue1042 MockValue(FromConstructibleAssignableRvalue&&) // NOLINT
1043 : from_rvalue(true), assigned(false) {}
1044 // Constructs `MockValue` from `FromImplicitConstructibleOnly`.
1045 // `MockValue` is not assignable from `FromImplicitConstructibleOnly`.
MockValue__anondd8dd5070111::MockValue1046 MockValue(const FromImplicitConstructibleOnly&) // NOLINT
1047 : from_rvalue(false), assigned(false) {}
1048 // Assigns `FromConstructibleAssignableLvalue`.
operator =__anondd8dd5070111::MockValue1049 MockValue& operator=(const FromConstructibleAssignableLvalue&) {
1050 from_rvalue = false;
1051 assigned = true;
1052 return *this;
1053 }
1054 // Assigns `FromConstructibleAssignableRvalue` (rvalue only).
operator =__anondd8dd5070111::MockValue1055 MockValue& operator=(FromConstructibleAssignableRvalue&&) {
1056 from_rvalue = true;
1057 assigned = true;
1058 return *this;
1059 }
1060 // Assigns `FromAssignableOnly`, but not constructible from
1061 // `FromAssignableOnly`.
operator =__anondd8dd5070111::MockValue1062 MockValue& operator=(const FromAssignableOnly&) {
1063 from_rvalue = false;
1064 assigned = true;
1065 return *this;
1066 }
1067 bool from_rvalue;
1068 bool assigned;
1069 };
1070
1071 // operator=(U&&)
TEST(Result,PerfectForwardingAssignment)1072 TEST(Result, PerfectForwardingAssignment) {
1073 // U == T
1074 constexpr int kValue1 = 10, kValue2 = 20;
1075 pw::Result<CopyDetector> status_or;
1076 CopyDetector lvalue(kValue1);
1077 status_or = lvalue;
1078 EXPECT_OK_AND_COPY_DETECTOR_HAS(status_or, kValue1, false, true);
1079 status_or = CopyDetector(kValue2);
1080 EXPECT_OK_AND_COPY_DETECTOR_HAS(status_or, kValue2, true, false);
1081
1082 // U != T
1083 EXPECT_TRUE(
1084 (std::is_assignable<pw::Result<MockValue>&,
1085 const FromConstructibleAssignableLvalue&>::value));
1086 EXPECT_TRUE((std::is_assignable<pw::Result<MockValue>&,
1087 FromConstructibleAssignableLvalue&&>::value));
1088 EXPECT_FALSE(
1089 (std::is_assignable<pw::Result<MockValue>&,
1090 const FromConstructibleAssignableRvalue&>::value));
1091 EXPECT_TRUE((std::is_assignable<pw::Result<MockValue>&,
1092 FromConstructibleAssignableRvalue&&>::value));
1093 EXPECT_TRUE(
1094 (std::is_assignable<pw::Result<MockValue>&,
1095 const FromImplicitConstructibleOnly&>::value));
1096 EXPECT_FALSE((std::is_assignable<pw::Result<MockValue>&,
1097 const FromAssignableOnly&>::value));
1098
1099 pw::Result<MockValue> from_lvalue(FromConstructibleAssignableLvalue{});
1100 EXPECT_FALSE(from_lvalue->from_rvalue);
1101 EXPECT_FALSE(from_lvalue->assigned);
1102 from_lvalue = FromConstructibleAssignableLvalue{};
1103 EXPECT_FALSE(from_lvalue->from_rvalue);
1104 EXPECT_TRUE(from_lvalue->assigned);
1105
1106 pw::Result<MockValue> from_rvalue(FromConstructibleAssignableRvalue{});
1107 EXPECT_TRUE(from_rvalue->from_rvalue);
1108 EXPECT_FALSE(from_rvalue->assigned);
1109 from_rvalue = FromConstructibleAssignableRvalue{};
1110 EXPECT_TRUE(from_rvalue->from_rvalue);
1111 EXPECT_TRUE(from_rvalue->assigned);
1112
1113 pw::Result<MockValue> from_implicit_constructible(
1114 FromImplicitConstructibleOnly{});
1115 EXPECT_FALSE(from_implicit_constructible->from_rvalue);
1116 EXPECT_FALSE(from_implicit_constructible->assigned);
1117 // construct a temporary `Result` object and invoke the `Result` move
1118 // assignment operator.
1119 from_implicit_constructible = FromImplicitConstructibleOnly{};
1120 EXPECT_FALSE(from_implicit_constructible->from_rvalue);
1121 EXPECT_FALSE(from_implicit_constructible->assigned);
1122 }
1123
TEST(Result,TestStatus)1124 TEST(Result, TestStatus) {
1125 pw::Result<int> good(4);
1126 EXPECT_TRUE(good.ok());
1127 pw::Result<int> bad(pw::Status::Cancelled());
1128 EXPECT_FALSE(bad.ok());
1129 EXPECT_EQ(bad.status().code(), pw::Status::Cancelled().code());
1130 }
1131
TEST(Result,OperatorStarRefQualifiers)1132 TEST(Result, OperatorStarRefQualifiers) {
1133 static_assert(
1134 std::is_same<const int&,
1135 decltype(*std::declval<const pw::Result<int>&>())>(),
1136 "Unexpected ref-qualifiers");
1137 static_assert(
1138 std::is_same<int&, decltype(*std::declval<pw::Result<int>&>())>(),
1139 "Unexpected ref-qualifiers");
1140 static_assert(
1141 std::is_same<const int&&,
1142 decltype(*std::declval<const pw::Result<int>&&>())>(),
1143 "Unexpected ref-qualifiers");
1144 static_assert(
1145 std::is_same<int&&, decltype(*std::declval<pw::Result<int>&&>())>(),
1146 "Unexpected ref-qualifiers");
1147 }
1148
TEST(Result,OperatorStar)1149 TEST(Result, OperatorStar) {
1150 const pw::Result<std::string> const_lvalue("hello");
1151 EXPECT_EQ("hello", *const_lvalue);
1152
1153 pw::Result<std::string> lvalue("hello");
1154 EXPECT_EQ("hello", *lvalue);
1155
1156 // Note: Recall that std::move() is equivalent to a static_cast to an rvalue
1157 // reference type.
1158 const pw::Result<std::string> const_rvalue("hello");
1159 EXPECT_EQ("hello", *std::move(const_rvalue)); // NOLINT
1160
1161 pw::Result<std::string> rvalue("hello");
1162 EXPECT_EQ("hello", *std::move(rvalue));
1163 }
1164
TEST(Result,OperatorArrowQualifiers)1165 TEST(Result, OperatorArrowQualifiers) {
1166 static_assert(
1167 std::is_same<
1168 const int*,
1169 decltype(std::declval<const pw::Result<int>&>().operator->())>(),
1170 "Unexpected qualifiers");
1171 static_assert(
1172 std::is_same<int*,
1173 decltype(std::declval<pw::Result<int>&>().operator->())>(),
1174 "Unexpected qualifiers");
1175 static_assert(
1176 std::is_same<
1177 const int*,
1178 decltype(std::declval<const pw::Result<int>&&>().operator->())>(),
1179 "Unexpected qualifiers");
1180 static_assert(
1181 std::is_same<int*,
1182 decltype(std::declval<pw::Result<int>&&>().operator->())>(),
1183 "Unexpected qualifiers");
1184 }
1185
TEST(Result,OperatorArrow)1186 TEST(Result, OperatorArrow) {
1187 const pw::Result<std::string> const_lvalue("hello");
1188 EXPECT_EQ(std::string("hello"), const_lvalue->c_str());
1189
1190 pw::Result<std::string> lvalue("hello");
1191 EXPECT_EQ(std::string("hello"), lvalue->c_str());
1192 }
1193
TEST(Result,RValueStatus)1194 TEST(Result, RValueStatus) {
1195 pw::Result<int> so(pw::Status::NotFound());
1196 const pw::Status s = std::move(so).status();
1197
1198 EXPECT_EQ(s.code(), pw::Status::NotFound().code());
1199
1200 // Check that !ok() still implies !status().ok(), even after moving out of the
1201 // object. See the note on the rvalue ref-qualified status method.
1202 EXPECT_FALSE(so.ok()); // NOLINT
1203 EXPECT_FALSE(so.status().ok());
1204
1205 // absl::Status sets itself to INTERNAL when moved, but pw::Status does not.
1206 // EXPECT_EQ(so.status().code(), pw::Status::Internal().code());
1207 }
1208
TEST(Result,TestValue)1209 TEST(Result, TestValue) {
1210 const int kI = 4;
1211 pw::Result<int> thing(kI);
1212 EXPECT_EQ(kI, *thing);
1213 }
1214
TEST(Result,TestValueConst)1215 TEST(Result, TestValueConst) {
1216 const int kI = 4;
1217 const pw::Result<int> thing(kI);
1218 EXPECT_EQ(kI, *thing);
1219 }
1220
TEST(Result,TestPointerDefaultCtor)1221 TEST(Result, TestPointerDefaultCtor) {
1222 pw::Result<int*> thing;
1223 EXPECT_FALSE(thing.ok());
1224 EXPECT_EQ(thing.status().code(), pw::Status::Unknown().code());
1225 }
1226
TEST(Result,TestPointerStatusCtor)1227 TEST(Result, TestPointerStatusCtor) {
1228 pw::Result<int*> thing(pw::Status::Cancelled());
1229 EXPECT_FALSE(thing.ok());
1230 EXPECT_EQ(thing.status().code(), pw::Status::Cancelled().code());
1231 }
1232
TEST(Result,TestPointerValueCtor)1233 TEST(Result, TestPointerValueCtor) {
1234 const int kI = 4;
1235
1236 // Construction from a non-null pointer
1237 {
1238 pw::Result<const int*> so(&kI);
1239 EXPECT_TRUE(so.ok());
1240 PW_TEST_EXPECT_OK(so.status());
1241 EXPECT_EQ(&kI, *so);
1242 }
1243
1244 // Construction from a null pointer constant
1245 {
1246 pw::Result<const int*> so(nullptr);
1247 EXPECT_TRUE(so.ok());
1248 PW_TEST_EXPECT_OK(so.status());
1249 EXPECT_EQ(nullptr, *so);
1250 }
1251
1252 // Construction from a non-literal null pointer
1253 {
1254 const int* const p = nullptr;
1255
1256 pw::Result<const int*> so(p);
1257 EXPECT_TRUE(so.ok());
1258 PW_TEST_EXPECT_OK(so.status());
1259 EXPECT_EQ(nullptr, *so);
1260 }
1261 }
1262
TEST(Result,TestPointerCopyCtorStatusOk)1263 TEST(Result, TestPointerCopyCtorStatusOk) {
1264 const int kI = 0;
1265 pw::Result<const int*> original(&kI);
1266 pw::Result<const int*> copy(original);
1267 PW_TEST_EXPECT_OK(copy.status());
1268 EXPECT_EQ(*original, *copy);
1269 }
1270
TEST(Result,TestPointerCopyCtorStatusNotOk)1271 TEST(Result, TestPointerCopyCtorStatusNotOk) {
1272 pw::Result<int*> original(pw::Status::Cancelled());
1273 pw::Result<int*> copy(original);
1274 EXPECT_EQ(copy.status().code(), pw::Status::Cancelled().code());
1275 }
1276
TEST(Result,TestPointerCopyCtorStatusOKConverting)1277 TEST(Result, TestPointerCopyCtorStatusOKConverting) {
1278 Derived derived;
1279 pw::Result<Derived*> original(&derived);
1280 pw::Result<Base2*> copy(original);
1281 PW_TEST_EXPECT_OK(copy.status());
1282 EXPECT_EQ(static_cast<const Base2*>(*original), *copy);
1283 }
1284
TEST(Result,TestPointerCopyCtorStatusNotOkConverting)1285 TEST(Result, TestPointerCopyCtorStatusNotOkConverting) {
1286 pw::Result<Derived*> original(pw::Status::Cancelled());
1287 pw::Result<Base2*> copy(original);
1288 EXPECT_EQ(copy.status().code(), pw::Status::Cancelled().code());
1289 }
1290
TEST(Result,TestPointerAssignmentStatusOk)1291 TEST(Result, TestPointerAssignmentStatusOk) {
1292 const int kI = 0;
1293 pw::Result<const int*> source(&kI);
1294 pw::Result<const int*> target;
1295 target = source;
1296 PW_TEST_EXPECT_OK(target.status());
1297 EXPECT_EQ(*source, *target);
1298 }
1299
TEST(Result,TestPointerAssignmentStatusNotOk)1300 TEST(Result, TestPointerAssignmentStatusNotOk) {
1301 pw::Result<int*> source(pw::Status::Cancelled());
1302 pw::Result<int*> target;
1303 target = source;
1304 EXPECT_EQ(target.status().code(), pw::Status::Cancelled().code());
1305 }
1306
TEST(Result,TestPointerAssignmentStatusOKConverting)1307 TEST(Result, TestPointerAssignmentStatusOKConverting) {
1308 Derived derived;
1309 pw::Result<Derived*> source(&derived);
1310 pw::Result<Base2*> target;
1311 target = source;
1312 PW_TEST_EXPECT_OK(target.status());
1313 EXPECT_EQ(static_cast<const Base2*>(*source), *target);
1314 }
1315
TEST(Result,TestPointerAssignmentStatusNotOkConverting)1316 TEST(Result, TestPointerAssignmentStatusNotOkConverting) {
1317 pw::Result<Derived*> source(pw::Status::Cancelled());
1318 pw::Result<Base2*> target;
1319 target = source;
1320 EXPECT_EQ(target.status(), source.status());
1321 }
1322
TEST(Result,TestPointerStatus)1323 TEST(Result, TestPointerStatus) {
1324 const int kI = 0;
1325 pw::Result<const int*> good(&kI);
1326 EXPECT_TRUE(good.ok());
1327 pw::Result<const int*> bad(pw::Status::Cancelled());
1328 EXPECT_EQ(bad.status().code(), pw::Status::Cancelled().code());
1329 }
1330
TEST(Result,TestPointerValue)1331 TEST(Result, TestPointerValue) {
1332 const int kI = 0;
1333 pw::Result<const int*> thing(&kI);
1334 EXPECT_EQ(&kI, *thing);
1335 }
1336
TEST(Result,TestPointerValueConst)1337 TEST(Result, TestPointerValueConst) {
1338 const int kI = 0;
1339 const pw::Result<const int*> thing(&kI);
1340 EXPECT_EQ(&kI, *thing);
1341 }
1342
TEST(Result,ResultVectorOfUniquePointerCanReserveAndResize)1343 TEST(Result, ResultVectorOfUniquePointerCanReserveAndResize) {
1344 using EvilType = std::vector<std::unique_ptr<int>>;
1345 static_assert(std::is_copy_constructible<EvilType>::value);
1346 std::vector<::pw::Result<EvilType>> v(5);
1347 v.reserve(v.capacity() + 10);
1348 v.resize(v.capacity() + 10);
1349 }
1350
TEST(Result,ConstPayload)1351 TEST(Result, ConstPayload) {
1352 // A reduced version of a problematic type found in the wild. All of the
1353 // operations below should compile.
1354 pw::Result<const int> a;
1355
1356 // Copy-construction
1357 pw::Result<const int> b(a);
1358
1359 // Copy-assignment
1360 EXPECT_FALSE(std::is_copy_assignable<pw::Result<const int>>::value);
1361
1362 // Move-construction
1363 pw::Result<const int> c(std::move(a));
1364
1365 // Move-assignment
1366 EXPECT_FALSE(std::is_move_assignable<pw::Result<const int>>::value);
1367 }
1368
TEST(Result,MapToResultUniquePtr)1369 TEST(Result, MapToResultUniquePtr) {
1370 // A reduced version of a problematic type found in the wild. All of the
1371 // operations below should compile.
1372 using MapType = std::map<std::string, pw::Result<std::unique_ptr<int>>>;
1373
1374 MapType a;
1375
1376 // Move-construction
1377 MapType b(std::move(a));
1378
1379 // Move-assignment
1380 a = std::move(b);
1381 }
1382
TEST(Result,ValueOrOk)1383 TEST(Result, ValueOrOk) {
1384 const pw::Result<int> status_or = 0;
1385 EXPECT_EQ(status_or.value_or(-1), 0);
1386 }
1387
TEST(Result,ValueOrDefault)1388 TEST(Result, ValueOrDefault) {
1389 const pw::Result<int> status_or = pw::Status::Cancelled();
1390 EXPECT_EQ(status_or.value_or(-1), -1);
1391 }
1392
TEST(Result,MoveOnlyValueOrOk)1393 TEST(Result, MoveOnlyValueOrOk) {
1394 pw::Result<std::unique_ptr<int>> status_or = std::make_unique<int>(0);
1395 ASSERT_TRUE(status_or.ok());
1396 auto value = std::move(status_or).value_or(std::make_unique<int>(-1));
1397 EXPECT_EQ(*value, 0);
1398 }
1399
TEST(Result,MoveOnlyValueOrDefault)1400 TEST(Result, MoveOnlyValueOrDefault) {
1401 pw::Result<std::unique_ptr<int>> status_or(pw::Status::Cancelled());
1402 ASSERT_FALSE(status_or.ok());
1403 auto value = std::move(status_or).value_or(std::make_unique<int>(-1));
1404 EXPECT_EQ(*value, -1);
1405 }
1406
MakeStatus()1407 static pw::Result<int> MakeStatus() { return 100; }
1408
TEST(Result,TestIgnoreError)1409 TEST(Result, TestIgnoreError) { MakeStatus().IgnoreError(); }
1410
TEST(Result,EqualityOperator)1411 TEST(Result, EqualityOperator) {
1412 constexpr int kNumCases = 4;
1413 std::array<pw::Result<int>, kNumCases> group1 = {
1414 pw::Result<int>(1),
1415 pw::Result<int>(2),
1416 pw::Result<int>(pw::Status::InvalidArgument()),
1417 pw::Result<int>(pw::Status::Internal())};
1418 std::array<pw::Result<int>, kNumCases> group2 = {
1419 pw::Result<int>(1),
1420 pw::Result<int>(2),
1421 pw::Result<int>(pw::Status::InvalidArgument()),
1422 pw::Result<int>(pw::Status::Internal())};
1423 for (int i = 0; i < kNumCases; ++i) {
1424 for (int j = 0; j < kNumCases; ++j) {
1425 if (i == j) {
1426 EXPECT_TRUE(group1[i] == group2[j]);
1427 EXPECT_FALSE(group1[i] != group2[j]);
1428 } else {
1429 EXPECT_FALSE(group1[i] == group2[j]);
1430 EXPECT_TRUE(group1[i] != group2[j]);
1431 }
1432 }
1433 }
1434 }
1435
1436 struct MyType {
operator ==__anondd8dd5070111::MyType1437 bool operator==(const MyType&) const { return true; }
1438 };
1439
1440 enum class ConvTraits { kNone = 0, kImplicit = 1, kExplicit = 2 };
1441
1442 // This class has conversion operator to `Result<T>` based on value of
1443 // `conv_traits`.
1444 template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
1445 struct ResultConversionBase {};
1446
1447 template <typename T>
1448 struct ResultConversionBase<T, ConvTraits::kImplicit> {
operator pw::Result<T>__anondd8dd5070111::ResultConversionBase1449 operator pw::Result<T>() const& { // NOLINT
1450 return pw::Status::InvalidArgument();
1451 }
operator pw::Result<T>__anondd8dd5070111::ResultConversionBase1452 operator pw::Result<T>() && { // NOLINT
1453 return pw::Status::InvalidArgument();
1454 }
1455 };
1456
1457 template <typename T>
1458 struct ResultConversionBase<T, ConvTraits::kExplicit> {
operator pw::Result<T>__anondd8dd5070111::ResultConversionBase1459 explicit operator pw::Result<T>() const& {
1460 return pw::Status::InvalidArgument();
1461 }
operator pw::Result<T>__anondd8dd5070111::ResultConversionBase1462 explicit operator pw::Result<T>() && { return pw::Status::InvalidArgument(); }
1463 };
1464
1465 // This class has conversion operator to `T` based on the value of
1466 // `conv_traits`.
1467 template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
1468 struct ConversionBase {};
1469
1470 template <typename T>
1471 struct ConversionBase<T, ConvTraits::kImplicit> {
operator T__anondd8dd5070111::ConversionBase1472 operator T() const& { return t; } // NOLINT
operator T__anondd8dd5070111::ConversionBase1473 operator T() && { return std::move(t); } // NOLINT
1474 T t;
1475 };
1476
1477 template <typename T>
1478 struct ConversionBase<T, ConvTraits::kExplicit> {
operator T__anondd8dd5070111::ConversionBase1479 explicit operator T() const& { return t; }
operator T__anondd8dd5070111::ConversionBase1480 explicit operator T() && { return std::move(t); }
1481 T t;
1482 };
1483
1484 // This class has conversion operator to `pw::Status` based on the value of
1485 // `conv_traits`.
1486 template <ConvTraits conv_traits = ConvTraits::kNone>
1487 struct StatusConversionBase {};
1488
1489 template <>
1490 struct StatusConversionBase<ConvTraits::kImplicit> {
operator pw::Status__anondd8dd5070111::StatusConversionBase1491 operator pw::Status() const& { // NOLINT
1492 return pw::Status::Internal();
1493 }
operator pw::Status__anondd8dd5070111::StatusConversionBase1494 operator pw::Status() && { // NOLINT
1495 return pw::Status::Internal();
1496 }
1497 };
1498
1499 template <>
1500 struct StatusConversionBase<ConvTraits::kExplicit> {
operator pw::Status__anondd8dd5070111::StatusConversionBase1501 explicit operator pw::Status() const& { // NOLINT
1502 return pw::Status::Internal();
1503 }
operator pw::Status__anondd8dd5070111::StatusConversionBase1504 explicit operator pw::Status() && { // NOLINT
1505 return pw::Status::Internal();
1506 }
1507 };
1508
1509 static constexpr int kConvToStatus = 1;
1510 static constexpr int kConvToResult = 2;
1511 static constexpr int kConvToT = 4;
1512 static constexpr int kConvExplicit = 8;
1513
GetConvTraits(int bit,int config)1514 constexpr ConvTraits GetConvTraits(int bit, int config) {
1515 return (config & bit) == 0
1516 ? ConvTraits::kNone
1517 : ((config & kConvExplicit) == 0 ? ConvTraits::kImplicit
1518 : ConvTraits::kExplicit);
1519 }
1520
1521 // This class conditionally has conversion operator to `pw::Status`, `T`,
1522 // `Result<T>`, based on values of the template parameters.
1523 template <typename T, int config>
1524 struct CustomType
1525 : ResultConversionBase<T, GetConvTraits(kConvToResult, config)>,
1526 ConversionBase<T, GetConvTraits(kConvToT, config)>,
1527 StatusConversionBase<GetConvTraits(kConvToStatus, config)> {};
1528
1529 struct ConvertibleToAnyResult {
1530 template <typename T>
operator pw::Result<T>__anondd8dd5070111::ConvertibleToAnyResult1531 operator pw::Result<T>() const { // NOLINT
1532 return pw::Status::InvalidArgument();
1533 }
1534 };
1535
1536 // Test the rank of overload resolution for `Result<T>` constructor and
1537 // assignment, from highest to lowest:
1538 // 1. T/Status
1539 // 2. U that has conversion operator to pw::Result<T>
1540 // 3. U that is convertible to Status
1541 // 4. U that is convertible to T
TEST(Result,ConstructionFromT)1542 TEST(Result, ConstructionFromT) {
1543 // Construct pw::Result<T> from T when T is convertible to
1544 // pw::Result<T>
1545 {
1546 ConvertibleToAnyResult v;
1547 pw::Result<ConvertibleToAnyResult> statusor(v);
1548 EXPECT_TRUE(statusor.ok());
1549 }
1550 {
1551 ConvertibleToAnyResult v;
1552 pw::Result<ConvertibleToAnyResult> statusor = v;
1553 EXPECT_TRUE(statusor.ok());
1554 }
1555 // Construct pw::Result<T> from T when T is explicitly convertible to
1556 // Status
1557 {
1558 CustomType<MyType, kConvToStatus | kConvExplicit> v;
1559 pw::Result<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor(v);
1560 EXPECT_TRUE(statusor.ok());
1561 }
1562 {
1563 CustomType<MyType, kConvToStatus | kConvExplicit> v;
1564 pw::Result<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor = v;
1565 EXPECT_TRUE(statusor.ok());
1566 }
1567 }
1568
1569 // Construct pw::Result<T> from U when U is explicitly convertible to T
TEST(Result,ConstructionFromTypeConvertibleToT)1570 TEST(Result, ConstructionFromTypeConvertibleToT) {
1571 {
1572 CustomType<MyType, kConvToT | kConvExplicit> v;
1573 pw::Result<MyType> statusor(v);
1574 EXPECT_TRUE(statusor.ok());
1575 }
1576 {
1577 CustomType<MyType, kConvToT> v;
1578 pw::Result<MyType> statusor = v;
1579 EXPECT_TRUE(statusor.ok());
1580 }
1581 }
1582
1583 // Construct pw::Result<T> from U when U has explicit conversion operator to
1584 // pw::Result<T>
TEST(Result,ConstructionFromTypeWithConversionOperatorToResultT)1585 TEST(Result, ConstructionFromTypeWithConversionOperatorToResultT) {
1586 {
1587 CustomType<MyType, kConvToResult | kConvExplicit> v;
1588 pw::Result<MyType> statusor(v);
1589 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1590 }
1591 {
1592 CustomType<MyType, kConvToT | kConvToResult | kConvExplicit> v;
1593 pw::Result<MyType> statusor(v);
1594 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1595 }
1596 {
1597 CustomType<MyType, kConvToResult | kConvToStatus | kConvExplicit> v;
1598 pw::Result<MyType> statusor(v);
1599 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1600 }
1601 {
1602 CustomType<MyType, kConvToT | kConvToResult | kConvToStatus | kConvExplicit>
1603 v;
1604 pw::Result<MyType> statusor(v);
1605 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1606 }
1607 {
1608 CustomType<MyType, kConvToResult> v;
1609 pw::Result<MyType> statusor = v;
1610 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1611 }
1612 {
1613 CustomType<MyType, kConvToT | kConvToResult> v;
1614 pw::Result<MyType> statusor = v;
1615 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1616 }
1617 {
1618 CustomType<MyType, kConvToResult | kConvToStatus> v;
1619 pw::Result<MyType> statusor = v;
1620 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1621 }
1622 {
1623 CustomType<MyType, kConvToT | kConvToResult | kConvToStatus> v;
1624 pw::Result<MyType> statusor = v;
1625 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1626 }
1627 }
1628
TEST(Result,ConstructionFromTypeConvertibleToStatus)1629 TEST(Result, ConstructionFromTypeConvertibleToStatus) {
1630 // Construction fails because conversion to `Status` is explicit.
1631 {
1632 CustomType<MyType, kConvToStatus | kConvExplicit> v;
1633 pw::Result<MyType> statusor(v);
1634 EXPECT_FALSE(statusor.ok());
1635 EXPECT_EQ(statusor.status(), static_cast<pw::Status>(v));
1636 }
1637 {
1638 CustomType<MyType, kConvToT | kConvToStatus | kConvExplicit> v;
1639 pw::Result<MyType> statusor(v);
1640 EXPECT_FALSE(statusor.ok());
1641 EXPECT_EQ(statusor.status(), static_cast<pw::Status>(v));
1642 }
1643 {
1644 CustomType<MyType, kConvToStatus> v;
1645 pw::Result<MyType> statusor = v;
1646 EXPECT_FALSE(statusor.ok());
1647 EXPECT_EQ(statusor.status(), static_cast<pw::Status>(v));
1648 }
1649 {
1650 CustomType<MyType, kConvToT | kConvToStatus> v;
1651 pw::Result<MyType> statusor = v;
1652 EXPECT_FALSE(statusor.ok());
1653 EXPECT_EQ(statusor.status(), static_cast<pw::Status>(v));
1654 }
1655 }
1656
TEST(Result,AssignmentFromT)1657 TEST(Result, AssignmentFromT) {
1658 // Assign to pw::Result<T> from T when T is convertible to
1659 // pw::Result<T>
1660 {
1661 ConvertibleToAnyResult v;
1662 pw::Result<ConvertibleToAnyResult> statusor;
1663 statusor = v;
1664 EXPECT_TRUE(statusor.ok());
1665 }
1666 // Assign to pw::Result<T> from T when T is convertible to Status
1667 {
1668 CustomType<MyType, kConvToStatus> v;
1669 pw::Result<CustomType<MyType, kConvToStatus>> statusor;
1670 statusor = v;
1671 EXPECT_TRUE(statusor.ok());
1672 }
1673 }
1674
TEST(Result,AssignmentFromTypeConvertibleToT)1675 TEST(Result, AssignmentFromTypeConvertibleToT) {
1676 // Assign to pw::Result<T> from U when U is convertible to T
1677 {
1678 CustomType<MyType, kConvToT> v;
1679 pw::Result<MyType> statusor;
1680 statusor = v;
1681 EXPECT_TRUE(statusor.ok());
1682 }
1683 }
1684
TEST(Result,AssignmentFromTypeWithConversionOperatortoResultT)1685 TEST(Result, AssignmentFromTypeWithConversionOperatortoResultT) {
1686 // Assign to pw::Result<T> from U when U has conversion operator to
1687 // pw::Result<T>
1688 {
1689 CustomType<MyType, kConvToResult> v;
1690 pw::Result<MyType> statusor;
1691 statusor = v;
1692 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1693 }
1694 {
1695 CustomType<MyType, kConvToT | kConvToResult> v;
1696 pw::Result<MyType> statusor;
1697 statusor = v;
1698 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1699 }
1700 {
1701 CustomType<MyType, kConvToResult | kConvToStatus> v;
1702 pw::Result<MyType> statusor;
1703 statusor = v;
1704 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1705 }
1706 {
1707 CustomType<MyType, kConvToT | kConvToResult | kConvToStatus> v;
1708 pw::Result<MyType> statusor;
1709 statusor = v;
1710 EXPECT_EQ(statusor, v.operator pw::Result<MyType>());
1711 }
1712 }
1713
TEST(Result,AssignmentFromTypeConvertibleToStatus)1714 TEST(Result, AssignmentFromTypeConvertibleToStatus) {
1715 // Assign to pw::Result<T> from U when U is convertible to Status
1716 {
1717 CustomType<MyType, kConvToStatus> v;
1718 pw::Result<MyType> statusor;
1719 statusor = v;
1720 EXPECT_FALSE(statusor.ok());
1721 EXPECT_EQ(statusor.status(), static_cast<pw::Status>(v));
1722 }
1723 {
1724 CustomType<MyType, kConvToT | kConvToStatus> v;
1725 pw::Result<MyType> statusor;
1726 statusor = v;
1727 EXPECT_FALSE(statusor.ok());
1728 EXPECT_EQ(statusor.status(), static_cast<pw::Status>(v));
1729 }
1730 }
1731
1732 } // namespace
1733