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