diff options
author | Vincent Ambo <mail@tazj.in> | 2022-02-07T23·05+0300 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2022-02-07T23·09+0000 |
commit | 5aa5d282eac56a21e74611c1cdbaa97bb5db2dca (patch) | |
tree | 8cc5dce8157a1470ff76719dd15d65f648a05522 /third_party/abseil_cpp/absl/status/statusor_test.cc | |
parent | a25675804c4f429fab5ee5201fe25e89865dfd13 (diff) |
chore(3p/abseil_cpp): unvendor abseil_cpp r/3786
we weren't actually using these sources anymore, okay? Change-Id: If701571d9716de308d3512e1eb22c35db0877a66 Reviewed-on: https://cl.tvl.fyi/c/depot/+/5248 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi> Autosubmit: tazjin <tazjin@tvl.su>
Diffstat (limited to 'third_party/abseil_cpp/absl/status/statusor_test.cc')
-rw-r--r-- | third_party/abseil_cpp/absl/status/statusor_test.cc | 1811 |
1 files changed, 0 insertions, 1811 deletions
diff --git a/third_party/abseil_cpp/absl/status/statusor_test.cc b/third_party/abseil_cpp/absl/status/statusor_test.cc deleted file mode 100644 index c2e8fb7e359e..000000000000 --- a/third_party/abseil_cpp/absl/status/statusor_test.cc +++ /dev/null @@ -1,1811 +0,0 @@ -// Copyright 2020 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/status/statusor.h" - -#include <array> -#include <initializer_list> -#include <memory> -#include <type_traits> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/base/casts.h" -#include "absl/memory/memory.h" -#include "absl/status/status.h" -#include "absl/types/any.h" -#include "absl/utility/utility.h" - -namespace { - -using ::testing::AllOf; -using ::testing::AnyWith; -using ::testing::ElementsAre; -using ::testing::Field; -using ::testing::Ne; -using ::testing::Not; -using ::testing::Pointee; -using ::testing::VariantWith; - -#ifdef GTEST_HAS_STATUS_MATCHERS -using ::testing::status::IsOk; -using ::testing::status::IsOkAndHolds; -#else // GTEST_HAS_STATUS_MATCHERS -inline const ::absl::Status& GetStatus(const ::absl::Status& status) { - return status; -} - -template <typename T> -inline const ::absl::Status& GetStatus(const ::absl::StatusOr<T>& status) { - return status.status(); -} - -// Monomorphic implementation of matcher IsOkAndHolds(m). StatusOrType is a -// reference to StatusOr<T>. -template <typename StatusOrType> -class IsOkAndHoldsMatcherImpl - : public ::testing::MatcherInterface<StatusOrType> { - public: - typedef - typename std::remove_reference<StatusOrType>::type::value_type value_type; - - template <typename InnerMatcher> - explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher) - : inner_matcher_(::testing::SafeMatcherCast<const value_type&>( - std::forward<InnerMatcher>(inner_matcher))) {} - - void DescribeTo(std::ostream* os) const override { - *os << "is OK and has a value that "; - inner_matcher_.DescribeTo(os); - } - - void DescribeNegationTo(std::ostream* os) const override { - *os << "isn't OK or has a value that "; - inner_matcher_.DescribeNegationTo(os); - } - - bool MatchAndExplain( - StatusOrType actual_value, - ::testing::MatchResultListener* result_listener) const override { - if (!actual_value.ok()) { - *result_listener << "which has status " << actual_value.status(); - return false; - } - - ::testing::StringMatchResultListener inner_listener; - const bool matches = - inner_matcher_.MatchAndExplain(*actual_value, &inner_listener); - const std::string inner_explanation = inner_listener.str(); - if (!inner_explanation.empty()) { - *result_listener << "which contains value " - << ::testing::PrintToString(*actual_value) << ", " - << inner_explanation; - } - return matches; - } - - private: - const ::testing::Matcher<const value_type&> inner_matcher_; -}; - -// Implements IsOkAndHolds(m) as a polymorphic matcher. -template <typename InnerMatcher> -class IsOkAndHoldsMatcher { - public: - explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher) - : inner_matcher_(std::move(inner_matcher)) {} - - // Converts this polymorphic matcher to a monomorphic matcher of the - // given type. StatusOrType can be either StatusOr<T> or a - // reference to StatusOr<T>. - template <typename StatusOrType> - operator ::testing::Matcher<StatusOrType>() const { // NOLINT - return ::testing::Matcher<StatusOrType>( - new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_)); - } - - private: - const InnerMatcher inner_matcher_; -}; - -// Monomorphic implementation of matcher IsOk() for a given type T. -// T can be Status, StatusOr<>, or a reference to either of them. -template <typename T> -class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> { - public: - void DescribeTo(std::ostream* os) const override { *os << "is OK"; } - void DescribeNegationTo(std::ostream* os) const override { - *os << "is not OK"; - } - bool MatchAndExplain(T actual_value, - ::testing::MatchResultListener*) const override { - return GetStatus(actual_value).ok(); - } -}; - -// Implements IsOk() as a polymorphic matcher. -class IsOkMatcher { - public: - template <typename T> - operator ::testing::Matcher<T>() const { // NOLINT - return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<T>()); - } -}; - -// Macros for testing the results of functions that return absl::Status or -// absl::StatusOr<T> (for any type T). -#define EXPECT_OK(expression) EXPECT_THAT(expression, IsOk()) - -// Returns a gMock matcher that matches a StatusOr<> whose status is -// OK and whose value matches the inner matcher. -template <typename InnerMatcher> -IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type> IsOkAndHolds( - InnerMatcher&& inner_matcher) { - return IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>( - std::forward<InnerMatcher>(inner_matcher)); -} - -// Returns a gMock matcher that matches a Status or StatusOr<> which is OK. -inline IsOkMatcher IsOk() { return IsOkMatcher(); } -#endif // GTEST_HAS_STATUS_MATCHERS - -struct CopyDetector { - CopyDetector() = default; - explicit CopyDetector(int xx) : x(xx) {} - CopyDetector(CopyDetector&& d) noexcept - : x(d.x), copied(false), moved(true) {} - CopyDetector(const CopyDetector& d) : x(d.x), copied(true), moved(false) {} - CopyDetector& operator=(const CopyDetector& c) { - x = c.x; - copied = true; - moved = false; - return *this; - } - CopyDetector& operator=(CopyDetector&& c) noexcept { - x = c.x; - copied = false; - moved = true; - return *this; - } - int x = 0; - bool copied = false; - bool moved = false; -}; - -testing::Matcher<const CopyDetector&> CopyDetectorHas(int a, bool b, bool c) { - return AllOf(Field(&CopyDetector::x, a), Field(&CopyDetector::moved, b), - Field(&CopyDetector::copied, c)); -} - -class Base1 { - public: - virtual ~Base1() {} - int pad; -}; - -class Base2 { - public: - virtual ~Base2() {} - int yetotherpad; -}; - -class Derived : public Base1, public Base2 { - public: - virtual ~Derived() {} - int evenmorepad; -}; - -class CopyNoAssign { - public: - explicit CopyNoAssign(int value) : foo(value) {} - CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {} - int foo; - - private: - const CopyNoAssign& operator=(const CopyNoAssign&); -}; - -absl::StatusOr<std::unique_ptr<int>> ReturnUniquePtr() { - // Uses implicit constructor from T&& - return absl::make_unique<int>(0); -} - -TEST(StatusOr, ElementType) { - static_assert(std::is_same<absl::StatusOr<int>::value_type, int>(), ""); - static_assert(std::is_same<absl::StatusOr<char>::value_type, char>(), ""); -} - -TEST(StatusOr, TestMoveOnlyInitialization) { - absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr()); - ASSERT_TRUE(thing.ok()); - EXPECT_EQ(0, **thing); - int* previous = thing->get(); - - thing = ReturnUniquePtr(); - EXPECT_TRUE(thing.ok()); - EXPECT_EQ(0, **thing); - EXPECT_NE(previous, thing->get()); -} - -TEST(StatusOr, TestMoveOnlyValueExtraction) { - absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr()); - ASSERT_TRUE(thing.ok()); - std::unique_ptr<int> ptr = *std::move(thing); - EXPECT_EQ(0, *ptr); - - thing = std::move(ptr); - ptr = std::move(*thing); - EXPECT_EQ(0, *ptr); -} - -TEST(StatusOr, TestMoveOnlyInitializationFromTemporaryByValueOrDie) { - std::unique_ptr<int> ptr(*ReturnUniquePtr()); - EXPECT_EQ(0, *ptr); -} - -TEST(StatusOr, TestValueOrDieOverloadForConstTemporary) { - static_assert( - std::is_same<const int&&, - decltype( - std::declval<const absl::StatusOr<int>&&>().value())>(), - "value() for const temporaries should return const T&&"); -} - -TEST(StatusOr, TestMoveOnlyConversion) { - absl::StatusOr<std::unique_ptr<const int>> const_thing(ReturnUniquePtr()); - EXPECT_TRUE(const_thing.ok()); - EXPECT_EQ(0, **const_thing); - - // Test rvalue converting assignment - const int* const_previous = const_thing->get(); - const_thing = ReturnUniquePtr(); - EXPECT_TRUE(const_thing.ok()); - EXPECT_EQ(0, **const_thing); - EXPECT_NE(const_previous, const_thing->get()); -} - -TEST(StatusOr, TestMoveOnlyVector) { - // Sanity check that absl::StatusOr<MoveOnly> works in vector. - std::vector<absl::StatusOr<std::unique_ptr<int>>> vec; - vec.push_back(ReturnUniquePtr()); - vec.resize(2); - auto another_vec = std::move(vec); - EXPECT_EQ(0, **another_vec[0]); - EXPECT_EQ(absl::UnknownError(""), another_vec[1].status()); -} - -TEST(StatusOr, TestDefaultCtor) { - absl::StatusOr<int> thing; - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown); -} - -TEST(StatusOr, StatusCtorForwards) { - absl::Status status(absl::StatusCode::kInternal, "Some error"); - - EXPECT_EQ(absl::StatusOr<int>(status).status().message(), "Some error"); - EXPECT_EQ(status.message(), "Some error"); - - EXPECT_EQ(absl::StatusOr<int>(std::move(status)).status().message(), - "Some error"); - EXPECT_NE(status.message(), "Some error"); -} - -// Define `EXPECT_DEATH_OR_THROW` to test the behavior of `StatusOr::value`, -// which either throws `BadStatusOrAccess` or `LOG(FATAL)` based on whether -// exceptions are enabled. -#ifdef ABSL_HAVE_EXCEPTIONS -#define EXPECT_DEATH_OR_THROW(statement, status_) \ - EXPECT_THROW( \ - { \ - try { \ - statement; \ - } catch (const absl::BadStatusOrAccess& e) { \ - EXPECT_EQ(e.status(), status_); \ - throw; \ - } \ - }, \ - absl::BadStatusOrAccess); -#else // ABSL_HAVE_EXCEPTIONS -#define EXPECT_DEATH_OR_THROW(statement, status) \ - EXPECT_DEATH_IF_SUPPORTED(statement, status.ToString()); -#endif // ABSL_HAVE_EXCEPTIONS - -TEST(StatusOrDeathTest, TestDefaultCtorValue) { - absl::StatusOr<int> thing; - EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError("")); - const absl::StatusOr<int> thing2; - EXPECT_DEATH_OR_THROW(thing2.value(), absl::UnknownError("")); -} - -TEST(StatusOrDeathTest, TestValueNotOk) { - absl::StatusOr<int> thing(absl::CancelledError()); - EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError()); -} - -TEST(StatusOrDeathTest, TestValueNotOkConst) { - const absl::StatusOr<int> thing(absl::UnknownError("")); - EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError("")); -} - -TEST(StatusOrDeathTest, TestPointerDefaultCtorValue) { - absl::StatusOr<int*> thing; - EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError("")); -} - -TEST(StatusOrDeathTest, TestPointerValueNotOk) { - absl::StatusOr<int*> thing(absl::CancelledError()); - EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError()); -} - -TEST(StatusOrDeathTest, TestPointerValueNotOkConst) { - const absl::StatusOr<int*> thing(absl::CancelledError()); - EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError()); -} - -#if GTEST_HAS_DEATH_TEST -TEST(StatusOrDeathTest, TestStatusCtorStatusOk) { - EXPECT_DEBUG_DEATH( - { - // This will DCHECK - absl::StatusOr<int> thing(absl::OkStatus()); - // In optimized mode, we are actually going to get error::INTERNAL for - // status here, rather than crashing, so check that. - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal); - }, - "An OK status is not a valid constructor argument"); -} - -TEST(StatusOrDeathTest, TestPointerStatusCtorStatusOk) { - EXPECT_DEBUG_DEATH( - { - absl::StatusOr<int*> thing(absl::OkStatus()); - // In optimized mode, we are actually going to get error::INTERNAL for - // status here, rather than crashing, so check that. - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal); - }, - "An OK status is not a valid constructor argument"); -} -#endif - -TEST(StatusOr, ValueAccessor) { - const int kIntValue = 110; - { - absl::StatusOr<int> status_or(kIntValue); - EXPECT_EQ(kIntValue, status_or.value()); - EXPECT_EQ(kIntValue, std::move(status_or).value()); - } - { - absl::StatusOr<CopyDetector> status_or(kIntValue); - EXPECT_THAT(status_or, - IsOkAndHolds(CopyDetectorHas(kIntValue, false, false))); - CopyDetector copy_detector = status_or.value(); - EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, false, true)); - copy_detector = std::move(status_or).value(); - EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, true, false)); - } -} - -TEST(StatusOr, BadValueAccess) { - const absl::Status kError = absl::CancelledError("message"); - absl::StatusOr<int> status_or(kError); - EXPECT_DEATH_OR_THROW(status_or.value(), kError); -} - -TEST(StatusOr, TestStatusCtor) { - absl::StatusOr<int> thing(absl::CancelledError()); - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled); -} - - - -TEST(StatusOr, TestValueCtor) { - const int kI = 4; - const absl::StatusOr<int> thing(kI); - EXPECT_TRUE(thing.ok()); - EXPECT_EQ(kI, *thing); -} - -struct Foo { - const int x; - explicit Foo(int y) : x(y) {} -}; - -TEST(StatusOr, InPlaceConstruction) { - EXPECT_THAT(absl::StatusOr<Foo>(absl::in_place, 10), - IsOkAndHolds(Field(&Foo::x, 10))); -} - -struct InPlaceHelper { - InPlaceHelper(std::initializer_list<int> xs, std::unique_ptr<int> yy) - : x(xs), y(std::move(yy)) {} - const std::vector<int> x; - std::unique_ptr<int> y; -}; - -TEST(StatusOr, InPlaceInitListConstruction) { - absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12}, - absl::make_unique<int>(13)); - EXPECT_THAT(status_or, IsOkAndHolds(AllOf( - Field(&InPlaceHelper::x, ElementsAre(10, 11, 12)), - Field(&InPlaceHelper::y, Pointee(13))))); -} - -TEST(StatusOr, Emplace) { - absl::StatusOr<Foo> status_or_foo(10); - status_or_foo.emplace(20); - EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20))); - status_or_foo = absl::InvalidArgumentError("msg"); - EXPECT_FALSE(status_or_foo.ok()); - EXPECT_EQ(status_or_foo.status().code(), absl::StatusCode::kInvalidArgument); - EXPECT_EQ(status_or_foo.status().message(), "msg"); - status_or_foo.emplace(20); - EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20))); -} - -TEST(StatusOr, EmplaceInitializerList) { - absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12}, - absl::make_unique<int>(13)); - status_or.emplace({1, 2, 3}, absl::make_unique<int>(4)); - EXPECT_THAT(status_or, - IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)), - Field(&InPlaceHelper::y, Pointee(4))))); - status_or = absl::InvalidArgumentError("msg"); - EXPECT_FALSE(status_or.ok()); - EXPECT_EQ(status_or.status().code(), absl::StatusCode::kInvalidArgument); - EXPECT_EQ(status_or.status().message(), "msg"); - status_or.emplace({1, 2, 3}, absl::make_unique<int>(4)); - EXPECT_THAT(status_or, - IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)), - Field(&InPlaceHelper::y, Pointee(4))))); -} - -TEST(StatusOr, TestCopyCtorStatusOk) { - const int kI = 4; - const absl::StatusOr<int> original(kI); - const absl::StatusOr<int> copy(original); - EXPECT_OK(copy.status()); - EXPECT_EQ(*original, *copy); -} - -TEST(StatusOr, TestCopyCtorStatusNotOk) { - absl::StatusOr<int> original(absl::CancelledError()); - absl::StatusOr<int> copy(original); - EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestCopyCtorNonAssignable) { - const int kI = 4; - CopyNoAssign value(kI); - absl::StatusOr<CopyNoAssign> original(value); - absl::StatusOr<CopyNoAssign> copy(original); - EXPECT_OK(copy.status()); - EXPECT_EQ(original->foo, copy->foo); -} - -TEST(StatusOr, TestCopyCtorStatusOKConverting) { - const int kI = 4; - absl::StatusOr<int> original(kI); - absl::StatusOr<double> copy(original); - EXPECT_OK(copy.status()); - EXPECT_DOUBLE_EQ(*original, *copy); -} - -TEST(StatusOr, TestCopyCtorStatusNotOkConverting) { - absl::StatusOr<int> original(absl::CancelledError()); - absl::StatusOr<double> copy(original); - EXPECT_EQ(copy.status(), original.status()); -} - -TEST(StatusOr, TestAssignmentStatusOk) { - // Copy assignmment - { - const auto p = std::make_shared<int>(17); - absl::StatusOr<std::shared_ptr<int>> source(p); - - absl::StatusOr<std::shared_ptr<int>> target; - target = source; - - ASSERT_TRUE(target.ok()); - EXPECT_OK(target.status()); - EXPECT_EQ(p, *target); - - ASSERT_TRUE(source.ok()); - EXPECT_OK(source.status()); - EXPECT_EQ(p, *source); - } - - // Move asssignment - { - const auto p = std::make_shared<int>(17); - absl::StatusOr<std::shared_ptr<int>> source(p); - - absl::StatusOr<std::shared_ptr<int>> target; - target = std::move(source); - - ASSERT_TRUE(target.ok()); - EXPECT_OK(target.status()); - EXPECT_EQ(p, *target); - - ASSERT_TRUE(source.ok()); - EXPECT_OK(source.status()); - EXPECT_EQ(nullptr, *source); - } -} - -TEST(StatusOr, TestAssignmentStatusNotOk) { - // Copy assignment - { - const absl::Status expected = absl::CancelledError(); - absl::StatusOr<int> source(expected); - - absl::StatusOr<int> target; - target = source; - - EXPECT_FALSE(target.ok()); - EXPECT_EQ(expected, target.status()); - - EXPECT_FALSE(source.ok()); - EXPECT_EQ(expected, source.status()); - } - - // Move assignment - { - const absl::Status expected = absl::CancelledError(); - absl::StatusOr<int> source(expected); - - absl::StatusOr<int> target; - target = std::move(source); - - EXPECT_FALSE(target.ok()); - EXPECT_EQ(expected, target.status()); - - EXPECT_FALSE(source.ok()); - EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal); - } -} - -TEST(StatusOr, TestAssignmentStatusOKConverting) { - // Copy assignment - { - const int kI = 4; - absl::StatusOr<int> source(kI); - - absl::StatusOr<double> target; - target = source; - - ASSERT_TRUE(target.ok()); - EXPECT_OK(target.status()); - EXPECT_DOUBLE_EQ(kI, *target); - - ASSERT_TRUE(source.ok()); - EXPECT_OK(source.status()); - EXPECT_DOUBLE_EQ(kI, *source); - } - - // Move assignment - { - const auto p = new int(17); - absl::StatusOr<std::unique_ptr<int>> source(absl::WrapUnique(p)); - - absl::StatusOr<std::shared_ptr<int>> target; - target = std::move(source); - - ASSERT_TRUE(target.ok()); - EXPECT_OK(target.status()); - EXPECT_EQ(p, target->get()); - - ASSERT_TRUE(source.ok()); - EXPECT_OK(source.status()); - EXPECT_EQ(nullptr, source->get()); - } -} - -struct A { - int x; -}; - -struct ImplicitConstructibleFromA { - int x; - bool moved; - ImplicitConstructibleFromA(const A& a) // NOLINT - : x(a.x), moved(false) {} - ImplicitConstructibleFromA(A&& a) // NOLINT - : x(a.x), moved(true) {} -}; - -TEST(StatusOr, ImplicitConvertingConstructor) { - EXPECT_THAT( - absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>( - absl::StatusOr<A>(A{11})), - IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 11), - Field(&ImplicitConstructibleFromA::moved, true)))); - absl::StatusOr<A> a(A{12}); - EXPECT_THAT( - absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(a), - IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 12), - Field(&ImplicitConstructibleFromA::moved, false)))); -} - -struct ExplicitConstructibleFromA { - int x; - bool moved; - explicit ExplicitConstructibleFromA(const A& a) : x(a.x), moved(false) {} - explicit ExplicitConstructibleFromA(A&& a) : x(a.x), moved(true) {} -}; - -TEST(StatusOr, ExplicitConvertingConstructor) { - EXPECT_FALSE( - (std::is_convertible<const absl::StatusOr<A>&, - absl::StatusOr<ExplicitConstructibleFromA>>::value)); - EXPECT_FALSE( - (std::is_convertible<absl::StatusOr<A>&&, - absl::StatusOr<ExplicitConstructibleFromA>>::value)); - EXPECT_THAT( - absl::StatusOr<ExplicitConstructibleFromA>(absl::StatusOr<A>(A{11})), - IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 11), - Field(&ExplicitConstructibleFromA::moved, true)))); - absl::StatusOr<A> a(A{12}); - EXPECT_THAT( - absl::StatusOr<ExplicitConstructibleFromA>(a), - IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 12), - Field(&ExplicitConstructibleFromA::moved, false)))); -} - -struct ImplicitConstructibleFromBool { - ImplicitConstructibleFromBool(bool y) : x(y) {} // NOLINT - bool x = false; -}; - -struct ConvertibleToBool { - explicit ConvertibleToBool(bool y) : x(y) {} - operator bool() const { return x; } // NOLINT - bool x = false; -}; - -TEST(StatusOr, ImplicitBooleanConstructionWithImplicitCasts) { - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT( - absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromBool>>( - absl::StatusOr<bool>(false)), - IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false))); - EXPECT_FALSE((std::is_convertible< - absl::StatusOr<ConvertibleToBool>, - absl::StatusOr<ImplicitConstructibleFromBool>>::value)); -} - -TEST(StatusOr, BooleanConstructionWithImplicitCasts) { - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT( - absl::StatusOr<ImplicitConstructibleFromBool>{ - absl::StatusOr<bool>(false)}, - IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false))); - EXPECT_THAT( - absl::StatusOr<ImplicitConstructibleFromBool>{ - absl::StatusOr<bool>(absl::InvalidArgumentError(""))}, - Not(IsOk())); - - EXPECT_THAT( - absl::StatusOr<ImplicitConstructibleFromBool>{ - absl::StatusOr<ConvertibleToBool>(ConvertibleToBool{false})}, - IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false))); - EXPECT_THAT( - absl::StatusOr<ImplicitConstructibleFromBool>{ - absl::StatusOr<ConvertibleToBool>(absl::InvalidArgumentError(""))}, - Not(IsOk())); -} - -TEST(StatusOr, ConstImplicitCast) { - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>( - absl::StatusOr<const bool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>( - absl::StatusOr<const bool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>( - absl::StatusOr<bool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>( - absl::StatusOr<bool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const std::string>>( - absl::StatusOr<std::string>("foo")), - IsOkAndHolds("foo")); - EXPECT_THAT(absl::implicit_cast<absl::StatusOr<std::string>>( - absl::StatusOr<const std::string>("foo")), - IsOkAndHolds("foo")); - EXPECT_THAT( - absl::implicit_cast<absl::StatusOr<std::shared_ptr<const std::string>>>( - absl::StatusOr<std::shared_ptr<std::string>>( - std::make_shared<std::string>("foo"))), - IsOkAndHolds(Pointee(std::string("foo")))); -} - -TEST(StatusOr, ConstExplicitConstruction) { - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(false)), - IsOkAndHolds(false)); - EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(true)), - IsOkAndHolds(true)); - EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(false)), - IsOkAndHolds(false)); -} - -struct ExplicitConstructibleFromInt { - int x; - explicit ExplicitConstructibleFromInt(int y) : x(y) {} -}; - -TEST(StatusOr, ExplicitConstruction) { - EXPECT_THAT(absl::StatusOr<ExplicitConstructibleFromInt>(10), - IsOkAndHolds(Field(&ExplicitConstructibleFromInt::x, 10))); -} - -TEST(StatusOr, ImplicitConstruction) { - // Check implicit casting works. - auto status_or = - absl::implicit_cast<absl::StatusOr<absl::variant<int, std::string>>>(10); - EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10))); -} - -TEST(StatusOr, ImplicitConstructionFromInitliazerList) { - // Note: dropping the explicit std::initializer_list<int> is not supported - // by absl::StatusOr or absl::optional. - auto status_or = - absl::implicit_cast<absl::StatusOr<std::vector<int>>>({{10, 20, 30}}); - EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30))); -} - -TEST(StatusOr, UniquePtrImplicitConstruction) { - auto status_or = absl::implicit_cast<absl::StatusOr<std::unique_ptr<Base1>>>( - absl::make_unique<Derived>()); - EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr))); -} - -TEST(StatusOr, NestedStatusOrCopyAndMoveConstructorTests) { - absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10); - absl::StatusOr<absl::StatusOr<CopyDetector>> status_error = - absl::InvalidArgumentError("foo"); - EXPECT_THAT(status_or, - IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false)))); - absl::StatusOr<absl::StatusOr<CopyDetector>> a = status_or; - EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true)))); - absl::StatusOr<absl::StatusOr<CopyDetector>> a_err = status_error; - EXPECT_THAT(a_err, Not(IsOk())); - - const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or; - absl::StatusOr<absl::StatusOr<CopyDetector>> b = cref; // NOLINT - EXPECT_THAT(b, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true)))); - const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error; - absl::StatusOr<absl::StatusOr<CopyDetector>> b_err = cref_err; // NOLINT - EXPECT_THAT(b_err, Not(IsOk())); - - absl::StatusOr<absl::StatusOr<CopyDetector>> c = std::move(status_or); - EXPECT_THAT(c, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false)))); - absl::StatusOr<absl::StatusOr<CopyDetector>> c_err = std::move(status_error); - EXPECT_THAT(c_err, Not(IsOk())); -} - -TEST(StatusOr, NestedStatusOrCopyAndMoveAssignment) { - absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10); - absl::StatusOr<absl::StatusOr<CopyDetector>> status_error = - absl::InvalidArgumentError("foo"); - absl::StatusOr<absl::StatusOr<CopyDetector>> a; - a = status_or; - EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true)))); - a = status_error; - EXPECT_THAT(a, Not(IsOk())); - - const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or; - a = cref; - EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true)))); - const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error; - a = cref_err; - EXPECT_THAT(a, Not(IsOk())); - a = std::move(status_or); - EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false)))); - a = std::move(status_error); - EXPECT_THAT(a, Not(IsOk())); -} - -struct Copyable { - Copyable() {} - Copyable(const Copyable&) {} - Copyable& operator=(const Copyable&) { return *this; } -}; - -struct MoveOnly { - MoveOnly() {} - MoveOnly(MoveOnly&&) {} - MoveOnly& operator=(MoveOnly&&) { return *this; } -}; - -struct NonMovable { - NonMovable() {} - NonMovable(const NonMovable&) = delete; - NonMovable(NonMovable&&) = delete; - NonMovable& operator=(const NonMovable&) = delete; - NonMovable& operator=(NonMovable&&) = delete; -}; - -TEST(StatusOr, CopyAndMoveAbility) { - EXPECT_TRUE(std::is_copy_constructible<Copyable>::value); - EXPECT_TRUE(std::is_copy_assignable<Copyable>::value); - EXPECT_TRUE(std::is_move_constructible<Copyable>::value); - EXPECT_TRUE(std::is_move_assignable<Copyable>::value); - EXPECT_FALSE(std::is_copy_constructible<MoveOnly>::value); - EXPECT_FALSE(std::is_copy_assignable<MoveOnly>::value); - EXPECT_TRUE(std::is_move_constructible<MoveOnly>::value); - EXPECT_TRUE(std::is_move_assignable<MoveOnly>::value); - EXPECT_FALSE(std::is_copy_constructible<NonMovable>::value); - EXPECT_FALSE(std::is_copy_assignable<NonMovable>::value); - EXPECT_FALSE(std::is_move_constructible<NonMovable>::value); - EXPECT_FALSE(std::is_move_assignable<NonMovable>::value); -} - -TEST(StatusOr, StatusOrAnyCopyAndMoveConstructorTests) { - absl::StatusOr<absl::any> status_or = CopyDetector(10); - absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo"); - EXPECT_THAT( - status_or, - IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false)))); - absl::StatusOr<absl::any> a = status_or; - EXPECT_THAT( - a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true)))); - absl::StatusOr<absl::any> a_err = status_error; - EXPECT_THAT(a_err, Not(IsOk())); - - const absl::StatusOr<absl::any>& cref = status_or; - // No lint for no-change copy. - absl::StatusOr<absl::any> b = cref; // NOLINT - EXPECT_THAT( - b, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true)))); - const absl::StatusOr<absl::any>& cref_err = status_error; - // No lint for no-change copy. - absl::StatusOr<absl::any> b_err = cref_err; // NOLINT - EXPECT_THAT(b_err, Not(IsOk())); - - absl::StatusOr<absl::any> c = std::move(status_or); - EXPECT_THAT( - c, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false)))); - absl::StatusOr<absl::any> c_err = std::move(status_error); - EXPECT_THAT(c_err, Not(IsOk())); -} - -TEST(StatusOr, StatusOrAnyCopyAndMoveAssignment) { - absl::StatusOr<absl::any> status_or = CopyDetector(10); - absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo"); - absl::StatusOr<absl::any> a; - a = status_or; - EXPECT_THAT( - a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true)))); - a = status_error; - EXPECT_THAT(a, Not(IsOk())); - - const absl::StatusOr<absl::any>& cref = status_or; - a = cref; - EXPECT_THAT( - a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true)))); - const absl::StatusOr<absl::any>& cref_err = status_error; - a = cref_err; - EXPECT_THAT(a, Not(IsOk())); - a = std::move(status_or); - EXPECT_THAT( - a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false)))); - a = std::move(status_error); - EXPECT_THAT(a, Not(IsOk())); -} - -TEST(StatusOr, StatusOrCopyAndMoveTestsConstructor) { - absl::StatusOr<CopyDetector> status_or(10); - ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false))); - absl::StatusOr<CopyDetector> a(status_or); - EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true))); - const absl::StatusOr<CopyDetector>& cref = status_or; - absl::StatusOr<CopyDetector> b(cref); // NOLINT - EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true))); - absl::StatusOr<CopyDetector> c(std::move(status_or)); - EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false))); -} - -TEST(StatusOr, StatusOrCopyAndMoveTestsAssignment) { - absl::StatusOr<CopyDetector> status_or(10); - ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false))); - absl::StatusOr<CopyDetector> a; - a = status_or; - EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true))); - const absl::StatusOr<CopyDetector>& cref = status_or; - absl::StatusOr<CopyDetector> b; - b = cref; - EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true))); - absl::StatusOr<CopyDetector> c; - c = std::move(status_or); - EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false))); -} - -TEST(StatusOr, AbslAnyAssignment) { - EXPECT_FALSE((std::is_assignable<absl::StatusOr<absl::any>, - absl::StatusOr<int>>::value)); - absl::StatusOr<absl::any> status_or; - status_or = absl::InvalidArgumentError("foo"); - EXPECT_THAT(status_or, Not(IsOk())); -} - -TEST(StatusOr, ImplicitAssignment) { - absl::StatusOr<absl::variant<int, std::string>> status_or; - status_or = 10; - EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10))); -} - -TEST(StatusOr, SelfDirectInitAssignment) { - absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}}; - status_or = *status_or; - EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30))); -} - -TEST(StatusOr, ImplicitCastFromInitializerList) { - absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}}; - EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30))); -} - -TEST(StatusOr, UniquePtrImplicitAssignment) { - absl::StatusOr<std::unique_ptr<Base1>> status_or; - status_or = absl::make_unique<Derived>(); - EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr))); -} - -TEST(StatusOr, Pointer) { - struct A {}; - struct B : public A {}; - struct C : private A {}; - - EXPECT_TRUE((std::is_constructible<absl::StatusOr<A*>, B*>::value)); - EXPECT_TRUE((std::is_convertible<B*, absl::StatusOr<A*>>::value)); - EXPECT_FALSE((std::is_constructible<absl::StatusOr<A*>, C*>::value)); - EXPECT_FALSE((std::is_convertible<C*, absl::StatusOr<A*>>::value)); -} - -TEST(StatusOr, TestAssignmentStatusNotOkConverting) { - // Copy assignment - { - const absl::Status expected = absl::CancelledError(); - absl::StatusOr<int> source(expected); - - absl::StatusOr<double> target; - target = source; - - EXPECT_FALSE(target.ok()); - EXPECT_EQ(expected, target.status()); - - EXPECT_FALSE(source.ok()); - EXPECT_EQ(expected, source.status()); - } - - // Move assignment - { - const absl::Status expected = absl::CancelledError(); - absl::StatusOr<int> source(expected); - - absl::StatusOr<double> target; - target = std::move(source); - - EXPECT_FALSE(target.ok()); - EXPECT_EQ(expected, target.status()); - - EXPECT_FALSE(source.ok()); - EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal); - } -} - -TEST(StatusOr, SelfAssignment) { - // Copy-assignment, status OK - { - // A string long enough that it's likely to defeat any inline representation - // optimization. - const std::string long_str(128, 'a'); - - absl::StatusOr<std::string> so = long_str; - so = *&so; - - ASSERT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(long_str, *so); - } - - // Copy-assignment, error status - { - absl::StatusOr<int> so = absl::NotFoundError("taco"); - so = *&so; - - EXPECT_FALSE(so.ok()); - EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound); - EXPECT_EQ(so.status().message(), "taco"); - } - - // Move-assignment with copyable type, status OK - { - absl::StatusOr<int> so = 17; - - // Fool the compiler, which otherwise complains. - auto& same = so; - so = std::move(same); - - ASSERT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(17, *so); - } - - // Move-assignment with copyable type, error status - { - absl::StatusOr<int> so = absl::NotFoundError("taco"); - - // Fool the compiler, which otherwise complains. - auto& same = so; - so = std::move(same); - - EXPECT_FALSE(so.ok()); - EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound); - EXPECT_EQ(so.status().message(), "taco"); - } - - // Move-assignment with non-copyable type, status OK - { - const auto raw = new int(17); - absl::StatusOr<std::unique_ptr<int>> so = absl::WrapUnique(raw); - - // Fool the compiler, which otherwise complains. - auto& same = so; - so = std::move(same); - - ASSERT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(raw, so->get()); - } - - // Move-assignment with non-copyable type, error status - { - absl::StatusOr<std::unique_ptr<int>> so = absl::NotFoundError("taco"); - - // Fool the compiler, which otherwise complains. - auto& same = so; - so = std::move(same); - - EXPECT_FALSE(so.ok()); - EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound); - EXPECT_EQ(so.status().message(), "taco"); - } -} - -// These types form the overload sets of the constructors and the assignment -// operators of `MockValue`. They distinguish construction from assignment, -// lvalue from rvalue. -struct FromConstructibleAssignableLvalue {}; -struct FromConstructibleAssignableRvalue {}; -struct FromImplicitConstructibleOnly {}; -struct FromAssignableOnly {}; - -// This class is for testing the forwarding value assignments of `StatusOr`. -// `from_rvalue` indicates whether the constructor or the assignment taking -// rvalue reference is called. `from_assignment` indicates whether any -// assignment is called. -struct MockValue { - // Constructs `MockValue` from `FromConstructibleAssignableLvalue`. - MockValue(const FromConstructibleAssignableLvalue&) // NOLINT - : from_rvalue(false), assigned(false) {} - // Constructs `MockValue` from `FromConstructibleAssignableRvalue`. - MockValue(FromConstructibleAssignableRvalue&&) // NOLINT - : from_rvalue(true), assigned(false) {} - // Constructs `MockValue` from `FromImplicitConstructibleOnly`. - // `MockValue` is not assignable from `FromImplicitConstructibleOnly`. - MockValue(const FromImplicitConstructibleOnly&) // NOLINT - : from_rvalue(false), assigned(false) {} - // Assigns `FromConstructibleAssignableLvalue`. - MockValue& operator=(const FromConstructibleAssignableLvalue&) { - from_rvalue = false; - assigned = true; - return *this; - } - // Assigns `FromConstructibleAssignableRvalue` (rvalue only). - MockValue& operator=(FromConstructibleAssignableRvalue&&) { - from_rvalue = true; - assigned = true; - return *this; - } - // Assigns `FromAssignableOnly`, but not constructible from - // `FromAssignableOnly`. - MockValue& operator=(const FromAssignableOnly&) { - from_rvalue = false; - assigned = true; - return *this; - } - bool from_rvalue; - bool assigned; -}; - -// operator=(U&&) -TEST(StatusOr, PerfectForwardingAssignment) { - // U == T - constexpr int kValue1 = 10, kValue2 = 20; - absl::StatusOr<CopyDetector> status_or; - CopyDetector lvalue(kValue1); - status_or = lvalue; - EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue1, false, true))); - status_or = CopyDetector(kValue2); - EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue2, true, false))); - - // U != T - EXPECT_TRUE( - (std::is_assignable<absl::StatusOr<MockValue>&, - const FromConstructibleAssignableLvalue&>::value)); - EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&, - FromConstructibleAssignableLvalue&&>::value)); - EXPECT_FALSE( - (std::is_assignable<absl::StatusOr<MockValue>&, - const FromConstructibleAssignableRvalue&>::value)); - EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&, - FromConstructibleAssignableRvalue&&>::value)); - EXPECT_TRUE( - (std::is_assignable<absl::StatusOr<MockValue>&, - const FromImplicitConstructibleOnly&>::value)); - EXPECT_FALSE((std::is_assignable<absl::StatusOr<MockValue>&, - const FromAssignableOnly&>::value)); - - absl::StatusOr<MockValue> from_lvalue(FromConstructibleAssignableLvalue{}); - EXPECT_FALSE(from_lvalue->from_rvalue); - EXPECT_FALSE(from_lvalue->assigned); - from_lvalue = FromConstructibleAssignableLvalue{}; - EXPECT_FALSE(from_lvalue->from_rvalue); - EXPECT_TRUE(from_lvalue->assigned); - - absl::StatusOr<MockValue> from_rvalue(FromConstructibleAssignableRvalue{}); - EXPECT_TRUE(from_rvalue->from_rvalue); - EXPECT_FALSE(from_rvalue->assigned); - from_rvalue = FromConstructibleAssignableRvalue{}; - EXPECT_TRUE(from_rvalue->from_rvalue); - EXPECT_TRUE(from_rvalue->assigned); - - absl::StatusOr<MockValue> from_implicit_constructible( - FromImplicitConstructibleOnly{}); - EXPECT_FALSE(from_implicit_constructible->from_rvalue); - EXPECT_FALSE(from_implicit_constructible->assigned); - // construct a temporary `StatusOr` object and invoke the `StatusOr` move - // assignment operator. - from_implicit_constructible = FromImplicitConstructibleOnly{}; - EXPECT_FALSE(from_implicit_constructible->from_rvalue); - EXPECT_FALSE(from_implicit_constructible->assigned); -} - -TEST(StatusOr, TestStatus) { - absl::StatusOr<int> good(4); - EXPECT_TRUE(good.ok()); - absl::StatusOr<int> bad(absl::CancelledError()); - EXPECT_FALSE(bad.ok()); - EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, OperatorStarRefQualifiers) { - static_assert( - std::is_same<const int&, - decltype(*std::declval<const absl::StatusOr<int>&>())>(), - "Unexpected ref-qualifiers"); - static_assert( - std::is_same<int&, decltype(*std::declval<absl::StatusOr<int>&>())>(), - "Unexpected ref-qualifiers"); - static_assert( - std::is_same<const int&&, - decltype(*std::declval<const absl::StatusOr<int>&&>())>(), - "Unexpected ref-qualifiers"); - static_assert( - std::is_same<int&&, decltype(*std::declval<absl::StatusOr<int>&&>())>(), - "Unexpected ref-qualifiers"); -} - -TEST(StatusOr, OperatorStar) { - const absl::StatusOr<std::string> const_lvalue("hello"); - EXPECT_EQ("hello", *const_lvalue); - - absl::StatusOr<std::string> lvalue("hello"); - EXPECT_EQ("hello", *lvalue); - - // Note: Recall that std::move() is equivalent to a static_cast to an rvalue - // reference type. - const absl::StatusOr<std::string> const_rvalue("hello"); - EXPECT_EQ("hello", *std::move(const_rvalue)); // NOLINT - - absl::StatusOr<std::string> rvalue("hello"); - EXPECT_EQ("hello", *std::move(rvalue)); -} - -TEST(StatusOr, OperatorArrowQualifiers) { - static_assert( - std::is_same< - const int*, - decltype(std::declval<const absl::StatusOr<int>&>().operator->())>(), - "Unexpected qualifiers"); - static_assert( - std::is_same< - int*, decltype(std::declval<absl::StatusOr<int>&>().operator->())>(), - "Unexpected qualifiers"); - static_assert( - std::is_same< - const int*, - decltype(std::declval<const absl::StatusOr<int>&&>().operator->())>(), - "Unexpected qualifiers"); - static_assert( - std::is_same< - int*, decltype(std::declval<absl::StatusOr<int>&&>().operator->())>(), - "Unexpected qualifiers"); -} - -TEST(StatusOr, OperatorArrow) { - const absl::StatusOr<std::string> const_lvalue("hello"); - EXPECT_EQ(std::string("hello"), const_lvalue->c_str()); - - absl::StatusOr<std::string> lvalue("hello"); - EXPECT_EQ(std::string("hello"), lvalue->c_str()); -} - -TEST(StatusOr, RValueStatus) { - absl::StatusOr<int> so(absl::NotFoundError("taco")); - const absl::Status s = std::move(so).status(); - - EXPECT_EQ(s.code(), absl::StatusCode::kNotFound); - EXPECT_EQ(s.message(), "taco"); - - // Check that !ok() still implies !status().ok(), even after moving out of the - // object. See the note on the rvalue ref-qualified status method. - EXPECT_FALSE(so.ok()); // NOLINT - EXPECT_FALSE(so.status().ok()); - EXPECT_EQ(so.status().code(), absl::StatusCode::kInternal); - EXPECT_EQ(so.status().message(), "Status accessed after move."); -} - -TEST(StatusOr, TestValue) { - const int kI = 4; - absl::StatusOr<int> thing(kI); - EXPECT_EQ(kI, *thing); -} - -TEST(StatusOr, TestValueConst) { - const int kI = 4; - const absl::StatusOr<int> thing(kI); - EXPECT_EQ(kI, *thing); -} - -TEST(StatusOr, TestPointerDefaultCtor) { - absl::StatusOr<int*> thing; - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown); -} - - - -TEST(StatusOr, TestPointerStatusCtor) { - absl::StatusOr<int*> thing(absl::CancelledError()); - EXPECT_FALSE(thing.ok()); - EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerValueCtor) { - const int kI = 4; - - // Construction from a non-null pointer - { - absl::StatusOr<const int*> so(&kI); - EXPECT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(&kI, *so); - } - - // Construction from a null pointer constant - { - absl::StatusOr<const int*> so(nullptr); - EXPECT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(nullptr, *so); - } - - // Construction from a non-literal null pointer - { - const int* const p = nullptr; - - absl::StatusOr<const int*> so(p); - EXPECT_TRUE(so.ok()); - EXPECT_OK(so.status()); - EXPECT_EQ(nullptr, *so); - } -} - -TEST(StatusOr, TestPointerCopyCtorStatusOk) { - const int kI = 0; - absl::StatusOr<const int*> original(&kI); - absl::StatusOr<const int*> copy(original); - EXPECT_OK(copy.status()); - EXPECT_EQ(*original, *copy); -} - -TEST(StatusOr, TestPointerCopyCtorStatusNotOk) { - absl::StatusOr<int*> original(absl::CancelledError()); - absl::StatusOr<int*> copy(original); - EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) { - Derived derived; - absl::StatusOr<Derived*> original(&derived); - absl::StatusOr<Base2*> copy(original); - EXPECT_OK(copy.status()); - EXPECT_EQ(static_cast<const Base2*>(*original), *copy); -} - -TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) { - absl::StatusOr<Derived*> original(absl::CancelledError()); - absl::StatusOr<Base2*> copy(original); - EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerAssignmentStatusOk) { - const int kI = 0; - absl::StatusOr<const int*> source(&kI); - absl::StatusOr<const int*> target; - target = source; - EXPECT_OK(target.status()); - EXPECT_EQ(*source, *target); -} - -TEST(StatusOr, TestPointerAssignmentStatusNotOk) { - absl::StatusOr<int*> source(absl::CancelledError()); - absl::StatusOr<int*> target; - target = source; - EXPECT_EQ(target.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerAssignmentStatusOKConverting) { - Derived derived; - absl::StatusOr<Derived*> source(&derived); - absl::StatusOr<Base2*> target; - target = source; - EXPECT_OK(target.status()); - EXPECT_EQ(static_cast<const Base2*>(*source), *target); -} - -TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) { - absl::StatusOr<Derived*> source(absl::CancelledError()); - absl::StatusOr<Base2*> target; - target = source; - EXPECT_EQ(target.status(), source.status()); -} - -TEST(StatusOr, TestPointerStatus) { - const int kI = 0; - absl::StatusOr<const int*> good(&kI); - EXPECT_TRUE(good.ok()); - absl::StatusOr<const int*> bad(absl::CancelledError()); - EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled); -} - -TEST(StatusOr, TestPointerValue) { - const int kI = 0; - absl::StatusOr<const int*> thing(&kI); - EXPECT_EQ(&kI, *thing); -} - -TEST(StatusOr, TestPointerValueConst) { - const int kI = 0; - const absl::StatusOr<const int*> thing(&kI); - EXPECT_EQ(&kI, *thing); -} - -TEST(StatusOr, StatusOrVectorOfUniquePointerCanReserveAndResize) { - using EvilType = std::vector<std::unique_ptr<int>>; - static_assert(std::is_copy_constructible<EvilType>::value, ""); - std::vector<::absl::StatusOr<EvilType>> v(5); - v.reserve(v.capacity() + 10); - v.resize(v.capacity() + 10); -} - -TEST(StatusOr, ConstPayload) { - // A reduced version of a problematic type found in the wild. All of the - // operations below should compile. - absl::StatusOr<const int> a; - - // Copy-construction - absl::StatusOr<const int> b(a); - - // Copy-assignment - EXPECT_FALSE(std::is_copy_assignable<absl::StatusOr<const int>>::value); - - // Move-construction - absl::StatusOr<const int> c(std::move(a)); - - // Move-assignment - EXPECT_FALSE(std::is_move_assignable<absl::StatusOr<const int>>::value); -} - -TEST(StatusOr, MapToStatusOrUniquePtr) { - // A reduced version of a problematic type found in the wild. All of the - // operations below should compile. - using MapType = std::map<std::string, absl::StatusOr<std::unique_ptr<int>>>; - - MapType a; - - // Move-construction - MapType b(std::move(a)); - - // Move-assignment - a = std::move(b); -} - -TEST(StatusOr, ValueOrOk) { - const absl::StatusOr<int> status_or = 0; - EXPECT_EQ(status_or.value_or(-1), 0); -} - -TEST(StatusOr, ValueOrDefault) { - const absl::StatusOr<int> status_or = absl::CancelledError(); - EXPECT_EQ(status_or.value_or(-1), -1); -} - -TEST(StatusOr, MoveOnlyValueOrOk) { - EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0)) - .value_or(absl::make_unique<int>(-1)), - Pointee(0)); -} - -TEST(StatusOr, MoveOnlyValueOrDefault) { - EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::CancelledError()) - .value_or(absl::make_unique<int>(-1)), - Pointee(-1)); -} - -static absl::StatusOr<int> MakeStatus() { return 100; } - -TEST(StatusOr, TestIgnoreError) { MakeStatus().IgnoreError(); } - -TEST(StatusOr, EqualityOperator) { - constexpr int kNumCases = 4; - std::array<absl::StatusOr<int>, kNumCases> group1 = { - absl::StatusOr<int>(1), absl::StatusOr<int>(2), - absl::StatusOr<int>(absl::InvalidArgumentError("msg")), - absl::StatusOr<int>(absl::InternalError("msg"))}; - std::array<absl::StatusOr<int>, kNumCases> group2 = { - absl::StatusOr<int>(1), absl::StatusOr<int>(2), - absl::StatusOr<int>(absl::InvalidArgumentError("msg")), - absl::StatusOr<int>(absl::InternalError("msg"))}; - for (int i = 0; i < kNumCases; ++i) { - for (int j = 0; j < kNumCases; ++j) { - if (i == j) { - EXPECT_TRUE(group1[i] == group2[j]); - EXPECT_FALSE(group1[i] != group2[j]); - } else { - EXPECT_FALSE(group1[i] == group2[j]); - EXPECT_TRUE(group1[i] != group2[j]); - } - } - } -} - -struct MyType { - bool operator==(const MyType&) const { return true; } -}; - -enum class ConvTraits { kNone = 0, kImplicit = 1, kExplicit = 2 }; - -// This class has conversion operator to `StatusOr<T>` based on value of -// `conv_traits`. -template <typename T, ConvTraits conv_traits = ConvTraits::kNone> -struct StatusOrConversionBase {}; - -template <typename T> -struct StatusOrConversionBase<T, ConvTraits::kImplicit> { - operator absl::StatusOr<T>() const& { // NOLINT - return absl::InvalidArgumentError("conversion to absl::StatusOr"); - } - operator absl::StatusOr<T>() && { // NOLINT - return absl::InvalidArgumentError("conversion to absl::StatusOr"); - } -}; - -template <typename T> -struct StatusOrConversionBase<T, ConvTraits::kExplicit> { - explicit operator absl::StatusOr<T>() const& { - return absl::InvalidArgumentError("conversion to absl::StatusOr"); - } - explicit operator absl::StatusOr<T>() && { - return absl::InvalidArgumentError("conversion to absl::StatusOr"); - } -}; - -// This class has conversion operator to `T` based on the value of -// `conv_traits`. -template <typename T, ConvTraits conv_traits = ConvTraits::kNone> -struct ConversionBase {}; - -template <typename T> -struct ConversionBase<T, ConvTraits::kImplicit> { - operator T() const& { return t; } // NOLINT - operator T() && { return std::move(t); } // NOLINT - T t; -}; - -template <typename T> -struct ConversionBase<T, ConvTraits::kExplicit> { - explicit operator T() const& { return t; } - explicit operator T() && { return std::move(t); } - T t; -}; - -// This class has conversion operator to `absl::Status` based on the value of -// `conv_traits`. -template <ConvTraits conv_traits = ConvTraits::kNone> -struct StatusConversionBase {}; - -template <> -struct StatusConversionBase<ConvTraits::kImplicit> { - operator absl::Status() const& { // NOLINT - return absl::InternalError("conversion to Status"); - } - operator absl::Status() && { // NOLINT - return absl::InternalError("conversion to Status"); - } -}; - -template <> -struct StatusConversionBase<ConvTraits::kExplicit> { - explicit operator absl::Status() const& { // NOLINT - return absl::InternalError("conversion to Status"); - } - explicit operator absl::Status() && { // NOLINT - return absl::InternalError("conversion to Status"); - } -}; - -static constexpr int kConvToStatus = 1; -static constexpr int kConvToStatusOr = 2; -static constexpr int kConvToT = 4; -static constexpr int kConvExplicit = 8; - -constexpr ConvTraits GetConvTraits(int bit, int config) { - return (config & bit) == 0 - ? ConvTraits::kNone - : ((config & kConvExplicit) == 0 ? ConvTraits::kImplicit - : ConvTraits::kExplicit); -} - -// This class conditionally has conversion operator to `absl::Status`, `T`, -// `StatusOr<T>`, based on values of the template parameters. -template <typename T, int config> -struct CustomType - : StatusOrConversionBase<T, GetConvTraits(kConvToStatusOr, config)>, - ConversionBase<T, GetConvTraits(kConvToT, config)>, - StatusConversionBase<GetConvTraits(kConvToStatus, config)> {}; - -struct ConvertibleToAnyStatusOr { - template <typename T> - operator absl::StatusOr<T>() const { // NOLINT - return absl::InvalidArgumentError("Conversion to absl::StatusOr"); - } -}; - -// Test the rank of overload resolution for `StatusOr<T>` constructor and -// assignment, from highest to lowest: -// 1. T/Status -// 2. U that has conversion operator to absl::StatusOr<T> -// 3. U that is convertible to Status -// 4. U that is convertible to T -TEST(StatusOr, ConstructionFromT) { - // Construct absl::StatusOr<T> from T when T is convertible to - // absl::StatusOr<T> - { - ConvertibleToAnyStatusOr v; - absl::StatusOr<ConvertibleToAnyStatusOr> statusor(v); - EXPECT_TRUE(statusor.ok()); - } - { - ConvertibleToAnyStatusOr v; - absl::StatusOr<ConvertibleToAnyStatusOr> statusor = v; - EXPECT_TRUE(statusor.ok()); - } - // Construct absl::StatusOr<T> from T when T is explicitly convertible to - // Status - { - CustomType<MyType, kConvToStatus | kConvExplicit> v; - absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor( - v); - EXPECT_TRUE(statusor.ok()); - } - { - CustomType<MyType, kConvToStatus | kConvExplicit> v; - absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor = - v; - EXPECT_TRUE(statusor.ok()); - } -} - -// Construct absl::StatusOr<T> from U when U is explicitly convertible to T -TEST(StatusOr, ConstructionFromTypeConvertibleToT) { - { - CustomType<MyType, kConvToT | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_TRUE(statusor.ok()); - } - { - CustomType<MyType, kConvToT> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_TRUE(statusor.ok()); - } -} - -// Construct absl::StatusOr<T> from U when U has explicit conversion operator to -// absl::StatusOr<T> -TEST(StatusOr, ConstructionFromTypeWithConversionOperatorToStatusOrT) { - { - CustomType<MyType, kConvToStatusOr | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToStatusOr | kConvToStatus | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, - kConvToT | kConvToStatusOr | kConvToStatus | kConvExplicit> - v; - absl::StatusOr<MyType> statusor(v); - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToStatusOr> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToStatusOr | kConvToStatus> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } -} - -TEST(StatusOr, ConstructionFromTypeConvertibleToStatus) { - // Construction fails because conversion to `Status` is explicit. - { - CustomType<MyType, kConvToStatus | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } - { - CustomType<MyType, kConvToT | kConvToStatus | kConvExplicit> v; - absl::StatusOr<MyType> statusor(v); - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } - { - CustomType<MyType, kConvToStatus> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } - { - CustomType<MyType, kConvToT | kConvToStatus> v; - absl::StatusOr<MyType> statusor = v; - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } -} - -TEST(StatusOr, AssignmentFromT) { - // Assign to absl::StatusOr<T> from T when T is convertible to - // absl::StatusOr<T> - { - ConvertibleToAnyStatusOr v; - absl::StatusOr<ConvertibleToAnyStatusOr> statusor; - statusor = v; - EXPECT_TRUE(statusor.ok()); - } - // Assign to absl::StatusOr<T> from T when T is convertible to Status - { - CustomType<MyType, kConvToStatus> v; - absl::StatusOr<CustomType<MyType, kConvToStatus>> statusor; - statusor = v; - EXPECT_TRUE(statusor.ok()); - } -} - -TEST(StatusOr, AssignmentFromTypeConvertibleToT) { - // Assign to absl::StatusOr<T> from U when U is convertible to T - { - CustomType<MyType, kConvToT> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_TRUE(statusor.ok()); - } -} - -TEST(StatusOr, AssignmentFromTypeWithConversionOperatortoStatusOrT) { - // Assign to absl::StatusOr<T> from U when U has conversion operator to - // absl::StatusOr<T> - { - CustomType<MyType, kConvToStatusOr> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToStatusOr | kConvToStatus> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } - { - CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>()); - } -} - -TEST(StatusOr, AssignmentFromTypeConvertibleToStatus) { - // Assign to absl::StatusOr<T> from U when U is convertible to Status - { - CustomType<MyType, kConvToStatus> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } - { - CustomType<MyType, kConvToT | kConvToStatus> v; - absl::StatusOr<MyType> statusor; - statusor = v; - EXPECT_FALSE(statusor.ok()); - EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); - } -} - -} // namespace |