diff options
Diffstat (limited to 'third_party/abseil_cpp/absl/status')
-rw-r--r-- | third_party/abseil_cpp/absl/status/BUILD.bazel | 103 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/CMakeLists.txt | 88 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/internal/status_internal.h | 58 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/internal/statusor_internal.h | 396 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/status.cc | 442 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/status.h | 817 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/status_payload_printer.cc | 38 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/status_payload_printer.h | 51 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/status_test.cc | 458 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/statusor.cc | 71 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/statusor.h | 760 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/statusor_internals.h | 250 | ||||
-rw-r--r-- | third_party/abseil_cpp/absl/status/statusor_test.cc | 1811 |
13 files changed, 0 insertions, 5343 deletions
diff --git a/third_party/abseil_cpp/absl/status/BUILD.bazel b/third_party/abseil_cpp/absl/status/BUILD.bazel deleted file mode 100644 index 189bd73d0e46..000000000000 --- a/third_party/abseil_cpp/absl/status/BUILD.bazel +++ /dev/null @@ -1,103 +0,0 @@ -# -# Copyright 2017 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. - -# This package contains `absl::Status`. -# It will expand later to have utilities around `Status` like `StatusOr`, -# `StatusBuilder` and macros. - -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") -load( - "//absl:copts/configure_copts.bzl", - "ABSL_DEFAULT_COPTS", - "ABSL_TEST_COPTS", -) - -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -cc_library( - name = "status", - srcs = [ - "internal/status_internal.h", - "status.cc", - "status_payload_printer.cc", - ], - hdrs = [ - "status.h", - "status_payload_printer.h", - ], - copts = ABSL_DEFAULT_COPTS, - deps = [ - "//absl/base:atomic_hook", - "//absl/base:config", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/container:inlined_vector", - "//absl/debugging:stacktrace", - "//absl/debugging:symbolize", - "//absl/strings", - "//absl/strings:cord", - "//absl/strings:str_format", - "//absl/types:optional", - ], -) - -cc_test( - name = "status_test", - srcs = ["status_test.cc"], - copts = ABSL_TEST_COPTS, - deps = [ - ":status", - "//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - -cc_library( - name = "statusor", - srcs = [ - "internal/statusor_internal.h", - "statusor.cc", - ], - hdrs = [ - "statusor.h", - ], - copts = ABSL_DEFAULT_COPTS, - deps = [ - ":status", - "//absl/base:core_headers", - "//absl/base:raw_logging_internal", - "//absl/meta:type_traits", - "//absl/strings", - "//absl/types:variant", - "//absl/utility", - ], -) - -cc_test( - name = "statusor_test", - size = "small", - srcs = ["statusor_test.cc"], - deps = [ - ":status", - ":statusor", - "//absl/base", - "//absl/memory", - "//absl/types:any", - "//absl/utility", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/third_party/abseil_cpp/absl/status/CMakeLists.txt b/third_party/abseil_cpp/absl/status/CMakeLists.txt deleted file mode 100644 index f0d798a3732d..000000000000 --- a/third_party/abseil_cpp/absl/status/CMakeLists.txt +++ /dev/null @@ -1,88 +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. -# -absl_cc_library( - NAME - status - HDRS - "status.h" - SRCS - "internal/status_internal.h" - "status.cc" - "status_payload_printer.h" - "status_payload_printer.cc" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::atomic_hook - absl::config - absl::core_headers - absl::raw_logging_internal - absl::inlined_vector - absl::stacktrace - absl::symbolize - absl::strings - absl::cord - absl::str_format - absl::optional - PUBLIC -) - -absl_cc_test( - NAME - status_test - SRCS - "status_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::status - absl::strings - gmock_main -) - -absl_cc_library( - NAME - statusor - HDRS - "statusor.h" - SRCS - "statusor.cc" - "internal/statusor_internal.h" - COPTS - ${ABSL_DEFAULT_COPTS} - DEPS - absl::status - absl::core_headers - absl::raw_logging_internal - absl::type_traits - absl::strings - absl::utility - absl::variant - PUBLIC -) - -absl_cc_test( - NAME - statusor_test - SRCS - "statusor_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::status - absl::statusor - gmock_main -) diff --git a/third_party/abseil_cpp/absl/status/internal/status_internal.h b/third_party/abseil_cpp/absl/status/internal/status_internal.h deleted file mode 100644 index 279f8f55bef0..000000000000 --- a/third_party/abseil_cpp/absl/status/internal/status_internal.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2019 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. -#ifndef ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_ -#define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_ - -#include <string> - -#include "absl/container/inlined_vector.h" -#include "absl/strings/cord.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -enum class StatusCode : int; - -namespace status_internal { - -// Container for status payloads. -struct Payload { - std::string type_url; - absl::Cord payload; -}; - -using Payloads = absl::InlinedVector<Payload, 1>; - -// Reference-counted representation of Status data. -struct StatusRep { - StatusRep(absl::StatusCode code, std::string message, - std::unique_ptr<status_internal::Payloads> payloads) - : ref(int32_t{1}), - code(code), - message(std::move(message)), - payloads(std::move(payloads)) {} - - std::atomic<int32_t> ref; - absl::StatusCode code; - std::string message; - std::unique_ptr<status_internal::Payloads> payloads; -}; - -absl::StatusCode MapToLocalCode(int value); -} // namespace status_internal - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_ diff --git a/third_party/abseil_cpp/absl/status/internal/statusor_internal.h b/third_party/abseil_cpp/absl/status/internal/statusor_internal.h deleted file mode 100644 index eaac2c0b14c6..000000000000 --- a/third_party/abseil_cpp/absl/status/internal/statusor_internal.h +++ /dev/null @@ -1,396 +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. -#ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_ -#define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_ - -#include <type_traits> -#include <utility> - -#include "absl/base/attributes.h" -#include "absl/meta/type_traits.h" -#include "absl/status/status.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -template <typename T> -class ABSL_MUST_USE_RESULT StatusOr; - -namespace internal_statusor { - -// Detects whether `U` has conversion operator to `StatusOr<T>`, i.e. `operator -// StatusOr<T>()`. -template <typename T, typename U, typename = void> -struct HasConversionOperatorToStatusOr : std::false_type {}; - -template <typename T, typename U> -void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]); - -template <typename T, typename U> -struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))> - : std::true_type {}; - -// Detects whether `T` is constructible or convertible from `StatusOr<U>`. -template <typename T, typename U> -using IsConstructibleOrConvertibleFromStatusOr = - absl::disjunction<std::is_constructible<T, StatusOr<U>&>, - std::is_constructible<T, const StatusOr<U>&>, - std::is_constructible<T, StatusOr<U>&&>, - std::is_constructible<T, const StatusOr<U>&&>, - std::is_convertible<StatusOr<U>&, T>, - std::is_convertible<const StatusOr<U>&, T>, - std::is_convertible<StatusOr<U>&&, T>, - std::is_convertible<const StatusOr<U>&&, T>>; - -// Detects whether `T` is constructible or convertible or assignable from -// `StatusOr<U>`. -template <typename T, typename U> -using IsConstructibleOrConvertibleOrAssignableFromStatusOr = - absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>, - std::is_assignable<T&, StatusOr<U>&>, - std::is_assignable<T&, const StatusOr<U>&>, - std::is_assignable<T&, StatusOr<U>&&>, - std::is_assignable<T&, const StatusOr<U>&&>>; - -// Detects whether direct initializing `StatusOr<T>` from `U` is ambiguous, i.e. -// when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`. -template <typename T, typename U> -struct IsDirectInitializationAmbiguous - : public absl::conditional_t< - std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, - U>::value, - std::false_type, - IsDirectInitializationAmbiguous< - T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {}; - -template <typename T, typename V> -struct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>> - : public IsConstructibleOrConvertibleFromStatusOr<T, V> {}; - -// Checks against the constraints of the direction initialization, i.e. when -// `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution. -template <typename T, typename U> -using IsDirectInitializationValid = absl::disjunction< - // Short circuits if T is basically U. - std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>, - absl::negation<absl::disjunction< - std::is_same<absl::StatusOr<T>, - absl::remove_cv_t<absl::remove_reference_t<U>>>, - std::is_same<absl::Status, - absl::remove_cv_t<absl::remove_reference_t<U>>>, - std::is_same<absl::in_place_t, - absl::remove_cv_t<absl::remove_reference_t<U>>>, - IsDirectInitializationAmbiguous<T, U>>>>; - -// This trait detects whether `StatusOr<T>::operator=(U&&)` is ambiguous, which -// is equivalent to whether all the following conditions are met: -// 1. `U` is `StatusOr<V>`. -// 2. `T` is constructible and assignable from `V`. -// 3. `T` is constructible and assignable from `U` (i.e. `StatusOr<V>`). -// For example, the following code is considered ambiguous: -// (`T` is `bool`, `U` is `StatusOr<bool>`, `V` is `bool`) -// StatusOr<bool> s1 = true; // s1.ok() && s1.ValueOrDie() == true -// StatusOr<bool> s2 = false; // s2.ok() && s2.ValueOrDie() == false -// s1 = s2; // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`? -template <typename T, typename U> -struct IsForwardingAssignmentAmbiguous - : public absl::conditional_t< - std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, - U>::value, - std::false_type, - IsForwardingAssignmentAmbiguous< - T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {}; - -template <typename T, typename U> -struct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>> - : public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {}; - -// Checks against the constraints of the forwarding assignment, i.e. whether -// `StatusOr<T>::operator(U&&)` should participate in overload resolution. -template <typename T, typename U> -using IsForwardingAssignmentValid = absl::disjunction< - // Short circuits if T is basically U. - std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>, - absl::negation<absl::disjunction< - std::is_same<absl::StatusOr<T>, - absl::remove_cv_t<absl::remove_reference_t<U>>>, - std::is_same<absl::Status, - absl::remove_cv_t<absl::remove_reference_t<U>>>, - std::is_same<absl::in_place_t, - absl::remove_cv_t<absl::remove_reference_t<U>>>, - IsForwardingAssignmentAmbiguous<T, U>>>>; - -class Helper { - public: - // Move type-agnostic error handling to the .cc. - static void HandleInvalidStatusCtorArg(Status*); - ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status); -}; - -// Construct an instance of T in `p` through placement new, passing Args... to -// the constructor. -// This abstraction is here mostly for the gcc performance fix. -template <typename T, typename... Args> -ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) { - new (p) T(std::forward<Args>(args)...); -} - -// Helper base class to hold the data and all operations. -// We move all this to a base class to allow mixing with the appropriate -// TraitsBase specialization. -template <typename T> -class StatusOrData { - template <typename U> - friend class StatusOrData; - - public: - StatusOrData() = delete; - - StatusOrData(const StatusOrData& other) { - if (other.ok()) { - MakeValue(other.data_); - MakeStatus(); - } else { - MakeStatus(other.status_); - } - } - - StatusOrData(StatusOrData&& other) noexcept { - if (other.ok()) { - MakeValue(std::move(other.data_)); - MakeStatus(); - } else { - MakeStatus(std::move(other.status_)); - } - } - - template <typename U> - explicit StatusOrData(const StatusOrData<U>& other) { - if (other.ok()) { - MakeValue(other.data_); - MakeStatus(); - } else { - MakeStatus(other.status_); - } - } - - template <typename U> - explicit StatusOrData(StatusOrData<U>&& other) { - if (other.ok()) { - MakeValue(std::move(other.data_)); - MakeStatus(); - } else { - MakeStatus(std::move(other.status_)); - } - } - - template <typename... Args> - explicit StatusOrData(absl::in_place_t, Args&&... args) - : data_(std::forward<Args>(args)...) { - MakeStatus(); - } - - explicit StatusOrData(const T& value) : data_(value) { - MakeStatus(); - } - explicit StatusOrData(T&& value) : data_(std::move(value)) { - MakeStatus(); - } - - template <typename U, - absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value, - int> = 0> - explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) { - EnsureNotOk(); - } - - StatusOrData& operator=(const StatusOrData& other) { - if (this == &other) return *this; - if (other.ok()) - Assign(other.data_); - else - AssignStatus(other.status_); - return *this; - } - - StatusOrData& operator=(StatusOrData&& other) { - if (this == &other) return *this; - if (other.ok()) - Assign(std::move(other.data_)); - else - AssignStatus(std::move(other.status_)); - return *this; - } - - ~StatusOrData() { - if (ok()) { - status_.~Status(); - data_.~T(); - } else { - status_.~Status(); - } - } - - template <typename U> - void Assign(U&& value) { - if (ok()) { - data_ = std::forward<U>(value); - } else { - MakeValue(std::forward<U>(value)); - status_ = OkStatus(); - } - } - - template <typename U> - void AssignStatus(U&& v) { - Clear(); - status_ = static_cast<absl::Status>(std::forward<U>(v)); - EnsureNotOk(); - } - - bool ok() const { return status_.ok(); } - - protected: - // status_ will always be active after the constructor. - // We make it a union to be able to initialize exactly how we need without - // waste. - // Eg. in the copy constructor we use the default constructor of Status in - // the ok() path to avoid an extra Ref call. - union { - Status status_; - }; - - // data_ is active iff status_.ok()==true - struct Dummy {}; - union { - // When T is const, we need some non-const object we can cast to void* for - // the placement new. dummy_ is that object. - Dummy dummy_; - T data_; - }; - - void Clear() { - if (ok()) data_.~T(); - } - - void EnsureOk() const { - if (ABSL_PREDICT_FALSE(!ok())) Helper::Crash(status_); - } - - void EnsureNotOk() { - if (ABSL_PREDICT_FALSE(ok())) Helper::HandleInvalidStatusCtorArg(&status_); - } - - // Construct the value (ie. data_) through placement new with the passed - // argument. - template <typename... Arg> - void MakeValue(Arg&&... arg) { - internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)...); - } - - // Construct the status (ie. status_) through placement new with the passed - // argument. - template <typename... Args> - void MakeStatus(Args&&... args) { - internal_statusor::PlacementNew<Status>(&status_, - std::forward<Args>(args)...); - } -}; - -// Helper base classes to allow implicitly deleted constructors and assignment -// operators in `StatusOr`. For example, `CopyCtorBase` will explicitly delete -// the copy constructor when T is not copy constructible and `StatusOr` will -// inherit that behavior implicitly. -template <typename T, bool = std::is_copy_constructible<T>::value> -struct CopyCtorBase { - CopyCtorBase() = default; - CopyCtorBase(const CopyCtorBase&) = default; - CopyCtorBase(CopyCtorBase&&) = default; - CopyCtorBase& operator=(const CopyCtorBase&) = default; - CopyCtorBase& operator=(CopyCtorBase&&) = default; -}; - -template <typename T> -struct CopyCtorBase<T, false> { - CopyCtorBase() = default; - CopyCtorBase(const CopyCtorBase&) = delete; - CopyCtorBase(CopyCtorBase&&) = default; - CopyCtorBase& operator=(const CopyCtorBase&) = default; - CopyCtorBase& operator=(CopyCtorBase&&) = default; -}; - -template <typename T, bool = std::is_move_constructible<T>::value> -struct MoveCtorBase { - MoveCtorBase() = default; - MoveCtorBase(const MoveCtorBase&) = default; - MoveCtorBase(MoveCtorBase&&) = default; - MoveCtorBase& operator=(const MoveCtorBase&) = default; - MoveCtorBase& operator=(MoveCtorBase&&) = default; -}; - -template <typename T> -struct MoveCtorBase<T, false> { - MoveCtorBase() = default; - MoveCtorBase(const MoveCtorBase&) = default; - MoveCtorBase(MoveCtorBase&&) = delete; - MoveCtorBase& operator=(const MoveCtorBase&) = default; - MoveCtorBase& operator=(MoveCtorBase&&) = default; -}; - -template <typename T, bool = std::is_copy_constructible<T>::value&& - std::is_copy_assignable<T>::value> -struct CopyAssignBase { - CopyAssignBase() = default; - CopyAssignBase(const CopyAssignBase&) = default; - CopyAssignBase(CopyAssignBase&&) = default; - CopyAssignBase& operator=(const CopyAssignBase&) = default; - CopyAssignBase& operator=(CopyAssignBase&&) = default; -}; - -template <typename T> -struct CopyAssignBase<T, false> { - CopyAssignBase() = default; - CopyAssignBase(const CopyAssignBase&) = default; - CopyAssignBase(CopyAssignBase&&) = default; - CopyAssignBase& operator=(const CopyAssignBase&) = delete; - CopyAssignBase& operator=(CopyAssignBase&&) = default; -}; - -template <typename T, bool = std::is_move_constructible<T>::value&& - std::is_move_assignable<T>::value> -struct MoveAssignBase { - MoveAssignBase() = default; - MoveAssignBase(const MoveAssignBase&) = default; - MoveAssignBase(MoveAssignBase&&) = default; - MoveAssignBase& operator=(const MoveAssignBase&) = default; - MoveAssignBase& operator=(MoveAssignBase&&) = default; -}; - -template <typename T> -struct MoveAssignBase<T, false> { - MoveAssignBase() = default; - MoveAssignBase(const MoveAssignBase&) = default; - MoveAssignBase(MoveAssignBase&&) = default; - MoveAssignBase& operator=(const MoveAssignBase&) = default; - MoveAssignBase& operator=(MoveAssignBase&&) = delete; -}; - -ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status); - -} // namespace internal_statusor -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_ diff --git a/third_party/abseil_cpp/absl/status/status.cc b/third_party/abseil_cpp/absl/status/status.cc deleted file mode 100644 index c71de846827c..000000000000 --- a/third_party/abseil_cpp/absl/status/status.cc +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright 2019 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/status.h" - -#include <cassert> - -#include "absl/base/internal/raw_logging.h" -#include "absl/debugging/stacktrace.h" -#include "absl/debugging/symbolize.h" -#include "absl/status/status_payload_printer.h" -#include "absl/strings/escaping.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_split.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -std::string StatusCodeToString(StatusCode code) { - switch (code) { - case StatusCode::kOk: - return "OK"; - case StatusCode::kCancelled: - return "CANCELLED"; - case StatusCode::kUnknown: - return "UNKNOWN"; - case StatusCode::kInvalidArgument: - return "INVALID_ARGUMENT"; - case StatusCode::kDeadlineExceeded: - return "DEADLINE_EXCEEDED"; - case StatusCode::kNotFound: - return "NOT_FOUND"; - case StatusCode::kAlreadyExists: - return "ALREADY_EXISTS"; - case StatusCode::kPermissionDenied: - return "PERMISSION_DENIED"; - case StatusCode::kUnauthenticated: - return "UNAUTHENTICATED"; - case StatusCode::kResourceExhausted: - return "RESOURCE_EXHAUSTED"; - case StatusCode::kFailedPrecondition: - return "FAILED_PRECONDITION"; - case StatusCode::kAborted: - return "ABORTED"; - case StatusCode::kOutOfRange: - return "OUT_OF_RANGE"; - case StatusCode::kUnimplemented: - return "UNIMPLEMENTED"; - case StatusCode::kInternal: - return "INTERNAL"; - case StatusCode::kUnavailable: - return "UNAVAILABLE"; - case StatusCode::kDataLoss: - return "DATA_LOSS"; - default: - return ""; - } -} - -std::ostream& operator<<(std::ostream& os, StatusCode code) { - return os << StatusCodeToString(code); -} - -namespace status_internal { - -static int FindPayloadIndexByUrl(const Payloads* payloads, - absl::string_view type_url) { - if (payloads == nullptr) return -1; - - for (size_t i = 0; i < payloads->size(); ++i) { - if ((*payloads)[i].type_url == type_url) return i; - } - - return -1; -} - -// Convert canonical code to a value known to this binary. -absl::StatusCode MapToLocalCode(int value) { - absl::StatusCode code = static_cast<absl::StatusCode>(value); - switch (code) { - case absl::StatusCode::kOk: - case absl::StatusCode::kCancelled: - case absl::StatusCode::kUnknown: - case absl::StatusCode::kInvalidArgument: - case absl::StatusCode::kDeadlineExceeded: - case absl::StatusCode::kNotFound: - case absl::StatusCode::kAlreadyExists: - case absl::StatusCode::kPermissionDenied: - case absl::StatusCode::kResourceExhausted: - case absl::StatusCode::kFailedPrecondition: - case absl::StatusCode::kAborted: - case absl::StatusCode::kOutOfRange: - case absl::StatusCode::kUnimplemented: - case absl::StatusCode::kInternal: - case absl::StatusCode::kUnavailable: - case absl::StatusCode::kDataLoss: - case absl::StatusCode::kUnauthenticated: - return code; - default: - return absl::StatusCode::kUnknown; - } -} -} // namespace status_internal - -absl::optional<absl::Cord> Status::GetPayload( - absl::string_view type_url) const { - const auto* payloads = GetPayloads(); - int index = status_internal::FindPayloadIndexByUrl(payloads, type_url); - if (index != -1) return (*payloads)[index].payload; - - return absl::nullopt; -} - -void Status::SetPayload(absl::string_view type_url, absl::Cord payload) { - if (ok()) return; - - PrepareToModify(); - - status_internal::StatusRep* rep = RepToPointer(rep_); - if (!rep->payloads) { - rep->payloads = absl::make_unique<status_internal::Payloads>(); - } - - int index = - status_internal::FindPayloadIndexByUrl(rep->payloads.get(), type_url); - if (index != -1) { - (*rep->payloads)[index].payload = std::move(payload); - return; - } - - rep->payloads->push_back({std::string(type_url), std::move(payload)}); -} - -bool Status::ErasePayload(absl::string_view type_url) { - int index = status_internal::FindPayloadIndexByUrl(GetPayloads(), type_url); - if (index != -1) { - PrepareToModify(); - GetPayloads()->erase(GetPayloads()->begin() + index); - if (GetPayloads()->empty() && message().empty()) { - // Special case: If this can be represented inlined, it MUST be - // inlined (EqualsSlow depends on this behavior). - StatusCode c = static_cast<StatusCode>(raw_code()); - Unref(rep_); - rep_ = CodeToInlinedRep(c); - } - return true; - } - - return false; -} - -void Status::ForEachPayload( - const std::function<void(absl::string_view, const absl::Cord&)>& visitor) - const { - if (auto* payloads = GetPayloads()) { - bool in_reverse = - payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6; - - for (size_t index = 0; index < payloads->size(); ++index) { - const auto& elem = - (*payloads)[in_reverse ? payloads->size() - 1 - index : index]; - -#ifdef NDEBUG - visitor(elem.type_url, elem.payload); -#else - // In debug mode invalidate the type url to prevent users from relying on - // this string lifetime. - - // NOLINTNEXTLINE intentional extra conversion to force temporary. - visitor(std::string(elem.type_url), elem.payload); -#endif // NDEBUG - } - } -} - -const std::string* Status::EmptyString() { - static std::string* empty_string = new std::string(); - return empty_string; -} - -constexpr const char Status::kMovedFromString[]; - -const std::string* Status::MovedFromString() { - static std::string* moved_from_string = new std::string(kMovedFromString); - return moved_from_string; -} - -void Status::UnrefNonInlined(uintptr_t rep) { - status_internal::StatusRep* r = RepToPointer(rep); - // Fast path: if ref==1, there is no need for a RefCountDec (since - // this is the only reference and therefore no other thread is - // allowed to be mucking with r). - if (r->ref.load(std::memory_order_acquire) == 1 || - r->ref.fetch_sub(1, std::memory_order_acq_rel) - 1 == 0) { - delete r; - } -} - -uintptr_t Status::NewRep(absl::StatusCode code, absl::string_view msg, - std::unique_ptr<status_internal::Payloads> payloads) { - status_internal::StatusRep* rep = new status_internal::StatusRep( - code, std::string(msg.data(), msg.size()), std::move(payloads)); - return PointerToRep(rep); -} - -Status::Status(absl::StatusCode code, absl::string_view msg) - : rep_(CodeToInlinedRep(code)) { - if (code != absl::StatusCode::kOk && !msg.empty()) { - rep_ = NewRep(code, msg, nullptr); - } -} - -int Status::raw_code() const { - if (IsInlined(rep_)) { - return static_cast<int>(InlinedRepToCode(rep_)); - } - status_internal::StatusRep* rep = RepToPointer(rep_); - return static_cast<int>(rep->code); -} - -absl::StatusCode Status::code() const { - return status_internal::MapToLocalCode(raw_code()); -} - -void Status::PrepareToModify() { - ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status."); - if (IsInlined(rep_)) { - rep_ = NewRep(static_cast<absl::StatusCode>(raw_code()), - absl::string_view(), nullptr); - return; - } - - uintptr_t rep_i = rep_; - status_internal::StatusRep* rep = RepToPointer(rep_); - if (rep->ref.load(std::memory_order_acquire) != 1) { - std::unique_ptr<status_internal::Payloads> payloads; - if (rep->payloads) { - payloads = absl::make_unique<status_internal::Payloads>(*rep->payloads); - } - rep_ = NewRep(rep->code, message(), std::move(payloads)); - UnrefNonInlined(rep_i); - } -} - -bool Status::EqualsSlow(const absl::Status& a, const absl::Status& b) { - if (IsInlined(a.rep_) != IsInlined(b.rep_)) return false; - if (a.message() != b.message()) return false; - if (a.raw_code() != b.raw_code()) return false; - if (a.GetPayloads() == b.GetPayloads()) return true; - - const status_internal::Payloads no_payloads; - const status_internal::Payloads* larger_payloads = - a.GetPayloads() ? a.GetPayloads() : &no_payloads; - const status_internal::Payloads* smaller_payloads = - b.GetPayloads() ? b.GetPayloads() : &no_payloads; - if (larger_payloads->size() < smaller_payloads->size()) { - std::swap(larger_payloads, smaller_payloads); - } - if ((larger_payloads->size() - smaller_payloads->size()) > 1) return false; - // Payloads can be ordered differently, so we can't just compare payload - // vectors. - for (const auto& payload : *larger_payloads) { - - bool found = false; - for (const auto& other_payload : *smaller_payloads) { - if (payload.type_url == other_payload.type_url) { - if (payload.payload != other_payload.payload) { - return false; - } - found = true; - break; - } - } - if (!found) return false; - } - return true; -} - -std::string Status::ToStringSlow() const { - std::string text; - absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message()); - status_internal::StatusPayloadPrinter printer = - status_internal::GetStatusPayloadPrinter(); - this->ForEachPayload([&](absl::string_view type_url, - const absl::Cord& payload) { - absl::optional<std::string> result; - if (printer) result = printer(type_url, payload); - absl::StrAppend( - &text, " [", type_url, "='", - result.has_value() ? *result : absl::CHexEscape(std::string(payload)), - "']"); - }); - - return text; -} - -std::ostream& operator<<(std::ostream& os, const Status& x) { - os << x.ToString(); - return os; -} - -Status AbortedError(absl::string_view message) { - return Status(absl::StatusCode::kAborted, message); -} - -Status AlreadyExistsError(absl::string_view message) { - return Status(absl::StatusCode::kAlreadyExists, message); -} - -Status CancelledError(absl::string_view message) { - return Status(absl::StatusCode::kCancelled, message); -} - -Status DataLossError(absl::string_view message) { - return Status(absl::StatusCode::kDataLoss, message); -} - -Status DeadlineExceededError(absl::string_view message) { - return Status(absl::StatusCode::kDeadlineExceeded, message); -} - -Status FailedPreconditionError(absl::string_view message) { - return Status(absl::StatusCode::kFailedPrecondition, message); -} - -Status InternalError(absl::string_view message) { - return Status(absl::StatusCode::kInternal, message); -} - -Status InvalidArgumentError(absl::string_view message) { - return Status(absl::StatusCode::kInvalidArgument, message); -} - -Status NotFoundError(absl::string_view message) { - return Status(absl::StatusCode::kNotFound, message); -} - -Status OutOfRangeError(absl::string_view message) { - return Status(absl::StatusCode::kOutOfRange, message); -} - -Status PermissionDeniedError(absl::string_view message) { - return Status(absl::StatusCode::kPermissionDenied, message); -} - -Status ResourceExhaustedError(absl::string_view message) { - return Status(absl::StatusCode::kResourceExhausted, message); -} - -Status UnauthenticatedError(absl::string_view message) { - return Status(absl::StatusCode::kUnauthenticated, message); -} - -Status UnavailableError(absl::string_view message) { - return Status(absl::StatusCode::kUnavailable, message); -} - -Status UnimplementedError(absl::string_view message) { - return Status(absl::StatusCode::kUnimplemented, message); -} - -Status UnknownError(absl::string_view message) { - return Status(absl::StatusCode::kUnknown, message); -} - -bool IsAborted(const Status& status) { - return status.code() == absl::StatusCode::kAborted; -} - -bool IsAlreadyExists(const Status& status) { - return status.code() == absl::StatusCode::kAlreadyExists; -} - -bool IsCancelled(const Status& status) { - return status.code() == absl::StatusCode::kCancelled; -} - -bool IsDataLoss(const Status& status) { - return status.code() == absl::StatusCode::kDataLoss; -} - -bool IsDeadlineExceeded(const Status& status) { - return status.code() == absl::StatusCode::kDeadlineExceeded; -} - -bool IsFailedPrecondition(const Status& status) { - return status.code() == absl::StatusCode::kFailedPrecondition; -} - -bool IsInternal(const Status& status) { - return status.code() == absl::StatusCode::kInternal; -} - -bool IsInvalidArgument(const Status& status) { - return status.code() == absl::StatusCode::kInvalidArgument; -} - -bool IsNotFound(const Status& status) { - return status.code() == absl::StatusCode::kNotFound; -} - -bool IsOutOfRange(const Status& status) { - return status.code() == absl::StatusCode::kOutOfRange; -} - -bool IsPermissionDenied(const Status& status) { - return status.code() == absl::StatusCode::kPermissionDenied; -} - -bool IsResourceExhausted(const Status& status) { - return status.code() == absl::StatusCode::kResourceExhausted; -} - -bool IsUnauthenticated(const Status& status) { - return status.code() == absl::StatusCode::kUnauthenticated; -} - -bool IsUnavailable(const Status& status) { - return status.code() == absl::StatusCode::kUnavailable; -} - -bool IsUnimplemented(const Status& status) { - return status.code() == absl::StatusCode::kUnimplemented; -} - -bool IsUnknown(const Status& status) { - return status.code() == absl::StatusCode::kUnknown; -} - -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/status/status.h b/third_party/abseil_cpp/absl/status/status.h deleted file mode 100644 index c4d6fce09050..000000000000 --- a/third_party/abseil_cpp/absl/status/status.h +++ /dev/null @@ -1,817 +0,0 @@ -// Copyright 2019 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. -// -// ----------------------------------------------------------------------------- -// File: status.h -// ----------------------------------------------------------------------------- -// -// This header file defines the Abseil `status` library, consisting of: -// -// * An `absl::Status` class for holding error handling information -// * A set of canonical `absl::StatusCode` error codes, and associated -// utilities for generating and propagating status codes. -// * A set of helper functions for creating status codes and checking their -// values -// -// Within Google, `absl::Status` is the primary mechanism for gracefully -// handling errors across API boundaries (and in particular across RPC -// boundaries). Some of these errors may be recoverable, but others may not. -// Most functions that can produce a recoverable error should be designed to -// return an `absl::Status` (or `absl::StatusOr`). -// -// Example: -// -// absl::Status myFunction(absl::string_view fname, ...) { -// ... -// // encounter error -// if (error condition) { -// return absl::InvalidArgumentError("bad mode"); -// } -// // else, return OK -// return absl::OkStatus(); -// } -// -// An `absl::Status` is designed to either return "OK" or one of a number of -// different error codes, corresponding to typical error conditions. -// In almost all cases, when using `absl::Status` you should use the canonical -// error codes (of type `absl::StatusCode`) enumerated in this header file. -// These canonical codes are understood across the codebase and will be -// accepted across all API and RPC boundaries. -#ifndef ABSL_STATUS_STATUS_H_ -#define ABSL_STATUS_STATUS_H_ - -#include <iostream> -#include <string> - -#include "absl/container/inlined_vector.h" -#include "absl/status/internal/status_internal.h" -#include "absl/strings/cord.h" -#include "absl/types/optional.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::StatusCode -// -// An `absl::StatusCode` is an enumerated type indicating either no error ("OK") -// or an error condition. In most cases, an `absl::Status` indicates a -// recoverable error, and the purpose of signalling an error is to indicate what -// action to take in response to that error. These error codes map to the proto -// RPC error codes indicated in https://cloud.google.com/apis/design/errors. -// -// The errors listed below are the canonical errors associated with -// `absl::Status` and are used throughout the codebase. As a result, these -// error codes are somewhat generic. -// -// In general, try to return the most specific error that applies if more than -// one error may pertain. For example, prefer `kOutOfRange` over -// `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or -// `kAlreadyExists` over `kFailedPrecondition`. -// -// Because these errors may travel RPC boundaries, these codes are tied to the -// `google.rpc.Code` definitions within -// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto -// The string value of these RPC codes is denoted within each enum below. -// -// If your error handling code requires more context, you can attach payloads -// to your status. See `absl::Status::SetPayload()` and -// `absl::Status::GetPayload()` below. -enum class StatusCode : int { - // StatusCode::kOk - // - // kOK (gRPC code "OK") does not indicate an error; this value is returned on - // success. It is typical to check for this value before proceeding on any - // given call across an API or RPC boundary. To check this value, use the - // `absl::Status::ok()` member function rather than inspecting the raw code. - kOk = 0, - - // StatusCode::kCancelled - // - // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled, - // typically by the caller. - kCancelled = 1, - - // StatusCode::kUnknown - // - // kUnknown (gRPC code "UNKNOWN") indicates an unknown error occurred. In - // general, more specific errors should be raised, if possible. Errors raised - // by APIs that do not return enough error information may be converted to - // this error. - kUnknown = 2, - - // StatusCode::kInvalidArgument - // - // kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller - // specified an invalid argument, such a malformed filename. Note that such - // errors should be narrowly limited to indicate to the invalid nature of the - // arguments themselves. Errors with validly formed arguments that may cause - // errors with the state of the receiving system should be denoted with - // `kFailedPrecondition` instead. - kInvalidArgument = 3, - - // StatusCode::kDeadlineExceeded - // - // kDeadlineExceeded (gRPC code "DEADLINE_EXCEEDED") indicates a deadline - // expired before the operation could complete. For operations that may change - // state within a system, this error may be returned even if the operation has - // completed successfully. For example, a successful response from a server - // could have been delayed long enough for the deadline to expire. - kDeadlineExceeded = 4, - - // StatusCode::kNotFound - // - // kNotFound (gRPC code "NOT_FOUND") indicates some requested entity (such as - // a file or directory) was not found. - // - // `kNotFound` is useful if a request should be denied for an entire class of - // users, such as during a gradual feature rollout or undocumented allow list. - // If, instead, a request should be denied for specific sets of users, such as - // through user-based access control, use `kPermissionDenied` instead. - kNotFound = 5, - - // StatusCode::kAlreadyExists - // - // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates the entity that a - // caller attempted to create (such as file or directory) is already present. - kAlreadyExists = 6, - - // StatusCode::kPermissionDenied - // - // kPermissionDenied (gRPC code "PERMISSION_DENIED") indicates that the caller - // does not have permission to execute the specified operation. Note that this - // error is different than an error due to an *un*authenticated user. This - // error code does not imply the request is valid or the requested entity - // exists or satisfies any other pre-conditions. - // - // `kPermissionDenied` must not be used for rejections caused by exhausting - // some resource. Instead, use `kResourceExhausted` for those errors. - // `kPermissionDenied` must not be used if the caller cannot be identified. - // Instead, use `kUnauthenticated` for those errors. - kPermissionDenied = 7, - - // StatusCode::kResourceExhausted - // - // kResourceExhausted (gRPC code "RESOURCE_EXHAUSTED") indicates some resource - // has been exhausted, perhaps a per-user quota, or perhaps the entire file - // system is out of space. - kResourceExhausted = 8, - - // StatusCode::kFailedPrecondition - // - // kFailedPrecondition (gRPC code "FAILED_PRECONDITION") indicates that the - // operation was rejected because the system is not in a state required for - // the operation's execution. For example, a directory to be deleted may be - // non-empty, an "rmdir" operation is applied to a non-directory, etc. - // - // Some guidelines that may help a service implementer in deciding between - // `kFailedPrecondition`, `kAborted`, and `kUnavailable`: - // - // (a) Use `kUnavailable` if the client can retry just the failing call. - // (b) Use `kAborted` if the client should retry at a higher transaction - // level (such as when a client-specified test-and-set fails, indicating - // the client should restart a read-modify-write sequence). - // (c) Use `kFailedPrecondition` if the client should not retry until - // the system state has been explicitly fixed. For example, if an "rmdir" - // fails because the directory is non-empty, `kFailedPrecondition` - // should be returned since the client should not retry unless - // the files are deleted from the directory. - kFailedPrecondition = 9, - - // StatusCode::kAborted - // - // kAborted (gRPC code "ABORTED") indicates the operation was aborted, - // typically due to a concurrency issue such as a sequencer check failure or a - // failed transaction. - // - // See the guidelines above for deciding between `kFailedPrecondition`, - // `kAborted`, and `kUnavailable`. - kAborted = 10, - - // StatusCode::kOutOfRange - // - // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was - // attempted past the valid range, such as seeking or reading past an - // end-of-file. - // - // Unlike `kInvalidArgument`, this error indicates a problem that may - // be fixed if the system state changes. For example, a 32-bit file - // system will generate `kInvalidArgument` if asked to read at an - // offset that is not in the range [0,2^32-1], but it will generate - // `kOutOfRange` if asked to read from an offset past the current - // file size. - // - // There is a fair bit of overlap between `kFailedPrecondition` and - // `kOutOfRange`. We recommend using `kOutOfRange` (the more specific - // error) when it applies so that callers who are iterating through - // a space can easily look for an `kOutOfRange` error to detect when - // they are done. - kOutOfRange = 11, - - // StatusCode::kUnimplemented - // - // kUnimplemented (gRPC code "UNIMPLEMENTED") indicates the operation is not - // implemented or supported in this service. In this case, the operation - // should not be re-attempted. - kUnimplemented = 12, - - // StatusCode::kInternal - // - // kInternal (gRPC code "INTERNAL") indicates an internal error has occurred - // and some invariants expected by the underlying system have not been - // satisfied. This error code is reserved for serious errors. - kInternal = 13, - - // StatusCode::kUnavailable - // - // kUnavailable (gRPC code "UNAVAILABLE") indicates the service is currently - // unavailable and that this is most likely a transient condition. An error - // such as this can be corrected by retrying with a backoff scheme. Note that - // it is not always safe to retry non-idempotent operations. - // - // See the guidelines above for deciding between `kFailedPrecondition`, - // `kAborted`, and `kUnavailable`. - kUnavailable = 14, - - // StatusCode::kDataLoss - // - // kDataLoss (gRPC code "DATA_LOSS") indicates that unrecoverable data loss or - // corruption has occurred. As this error is serious, proper alerting should - // be attached to errors such as this. - kDataLoss = 15, - - // StatusCode::kUnauthenticated - // - // kUnauthenticated (gRPC code "UNAUTHENTICATED") indicates that the request - // does not have valid authentication credentials for the operation. Correct - // the authentication and try again. - kUnauthenticated = 16, - - // StatusCode::DoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ - // - // NOTE: this error code entry should not be used and you should not rely on - // its value, which may change. - // - // The purpose of this enumerated value is to force people who handle status - // codes with `switch()` statements to *not* simply enumerate all possible - // values, but instead provide a "default:" case. Providing such a default - // case ensures that code will compile when new codes are added. - kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20 -}; - -// StatusCodeToString() -// -// Returns the name for the status code, or "" if it is an unknown value. -std::string StatusCodeToString(StatusCode code); - -// operator<< -// -// Streams StatusCodeToString(code) to `os`. -std::ostream& operator<<(std::ostream& os, StatusCode code); - -// absl::Status -// -// The `absl::Status` class is generally used to gracefully handle errors -// across API boundaries (and in particular across RPC boundaries). Some of -// these errors may be recoverable, but others may not. Most -// functions which can produce a recoverable error should be designed to return -// either an `absl::Status` (or the similar `absl::StatusOr<T>`, which holds -// either an object of type `T` or an error). -// -// API developers should construct their functions to return `absl::OkStatus()` -// upon success, or an `absl::StatusCode` upon another type of error (e.g -// an `absl::StatusCode::kInvalidArgument` error). The API provides convenience -// functions to constuct each status code. -// -// Example: -// -// absl::Status myFunction(absl::string_view fname, ...) { -// ... -// // encounter error -// if (error condition) { -// // Construct an absl::StatusCode::kInvalidArgument error -// return absl::InvalidArgumentError("bad mode"); -// } -// // else, return OK -// return absl::OkStatus(); -// } -// -// Users handling status error codes should prefer checking for an OK status -// using the `ok()` member function. Handling multiple error codes may justify -// use of switch statement, but only check for error codes you know how to -// handle; do not try to exhaustively match against all canonical error codes. -// Errors that cannot be handled should be logged and/or propagated for higher -// levels to deal with. If you do use a switch statement, make sure that you -// also provide a `default:` switch case, so that code does not break as other -// canonical codes are added to the API. -// -// Example: -// -// absl::Status result = DoSomething(); -// if (!result.ok()) { -// LOG(ERROR) << result; -// } -// -// // Provide a default if switching on multiple error codes -// switch (result.code()) { -// // The user hasn't authenticated. Ask them to reauth -// case absl::StatusCode::kUnauthenticated: -// DoReAuth(); -// break; -// // The user does not have permission. Log an error. -// case absl::StatusCode::kPermissionDenied: -// LOG(ERROR) << result; -// break; -// // Propagate the error otherwise. -// default: -// return true; -// } -// -// An `absl::Status` can optionally include a payload with more information -// about the error. Typically, this payload serves one of several purposes: -// -// * It may provide more fine-grained semantic information about the error to -// facilitate actionable remedies. -// * It may provide human-readable contexual information that is more -// appropriate to display to an end user. -// -// Example: -// -// absl::Status result = DoSomething(); -// // Inform user to retry after 30 seconds -// // See more error details in googleapis/google/rpc/error_details.proto -// if (absl::IsResourceExhausted(result)) { -// google::rpc::RetryInfo info; -// info.retry_delay().seconds() = 30; -// // Payloads require a unique key (a URL to ensure no collisions with -// // other payloads), and an `absl::Cord` to hold the encoded data. -// absl::string_view url = "type.googleapis.com/google.rpc.RetryInfo"; -// result.SetPayload(url, info.SerializeAsCord()); -// return result; -// } -// -class ABSL_MUST_USE_RESULT Status final { - public: - // Constructors - - // This default constructor creates an OK status with no message or payload. - // Avoid this constructor and prefer explicit construction of an OK status - // with `absl::OkStatus()`. - Status(); - - // Creates a status in the canonical error space with the specified - // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`, - // `msg` is ignored and an object identical to an OK status is constructed. - // - // The `msg` string must be in UTF-8. The implementation may complain (e.g., - // by printing a warning) if it is not. - Status(absl::StatusCode code, absl::string_view msg); - - Status(const Status&); - Status& operator=(const Status& x); - - // Move operators - - // The moved-from state is valid but unspecified. - Status(Status&&) noexcept; - Status& operator=(Status&&); - - ~Status(); - - // Status::Update() - // - // Updates the existing status with `new_status` provided that `this->ok()`. - // If the existing status already contains a non-OK error, this update has no - // effect and preserves the current data. Note that this behavior may change - // in the future to augment a current non-ok status with additional - // information about `new_status`. - // - // `Update()` provides a convenient way of keeping track of the first error - // encountered. - // - // Example: - // // Instead of "if (overall_status.ok()) overall_status = new_status" - // overall_status.Update(new_status); - // - void Update(const Status& new_status); - void Update(Status&& new_status); - - // Status::ok() - // - // Returns `true` if `this->ok()`. Prefer checking for an OK status using this - // member function. - ABSL_MUST_USE_RESULT bool ok() const; - - // Status::code() - // - // Returns the canonical error code of type `absl::StatusCode` of this status. - absl::StatusCode code() const; - - // Status::raw_code() - // - // Returns a raw (canonical) error code corresponding to the enum value of - // `google.rpc.Code` definitions within - // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto. - // These values could be out of the range of canonical `absl::StatusCode` - // enum values. - // - // NOTE: This function should only be called when converting to an associated - // wire format. Use `Status::code()` for error handling. - int raw_code() const; - - // Status::message() - // - // Returns the error message associated with this error code, if available. - // Note that this message rarely describes the error code. It is not unusual - // for the error message to be the empty string. As a result, prefer - // `Status::ToString()` for debug logging. - absl::string_view message() const; - - friend bool operator==(const Status&, const Status&); - friend bool operator!=(const Status&, const Status&); - - // Status::ToString() - // - // Returns a combination of the error code name, the message and any - // associated payload messages. This string is designed simply to be human - // readable and its exact format should not be load bearing. Do not depend on - // the exact format of the result of `ToString()` which is subject to change. - // - // The printed code name and the message are generally substrings of the - // result, and the payloads to be printed use the status payload printer - // mechanism (which is internal). - std::string ToString() const; - - // Status::IgnoreError() - // - // Ignores any errors. This method does nothing except potentially suppress - // complaints from any tools that are checking that errors are not dropped on - // the floor. - void IgnoreError() const; - - // swap() - // - // Swap the contents of one status with another. - friend void swap(Status& a, Status& b); - - //---------------------------------------------------------------------------- - // Payload Management APIs - //---------------------------------------------------------------------------- - - // A payload may be attached to a status to provide additional context to an - // error that may not be satisifed by an existing `absl::StatusCode`. - // Typically, this payload serves one of several purposes: - // - // * It may provide more fine-grained semantic information about the error - // to facilitate actionable remedies. - // * It may provide human-readable contexual information that is more - // appropriate to display to an end user. - // - // A payload consists of a [key,value] pair, where the key is a string - // referring to a unique "type URL" and the value is an object of type - // `absl::Cord` to hold the contextual data. - // - // The "type URL" should be unique and follow the format of a URL - // (https://en.wikipedia.org/wiki/URL) and, ideally, provide some - // documentation or schema on how to interpret its associated data. For - // example, the default type URL for a protobuf message type is - // "type.googleapis.com/packagename.messagename". Other custom wire formats - // should define the format of type URL in a similar practice so as to - // minimize the chance of conflict between type URLs. - // Users should ensure that the type URL can be mapped to a concrete - // C++ type if they want to deserialize the payload and read it effectively. - // - // To attach a payload to a status object, call `Status::SetPayload()`, - // passing it the type URL and an `absl::Cord` of associated data. Similarly, - // to extract the payload from a status, call `Status::GetPayload()`. You - // may attach multiple payloads (with differing type URLs) to any given - // status object, provided that the status is currently exhibiting an error - // code (i.e. is not OK). - - // Status::GetPayload() - // - // Gets the payload of a status given its unique `type_url` key, if present. - absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const; - - // Status::SetPayload() - // - // Sets the payload for a non-ok status using a `type_url` key, overwriting - // any existing payload for that `type_url`. - // - // NOTE: This function does nothing if the Status is ok. - void SetPayload(absl::string_view type_url, absl::Cord payload); - - // Status::ErasePayload() - // - // Erases the payload corresponding to the `type_url` key. Returns `true` if - // the payload was present. - bool ErasePayload(absl::string_view type_url); - - // Status::ForEachPayload() - // - // Iterates over the stored payloads and calls the - // `visitor(type_key, payload)` callable for each one. - // - // NOTE: The order of calls to `visitor()` is not specified and may change at - // any time. - // - // NOTE: Any mutation on the same 'absl::Status' object during visitation is - // forbidden and could result in undefined behavior. - void ForEachPayload( - const std::function<void(absl::string_view, const absl::Cord&)>& visitor) - const; - - private: - friend Status CancelledError(); - - // Creates a status in the canonical error space with the specified - // code, and an empty error message. - explicit Status(absl::StatusCode code); - - static void UnrefNonInlined(uintptr_t rep); - static void Ref(uintptr_t rep); - static void Unref(uintptr_t rep); - - // REQUIRES: !ok() - // Ensures rep_ is not shared with any other Status. - void PrepareToModify(); - - const status_internal::Payloads* GetPayloads() const; - status_internal::Payloads* GetPayloads(); - - // Takes ownership of payload. - static uintptr_t NewRep(absl::StatusCode code, absl::string_view msg, - std::unique_ptr<status_internal::Payloads> payload); - static bool EqualsSlow(const absl::Status& a, const absl::Status& b); - - // MSVC 14.0 limitation requires the const. - static constexpr const char kMovedFromString[] = - "Status accessed after move."; - - static const std::string* EmptyString(); - static const std::string* MovedFromString(); - - // Returns whether rep contains an inlined representation. - // See rep_ for details. - static bool IsInlined(uintptr_t rep); - - // Indicates whether this Status was the rhs of a move operation. See rep_ - // for details. - static bool IsMovedFrom(uintptr_t rep); - static uintptr_t MovedFromRep(); - - // Convert between error::Code and the inlined uintptr_t representation used - // by rep_. See rep_ for details. - static uintptr_t CodeToInlinedRep(absl::StatusCode code); - static absl::StatusCode InlinedRepToCode(uintptr_t rep); - - // Converts between StatusRep* and the external uintptr_t representation used - // by rep_. See rep_ for details. - static uintptr_t PointerToRep(status_internal::StatusRep* r); - static status_internal::StatusRep* RepToPointer(uintptr_t r); - - // Returns string for non-ok Status. - std::string ToStringSlow() const; - - // Status supports two different representations. - // - When the low bit is off it is an inlined representation. - // It uses the canonical error space, no message or payload. - // The error code is (rep_ >> 2). - // The (rep_ & 2) bit is the "moved from" indicator, used in IsMovedFrom(). - // - When the low bit is on it is an external representation. - // In this case all the data comes from a heap allocated Rep object. - // (rep_ - 1) is a status_internal::StatusRep* pointer to that structure. - uintptr_t rep_; -}; - -// OkStatus() -// -// Returns an OK status, equivalent to a default constructed instance. Prefer -// usage of `absl::OkStatus()` when constructing such an OK status. -Status OkStatus(); - -// operator<<() -// -// Prints a human-readable representation of `x` to `os`. -std::ostream& operator<<(std::ostream& os, const Status& x); - -// IsAborted() -// IsAlreadyExists() -// IsCancelled() -// IsDataLoss() -// IsDeadlineExceeded() -// IsFailedPrecondition() -// IsInternal() -// IsInvalidArgument() -// IsNotFound() -// IsOutOfRange() -// IsPermissionDenied() -// IsResourceExhausted() -// IsUnauthenticated() -// IsUnavailable() -// IsUnimplemented() -// IsUnknown() -// -// These convenience functions return `true` if a given status matches the -// `absl::StatusCode` error code of its associated function. -ABSL_MUST_USE_RESULT bool IsAborted(const Status& status); -ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status); -ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status); -ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status); -ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status); -ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status); -ABSL_MUST_USE_RESULT bool IsInternal(const Status& status); -ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status); -ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status); -ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status); -ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status); -ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status); -ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status); -ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status); -ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status); -ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status); - -// AbortedError() -// AlreadyExistsError() -// CancelledError() -// DataLossError() -// DeadlineExceededError() -// FailedPreconditionError() -// InternalError() -// InvalidArgumentError() -// NotFoundError() -// OutOfRangeError() -// PermissionDeniedError() -// ResourceExhaustedError() -// UnauthenticatedError() -// UnavailableError() -// UnimplementedError() -// UnknownError() -// -// These convenience functions create an `absl::Status` object with an error -// code as indicated by the associated function name, using the error message -// passed in `message`. -Status AbortedError(absl::string_view message); -Status AlreadyExistsError(absl::string_view message); -Status CancelledError(absl::string_view message); -Status DataLossError(absl::string_view message); -Status DeadlineExceededError(absl::string_view message); -Status FailedPreconditionError(absl::string_view message); -Status InternalError(absl::string_view message); -Status InvalidArgumentError(absl::string_view message); -Status NotFoundError(absl::string_view message); -Status OutOfRangeError(absl::string_view message); -Status PermissionDeniedError(absl::string_view message); -Status ResourceExhaustedError(absl::string_view message); -Status UnauthenticatedError(absl::string_view message); -Status UnavailableError(absl::string_view message); -Status UnimplementedError(absl::string_view message); -Status UnknownError(absl::string_view message); - -//------------------------------------------------------------------------------ -// Implementation details follow -//------------------------------------------------------------------------------ - -inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {} - -inline Status::Status(absl::StatusCode code) : rep_(CodeToInlinedRep(code)) {} - -inline Status::Status(const Status& x) : rep_(x.rep_) { Ref(rep_); } - -inline Status& Status::operator=(const Status& x) { - uintptr_t old_rep = rep_; - if (x.rep_ != old_rep) { - Ref(x.rep_); - rep_ = x.rep_; - Unref(old_rep); - } - return *this; -} - -inline Status::Status(Status&& x) noexcept : rep_(x.rep_) { - x.rep_ = MovedFromRep(); -} - -inline Status& Status::operator=(Status&& x) { - uintptr_t old_rep = rep_; - rep_ = x.rep_; - x.rep_ = MovedFromRep(); - Unref(old_rep); - return *this; -} - -inline void Status::Update(const Status& new_status) { - if (ok()) { - *this = new_status; - } -} - -inline void Status::Update(Status&& new_status) { - if (ok()) { - *this = std::move(new_status); - } -} - -inline Status::~Status() { Unref(rep_); } - -inline bool Status::ok() const { - return rep_ == CodeToInlinedRep(absl::StatusCode::kOk); -} - -inline absl::string_view Status::message() const { - return !IsInlined(rep_) - ? RepToPointer(rep_)->message - : (IsMovedFrom(rep_) ? absl::string_view(kMovedFromString) - : absl::string_view()); -} - -inline bool operator==(const Status& lhs, const Status& rhs) { - return lhs.rep_ == rhs.rep_ || Status::EqualsSlow(lhs, rhs); -} - -inline bool operator!=(const Status& lhs, const Status& rhs) { - return !(lhs == rhs); -} - -inline std::string Status::ToString() const { - return ok() ? "OK" : ToStringSlow(); -} - -inline void Status::IgnoreError() const { - // no-op -} - -inline void swap(absl::Status& a, absl::Status& b) { - using std::swap; - swap(a.rep_, b.rep_); -} - -inline const status_internal::Payloads* Status::GetPayloads() const { - return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get(); -} - -inline status_internal::Payloads* Status::GetPayloads() { - return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get(); -} - -inline bool Status::IsInlined(uintptr_t rep) { return (rep & 1) == 0; } - -inline bool Status::IsMovedFrom(uintptr_t rep) { - return IsInlined(rep) && (rep & 2) != 0; -} - -inline uintptr_t Status::MovedFromRep() { - return CodeToInlinedRep(absl::StatusCode::kInternal) | 2; -} - -inline uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) { - return static_cast<uintptr_t>(code) << 2; -} - -inline absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) { - assert(IsInlined(rep)); - return static_cast<absl::StatusCode>(rep >> 2); -} - -inline status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) { - assert(!IsInlined(rep)); - return reinterpret_cast<status_internal::StatusRep*>(rep - 1); -} - -inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) { - return reinterpret_cast<uintptr_t>(rep) + 1; -} - -inline void Status::Ref(uintptr_t rep) { - if (!IsInlined(rep)) { - RepToPointer(rep)->ref.fetch_add(1, std::memory_order_relaxed); - } -} - -inline void Status::Unref(uintptr_t rep) { - if (!IsInlined(rep)) { - UnrefNonInlined(rep); - } -} - -inline Status OkStatus() { return Status(); } - -// Creates a `Status` object with the `absl::StatusCode::kCancelled` error code -// and an empty message. It is provided only for efficiency, given that -// message-less kCancelled errors are common in the infrastructure. -inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); } - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_STATUS_H_ diff --git a/third_party/abseil_cpp/absl/status/status_payload_printer.cc b/third_party/abseil_cpp/absl/status/status_payload_printer.cc deleted file mode 100644 index a47aea11c2d3..000000000000 --- a/third_party/abseil_cpp/absl/status/status_payload_printer.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2019 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/status_payload_printer.h" - -#include <atomic> - -#include "absl/base/attributes.h" -#include "absl/base/internal/atomic_hook.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace status_internal { - -ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES -static absl::base_internal::AtomicHook<StatusPayloadPrinter> storage; - -void SetStatusPayloadPrinter(StatusPayloadPrinter printer) { - storage.Store(printer); -} - -StatusPayloadPrinter GetStatusPayloadPrinter() { - return storage.Load(); -} - -} // namespace status_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/status/status_payload_printer.h b/third_party/abseil_cpp/absl/status/status_payload_printer.h deleted file mode 100644 index 5e0937f67da8..000000000000 --- a/third_party/abseil_cpp/absl/status/status_payload_printer.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2019 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. -#ifndef ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_ -#define ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_ - -#include <string> - -#include "absl/strings/cord.h" -#include "absl/strings/string_view.h" -#include "absl/types/optional.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace status_internal { - -// By default, `Status::ToString` and `operator<<(Status)` print a payload by -// dumping the type URL and the raw bytes. To help debugging, we provide an -// extension point, which is a global printer function that can be set by users -// to specify how to print payloads. The function takes the type URL and the -// payload as input, and should return a valid human-readable string on success -// or `absl::nullopt` on failure (in which case it falls back to the default -// approach of printing the raw bytes). -// NOTE: This is an internal API and the design is subject to change in the -// future in a non-backward-compatible way. Since it's only meant for debugging -// purpose, you should not rely on it in any critical logic. -using StatusPayloadPrinter = absl::optional<std::string> (*)(absl::string_view, - const absl::Cord&); - -// Sets the global payload printer. Only one printer should be set per process. -// If multiple printers are set, it's undefined which one will be used. -void SetStatusPayloadPrinter(StatusPayloadPrinter); - -// Returns the global payload printer if previously set, otherwise `nullptr`. -StatusPayloadPrinter GetStatusPayloadPrinter(); - -} // namespace status_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_ diff --git a/third_party/abseil_cpp/absl/status/status_test.cc b/third_party/abseil_cpp/absl/status/status_test.cc deleted file mode 100644 index ca9488ad228c..000000000000 --- a/third_party/abseil_cpp/absl/status/status_test.cc +++ /dev/null @@ -1,458 +0,0 @@ -// Copyright 2019 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/status.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/strings/str_cat.h" - -namespace { - -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Optional; -using ::testing::UnorderedElementsAreArray; - -TEST(StatusCode, InsertionOperator) { - const absl::StatusCode code = absl::StatusCode::kUnknown; - std::ostringstream oss; - oss << code; - EXPECT_EQ(oss.str(), absl::StatusCodeToString(code)); -} - -// This structure holds the details for testing a single error code, -// its creator, and its classifier. -struct ErrorTest { - absl::StatusCode code; - using Creator = absl::Status (*)(absl::string_view); - using Classifier = bool (*)(const absl::Status&); - Creator creator; - Classifier classifier; -}; - -constexpr ErrorTest kErrorTests[]{ - {absl::StatusCode::kCancelled, absl::CancelledError, absl::IsCancelled}, - {absl::StatusCode::kUnknown, absl::UnknownError, absl::IsUnknown}, - {absl::StatusCode::kInvalidArgument, absl::InvalidArgumentError, - absl::IsInvalidArgument}, - {absl::StatusCode::kDeadlineExceeded, absl::DeadlineExceededError, - absl::IsDeadlineExceeded}, - {absl::StatusCode::kNotFound, absl::NotFoundError, absl::IsNotFound}, - {absl::StatusCode::kAlreadyExists, absl::AlreadyExistsError, - absl::IsAlreadyExists}, - {absl::StatusCode::kPermissionDenied, absl::PermissionDeniedError, - absl::IsPermissionDenied}, - {absl::StatusCode::kResourceExhausted, absl::ResourceExhaustedError, - absl::IsResourceExhausted}, - {absl::StatusCode::kFailedPrecondition, absl::FailedPreconditionError, - absl::IsFailedPrecondition}, - {absl::StatusCode::kAborted, absl::AbortedError, absl::IsAborted}, - {absl::StatusCode::kOutOfRange, absl::OutOfRangeError, absl::IsOutOfRange}, - {absl::StatusCode::kUnimplemented, absl::UnimplementedError, - absl::IsUnimplemented}, - {absl::StatusCode::kInternal, absl::InternalError, absl::IsInternal}, - {absl::StatusCode::kUnavailable, absl::UnavailableError, - absl::IsUnavailable}, - {absl::StatusCode::kDataLoss, absl::DataLossError, absl::IsDataLoss}, - {absl::StatusCode::kUnauthenticated, absl::UnauthenticatedError, - absl::IsUnauthenticated}, -}; - -TEST(Status, CreateAndClassify) { - for (const auto& test : kErrorTests) { - SCOPED_TRACE(absl::StatusCodeToString(test.code)); - - // Ensure that the creator does, in fact, create status objects with the - // expected error code and message. - std::string message = - absl::StrCat("error code ", test.code, " test message"); - absl::Status status = test.creator(message); - EXPECT_EQ(test.code, status.code()); - EXPECT_EQ(message, status.message()); - - // Ensure that the classifier returns true for a status produced by the - // creator. - EXPECT_TRUE(test.classifier(status)); - - // Ensure that the classifier returns false for status with a different - // code. - for (const auto& other : kErrorTests) { - if (other.code != test.code) { - EXPECT_FALSE(test.classifier(absl::Status(other.code, ""))) - << " other.code = " << other.code; - } - } - } -} - -TEST(Status, DefaultConstructor) { - absl::Status status; - EXPECT_TRUE(status.ok()); - EXPECT_EQ(absl::StatusCode::kOk, status.code()); - EXPECT_EQ("", status.message()); -} - -TEST(Status, OkStatus) { - absl::Status status = absl::OkStatus(); - EXPECT_TRUE(status.ok()); - EXPECT_EQ(absl::StatusCode::kOk, status.code()); - EXPECT_EQ("", status.message()); -} - -TEST(Status, ConstructorWithCodeMessage) { - { - absl::Status status(absl::StatusCode::kCancelled, ""); - EXPECT_FALSE(status.ok()); - EXPECT_EQ(absl::StatusCode::kCancelled, status.code()); - EXPECT_EQ("", status.message()); - } - { - absl::Status status(absl::StatusCode::kInternal, "message"); - EXPECT_FALSE(status.ok()); - EXPECT_EQ(absl::StatusCode::kInternal, status.code()); - EXPECT_EQ("message", status.message()); - } -} - -TEST(Status, ConstructOutOfRangeCode) { - const int kRawCode = 9999; - absl::Status status(static_cast<absl::StatusCode>(kRawCode), ""); - EXPECT_EQ(absl::StatusCode::kUnknown, status.code()); - EXPECT_EQ(kRawCode, status.raw_code()); -} - -constexpr char kUrl1[] = "url.payload.1"; -constexpr char kUrl2[] = "url.payload.2"; -constexpr char kUrl3[] = "url.payload.3"; -constexpr char kUrl4[] = "url.payload.xx"; - -constexpr char kPayload1[] = "aaaaa"; -constexpr char kPayload2[] = "bbbbb"; -constexpr char kPayload3[] = "ccccc"; - -using PayloadsVec = std::vector<std::pair<std::string, absl::Cord>>; - -TEST(Status, TestGetSetPayload) { - absl::Status ok_status = absl::OkStatus(); - ok_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - ok_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - - EXPECT_FALSE(ok_status.GetPayload(kUrl1)); - EXPECT_FALSE(ok_status.GetPayload(kUrl2)); - - absl::Status bad_status(absl::StatusCode::kInternal, "fail"); - bad_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - bad_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - - EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload1))); - EXPECT_THAT(bad_status.GetPayload(kUrl2), Optional(Eq(kPayload2))); - - EXPECT_FALSE(bad_status.GetPayload(kUrl3)); - - bad_status.SetPayload(kUrl1, absl::Cord(kPayload3)); - EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload3))); - - // Testing dynamically generated type_url - bad_status.SetPayload(absl::StrCat(kUrl1, ".1"), absl::Cord(kPayload1)); - EXPECT_THAT(bad_status.GetPayload(absl::StrCat(kUrl1, ".1")), - Optional(Eq(kPayload1))); -} - -TEST(Status, TestErasePayload) { - absl::Status bad_status(absl::StatusCode::kInternal, "fail"); - bad_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - bad_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - bad_status.SetPayload(kUrl3, absl::Cord(kPayload3)); - - EXPECT_FALSE(bad_status.ErasePayload(kUrl4)); - - EXPECT_TRUE(bad_status.GetPayload(kUrl2)); - EXPECT_TRUE(bad_status.ErasePayload(kUrl2)); - EXPECT_FALSE(bad_status.GetPayload(kUrl2)); - EXPECT_FALSE(bad_status.ErasePayload(kUrl2)); - - EXPECT_TRUE(bad_status.ErasePayload(kUrl1)); - EXPECT_TRUE(bad_status.ErasePayload(kUrl3)); - - bad_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - EXPECT_TRUE(bad_status.ErasePayload(kUrl1)); -} - -TEST(Status, TestComparePayloads) { - absl::Status bad_status1(absl::StatusCode::kInternal, "fail"); - bad_status1.SetPayload(kUrl1, absl::Cord(kPayload1)); - bad_status1.SetPayload(kUrl2, absl::Cord(kPayload2)); - bad_status1.SetPayload(kUrl3, absl::Cord(kPayload3)); - - absl::Status bad_status2(absl::StatusCode::kInternal, "fail"); - bad_status2.SetPayload(kUrl2, absl::Cord(kPayload2)); - bad_status2.SetPayload(kUrl3, absl::Cord(kPayload3)); - bad_status2.SetPayload(kUrl1, absl::Cord(kPayload1)); - - EXPECT_EQ(bad_status1, bad_status2); -} - -TEST(Status, TestComparePayloadsAfterErase) { - absl::Status payload_status(absl::StatusCode::kInternal, ""); - payload_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - payload_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - - absl::Status empty_status(absl::StatusCode::kInternal, ""); - - // Different payloads, not equal - EXPECT_NE(payload_status, empty_status); - EXPECT_TRUE(payload_status.ErasePayload(kUrl1)); - - // Still Different payloads, still not equal. - EXPECT_NE(payload_status, empty_status); - EXPECT_TRUE(payload_status.ErasePayload(kUrl2)); - - // Both empty payloads, should be equal - EXPECT_EQ(payload_status, empty_status); -} - -PayloadsVec AllVisitedPayloads(const absl::Status& s) { - PayloadsVec result; - - s.ForEachPayload([&](absl::string_view type_url, const absl::Cord& payload) { - result.push_back(std::make_pair(std::string(type_url), payload)); - }); - - return result; -} - -TEST(Status, TestForEachPayload) { - absl::Status bad_status(absl::StatusCode::kInternal, "fail"); - bad_status.SetPayload(kUrl1, absl::Cord(kPayload1)); - bad_status.SetPayload(kUrl2, absl::Cord(kPayload2)); - bad_status.SetPayload(kUrl3, absl::Cord(kPayload3)); - - int count = 0; - - bad_status.ForEachPayload( - [&count](absl::string_view, const absl::Cord&) { ++count; }); - - EXPECT_EQ(count, 3); - - PayloadsVec expected_payloads = {{kUrl1, absl::Cord(kPayload1)}, - {kUrl2, absl::Cord(kPayload2)}, - {kUrl3, absl::Cord(kPayload3)}}; - - // Test that we visit all the payloads in the status. - PayloadsVec visited_payloads = AllVisitedPayloads(bad_status); - EXPECT_THAT(visited_payloads, UnorderedElementsAreArray(expected_payloads)); - - // Test that visitation order is not consistent between run. - std::vector<absl::Status> scratch; - while (true) { - scratch.emplace_back(absl::StatusCode::kInternal, "fail"); - - scratch.back().SetPayload(kUrl1, absl::Cord(kPayload1)); - scratch.back().SetPayload(kUrl2, absl::Cord(kPayload2)); - scratch.back().SetPayload(kUrl3, absl::Cord(kPayload3)); - - if (AllVisitedPayloads(scratch.back()) != visited_payloads) { - break; - } - } -} - -TEST(Status, ToString) { - absl::Status s(absl::StatusCode::kInternal, "fail"); - EXPECT_EQ("INTERNAL: fail", s.ToString()); - s.SetPayload("foo", absl::Cord("bar")); - EXPECT_EQ("INTERNAL: fail [foo='bar']", s.ToString()); - s.SetPayload("bar", absl::Cord("\377")); - EXPECT_THAT(s.ToString(), - AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), - HasSubstr("[bar='\\xff']"))); -} - -absl::Status EraseAndReturn(const absl::Status& base) { - absl::Status copy = base; - EXPECT_TRUE(copy.ErasePayload(kUrl1)); - return copy; -} - -TEST(Status, CopyOnWriteForErasePayload) { - { - absl::Status base(absl::StatusCode::kInvalidArgument, "fail"); - base.SetPayload(kUrl1, absl::Cord(kPayload1)); - EXPECT_TRUE(base.GetPayload(kUrl1).has_value()); - absl::Status copy = EraseAndReturn(base); - EXPECT_TRUE(base.GetPayload(kUrl1).has_value()); - EXPECT_FALSE(copy.GetPayload(kUrl1).has_value()); - } - { - absl::Status base(absl::StatusCode::kInvalidArgument, "fail"); - base.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status copy = base; - - EXPECT_TRUE(base.GetPayload(kUrl1).has_value()); - EXPECT_TRUE(copy.GetPayload(kUrl1).has_value()); - - EXPECT_TRUE(base.ErasePayload(kUrl1)); - - EXPECT_FALSE(base.GetPayload(kUrl1).has_value()); - EXPECT_TRUE(copy.GetPayload(kUrl1).has_value()); - } -} - -TEST(Status, CopyConstructor) { - { - absl::Status status; - absl::Status copy(status); - EXPECT_EQ(copy, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - absl::Status copy(status); - EXPECT_EQ(copy, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - status.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status copy(status); - EXPECT_EQ(copy, status); - } -} - -TEST(Status, CopyAssignment) { - absl::Status assignee; - { - absl::Status status; - assignee = status; - EXPECT_EQ(assignee, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - assignee = status; - EXPECT_EQ(assignee, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - status.SetPayload(kUrl1, absl::Cord(kPayload1)); - assignee = status; - EXPECT_EQ(assignee, status); - } -} - -TEST(Status, CopyAssignmentIsNotRef) { - const absl::Status status_orig(absl::StatusCode::kInvalidArgument, "message"); - absl::Status status_copy = status_orig; - EXPECT_EQ(status_orig, status_copy); - status_copy.SetPayload(kUrl1, absl::Cord(kPayload1)); - EXPECT_NE(status_orig, status_copy); -} - -TEST(Status, MoveConstructor) { - { - absl::Status status; - absl::Status copy(absl::Status{}); - EXPECT_EQ(copy, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - absl::Status copy( - absl::Status(absl::StatusCode::kInvalidArgument, "message")); - EXPECT_EQ(copy, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - status.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status copy1(status); - absl::Status copy2(std::move(status)); - EXPECT_EQ(copy1, copy2); - } -} - -TEST(Status, MoveAssignment) { - absl::Status assignee; - { - absl::Status status; - assignee = absl::Status(); - EXPECT_EQ(assignee, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - assignee = absl::Status(absl::StatusCode::kInvalidArgument, "message"); - EXPECT_EQ(assignee, status); - } - { - absl::Status status(absl::StatusCode::kInvalidArgument, "message"); - status.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status copy(status); - assignee = std::move(status); - EXPECT_EQ(assignee, copy); - } -} - -TEST(Status, Update) { - absl::Status s; - s.Update(absl::OkStatus()); - EXPECT_TRUE(s.ok()); - const absl::Status a(absl::StatusCode::kCancelled, "message"); - s.Update(a); - EXPECT_EQ(s, a); - const absl::Status b(absl::StatusCode::kInternal, "other message"); - s.Update(b); - EXPECT_EQ(s, a); - s.Update(absl::OkStatus()); - EXPECT_EQ(s, a); - EXPECT_FALSE(s.ok()); -} - -TEST(Status, Equality) { - absl::Status ok; - absl::Status no_payload = absl::CancelledError("no payload"); - absl::Status one_payload = absl::InvalidArgumentError("one payload"); - one_payload.SetPayload(kUrl1, absl::Cord(kPayload1)); - absl::Status two_payloads = one_payload; - two_payloads.SetPayload(kUrl2, absl::Cord(kPayload2)); - const std::array<absl::Status, 4> status_arr = {ok, no_payload, one_payload, - two_payloads}; - for (int i = 0; i < status_arr.size(); i++) { - for (int j = 0; j < status_arr.size(); j++) { - if (i == j) { - EXPECT_TRUE(status_arr[i] == status_arr[j]); - EXPECT_FALSE(status_arr[i] != status_arr[j]); - } else { - EXPECT_TRUE(status_arr[i] != status_arr[j]); - EXPECT_FALSE(status_arr[i] == status_arr[j]); - } - } - } -} - -TEST(Status, Swap) { - auto test_swap = [](const absl::Status& s1, const absl::Status& s2) { - absl::Status copy1 = s1, copy2 = s2; - swap(copy1, copy2); - EXPECT_EQ(copy1, s2); - EXPECT_EQ(copy2, s1); - }; - const absl::Status ok; - const absl::Status no_payload(absl::StatusCode::kAlreadyExists, "no payload"); - absl::Status with_payload(absl::StatusCode::kInternal, "with payload"); - with_payload.SetPayload(kUrl1, absl::Cord(kPayload1)); - test_swap(ok, no_payload); - test_swap(no_payload, ok); - test_swap(ok, with_payload); - test_swap(with_payload, ok); - test_swap(no_payload, with_payload); - test_swap(with_payload, no_payload); -} - -} // namespace diff --git a/third_party/abseil_cpp/absl/status/statusor.cc b/third_party/abseil_cpp/absl/status/statusor.cc deleted file mode 100644 index b954b45e32c7..000000000000 --- a/third_party/abseil_cpp/absl/status/statusor.cc +++ /dev/null @@ -1,71 +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 <cstdlib> -#include <utility> - -#include "absl/base/internal/raw_logging.h" -#include "absl/status/status.h" -#include "absl/strings/str_cat.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -BadStatusOrAccess::BadStatusOrAccess(absl::Status status) - : status_(std::move(status)) {} - -BadStatusOrAccess::~BadStatusOrAccess() = default; -const char* BadStatusOrAccess::what() const noexcept { - return "Bad StatusOr access"; -} - -const absl::Status& BadStatusOrAccess::status() const { return status_; } - -namespace internal_statusor { - -void Helper::HandleInvalidStatusCtorArg(absl::Status* status) { - const char* kMessage = - "An OK status is not a valid constructor argument to StatusOr<T>"; -#ifdef NDEBUG - ABSL_INTERNAL_LOG(ERROR, kMessage); -#else - ABSL_INTERNAL_LOG(FATAL, kMessage); -#endif - // In optimized builds, we will fall back to InternalError. - *status = absl::InternalError(kMessage); -} - -void Helper::Crash(const absl::Status& status) { - ABSL_INTERNAL_LOG( - FATAL, - absl::StrCat("Attempting to fetch value instead of handling error ", - status.ToString())); -} - -void ThrowBadStatusOrAccess(absl::Status status) { -#ifdef ABSL_HAVE_EXCEPTIONS - throw absl::BadStatusOrAccess(std::move(status)); -#else - ABSL_INTERNAL_LOG( - FATAL, - absl::StrCat("Attempting to fetch value instead of handling error ", - status.ToString())); - std::abort(); -#endif -} - -} // namespace internal_statusor -ABSL_NAMESPACE_END -} // namespace absl diff --git a/third_party/abseil_cpp/absl/status/statusor.h b/third_party/abseil_cpp/absl/status/statusor.h deleted file mode 100644 index 469d486fdd2e..000000000000 --- a/third_party/abseil_cpp/absl/status/statusor.h +++ /dev/null @@ -1,760 +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. -// -// ----------------------------------------------------------------------------- -// File: statusor.h -// ----------------------------------------------------------------------------- -// -// An `absl::StatusOr<T>` represents a union of an `absl::Status` object -// and an object of type `T`. The `absl::StatusOr<T>` will either contain an -// object of type `T` (indicating a successful operation), or an error (of type -// `absl::Status`) explaining why such a value is not present. -// -// In general, check the success of an operation returning an -// `absl::StatusOr<T>` like you would an `absl::Status` by using the `ok()` -// member function. -// -// Example: -// -// StatusOr<Foo> result = Calculation(); -// if (result.ok()) { -// result->DoSomethingCool(); -// } else { -// LOG(ERROR) << result.status(); -// } -#ifndef ABSL_STATUS_STATUSOR_H_ -#define ABSL_STATUS_STATUSOR_H_ - -#include <exception> -#include <initializer_list> -#include <new> -#include <string> -#include <type_traits> -#include <utility> - -#include "absl/base/attributes.h" -#include "absl/meta/type_traits.h" -#include "absl/status/internal/statusor_internal.h" -#include "absl/status/status.h" -#include "absl/types/variant.h" -#include "absl/utility/utility.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -// BadStatusOrAccess -// -// This class defines the type of object to throw (if exceptions are enabled), -// when accessing the value of an `absl::StatusOr<T>` object that does not -// contain a value. This behavior is analogous to that of -// `std::bad_optional_access` in the case of accessing an invalid -// `std::optional` value. -// -// Example: -// -// try { -// absl::StatusOr<int> v = FetchInt(); -// DoWork(v.value()); // Accessing value() when not "OK" may throw -// } catch (absl::BadStatusOrAccess& ex) { -// LOG(ERROR) << ex.status(); -// } -class BadStatusOrAccess : public std::exception { - public: - explicit BadStatusOrAccess(absl::Status status); - ~BadStatusOrAccess() override; - - // BadStatusOrAccess::what() - // - // Returns the associated explanatory string of the `absl::StatusOr<T>` - // object's error code. This function only returns the string literal "Bad - // StatusOr Access" for cases when evaluating general exceptions. - // - // The pointer of this string is guaranteed to be valid until any non-const - // function is invoked on the exception object. - const char* what() const noexcept override; - - // BadStatusOrAccess::status() - // - // Returns the associated `absl::Status` of the `absl::StatusOr<T>` object's - // error. - const absl::Status& status() const; - - private: - absl::Status status_; -}; - -// Returned StatusOr objects may not be ignored. -template <typename T> -class ABSL_MUST_USE_RESULT StatusOr; - -// absl::StatusOr<T> -// -// The `absl::StatusOr<T>` class template is a union of an `absl::Status` object -// and an object of type `T`. The `absl::StatusOr<T>` models an object that is -// either a usable object, or an error (of type `absl::Status`) explaining why -// such an object is not present. An `absl::StatusOr<T>` is typically the return -// value of a function which may fail. -// -// An `absl::StatusOr<T>` can never hold an "OK" status (an -// `absl::StatusCode::kOk` value); instead, the presence of an object of type -// `T` indicates success. Instead of checking for a `kOk` value, use the -// `absl::StatusOr<T>::ok()` member function. (It is for this reason, and code -// readability, that using the `ok()` function is preferred for `absl::Status` -// as well.) -// -// Example: -// -// StatusOr<Foo> result = DoBigCalculationThatCouldFail(); -// if (result.ok()) { -// result->DoSomethingCool(); -// } else { -// LOG(ERROR) << result.status(); -// } -// -// Accessing the object held by an `absl::StatusOr<T>` should be performed via -// `operator*` or `operator->`, after a call to `ok()` confirms that the -// `absl::StatusOr<T>` holds an object of type `T`: -// -// Example: -// -// absl::StatusOr<int> i = GetCount(); -// if (i.ok()) { -// updated_total += *i -// } -// -// NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will -// throw an exception if exceptions are enabled or terminate the process when -// execeptions are not enabled. -// -// Example: -// -// StatusOr<Foo> result = DoBigCalculationThatCouldFail(); -// const Foo& foo = result.value(); // Crash/exception if no value present -// foo.DoSomethingCool(); -// -// A `absl::StatusOr<T*>` can be constructed from a null pointer like any other -// pointer value, and the result will be that `ok()` returns `true` and -// `value()` returns `nullptr`. Checking the value of pointer in an -// `absl::StatusOr<T>` generally requires a bit more care, to ensure both that a -// value is present and that value is not null: -// -// StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg); -// if (!result.ok()) { -// LOG(ERROR) << result.status(); -// } else if (*result == nullptr) { -// LOG(ERROR) << "Unexpected null pointer"; -// } else { -// (*result)->DoSomethingCool(); -// } -// -// Example factory implementation returning StatusOr<T>: -// -// StatusOr<Foo> FooFactory::MakeFoo(int arg) { -// if (arg <= 0) { -// return absl::Status(absl::StatusCode::kInvalidArgument, -// "Arg must be positive"); -// } -// return Foo(arg); -// } -template <typename T> -class StatusOr : private internal_statusor::StatusOrData<T>, - private internal_statusor::CopyCtorBase<T>, - private internal_statusor::MoveCtorBase<T>, - private internal_statusor::CopyAssignBase<T>, - private internal_statusor::MoveAssignBase<T> { - template <typename U> - friend class StatusOr; - - typedef internal_statusor::StatusOrData<T> Base; - - public: - // StatusOr<T>::value_type - // - // This instance data provides a generic `value_type` member for use within - // generic programming. This usage is analogous to that of - // `optional::value_type` in the case of `std::optional`. - typedef T value_type; - - // Constructors - - // Constructs a new `absl::StatusOr` with an `absl::StatusCode::kUnknown` - // status. This constructor is marked 'explicit' to prevent usages in return - // values such as 'return {};', under the misconception that - // `absl::StatusOr<std::vector<int>>` will be initialized with an empty - // vector, instead of an `absl::StatusCode::kUnknown` error code. - explicit StatusOr(); - - // `StatusOr<T>` is copy constructible if `T` is copy constructible. - StatusOr(const StatusOr&) = default; - // `StatusOr<T>` is copy assignable if `T` is copy constructible and copy - // assignable. - StatusOr& operator=(const StatusOr&) = default; - - // `StatusOr<T>` is move constructible if `T` is move constructible. - StatusOr(StatusOr&&) = default; - // `StatusOr<T>` is moveAssignable if `T` is move constructible and move - // assignable. - StatusOr& operator=(StatusOr&&) = default; - - // Converting Constructors - - // Constructs a new `absl::StatusOr<T>` from an `absl::StatusOr<U>`, when `T` - // is constructible from `U`. To avoid ambiguity, these constructors are - // disabled if `T` is also constructible from `StatusOr<U>.`. This constructor - // is explicit if and only if the corresponding construction of `T` from `U` - // is explicit. (This constructor inherits its explicitness from the - // underlying constructor.) - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, - std::is_convertible<const U&, T>, - absl::negation< - internal_statusor::IsConstructibleOrConvertibleFromStatusOr< - T, U>>>::value, - int> = 0> - StatusOr(const StatusOr<U>& other) // NOLINT - : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {} - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, - absl::negation<std::is_convertible<const U&, T>>, - absl::negation< - internal_statusor::IsConstructibleOrConvertibleFromStatusOr< - T, U>>>::value, - int> = 0> - explicit StatusOr(const StatusOr<U>& other) - : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {} - - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>, - std::is_convertible<U&&, T>, - absl::negation< - internal_statusor::IsConstructibleOrConvertibleFromStatusOr< - T, U>>>::value, - int> = 0> - StatusOr(StatusOr<U>&& other) // NOLINT - : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {} - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>, - absl::negation<std::is_convertible<U&&, T>>, - absl::negation< - internal_statusor::IsConstructibleOrConvertibleFromStatusOr< - T, U>>>::value, - int> = 0> - explicit StatusOr(StatusOr<U>&& other) - : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {} - - // Converting Assignment Operators - - // Creates an `absl::StatusOr<T>` through assignment from an - // `absl::StatusOr<U>` when: - // - // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` are OK by assigning - // `U` to `T` directly. - // * `absl::StatusOr<T>` is OK and `absl::StatusOr<U>` contains an error - // code by destroying `absl::StatusOr<T>`'s value and assigning from - // `absl::StatusOr<U>' - // * `absl::StatusOr<T>` contains an error code and `absl::StatusOr<U>` is - // OK by directly initializing `T` from `U`. - // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` contain an error - // code by assigning the `Status` in `absl::StatusOr<U>` to - // `absl::StatusOr<T>` - // - // These overloads only apply if `absl::StatusOr<T>` is constructible and - // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly - // assigned from `StatusOr<U>`. - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, - std::is_constructible<T, const U&>, - std::is_assignable<T, const U&>, - absl::negation< - internal_statusor:: - IsConstructibleOrConvertibleOrAssignableFromStatusOr< - T, U>>>::value, - int> = 0> - StatusOr& operator=(const StatusOr<U>& other) { - this->Assign(other); - return *this; - } - template < - typename U, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>, - std::is_assignable<T, U&&>, - absl::negation< - internal_statusor:: - IsConstructibleOrConvertibleOrAssignableFromStatusOr< - T, U>>>::value, - int> = 0> - StatusOr& operator=(StatusOr<U>&& other) { - this->Assign(std::move(other)); - return *this; - } - - // Constructs a new `absl::StatusOr<T>` with a non-ok status. After calling - // this constructor, `this->ok()` will be `false` and calls to `value()` will - // crash, or produce an exception if exceptions are enabled. - // - // The constructor also takes any type `U` that is convertible to - // `absl::Status`. This constructor is explicit if an only if `U` is not of - // type `absl::Status` and the conversion from `U` to `Status` is explicit. - // - // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed. - // In optimized builds, passing absl::OkStatus() here will have the effect - // of passing absl::StatusCode::kInternal as a fallback. - template < - typename U = absl::Status, - absl::enable_if_t< - absl::conjunction< - std::is_convertible<U&&, absl::Status>, - std::is_constructible<absl::Status, U&&>, - absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>, - absl::negation<std::is_same<absl::decay_t<U>, T>>, - absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>, - absl::negation<internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>::value, - int> = 0> - StatusOr(U&& v) : Base(std::forward<U>(v)) {} - - template < - typename U = absl::Status, - absl::enable_if_t< - absl::conjunction< - absl::negation<std::is_convertible<U&&, absl::Status>>, - std::is_constructible<absl::Status, U&&>, - absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>, - absl::negation<std::is_same<absl::decay_t<U>, T>>, - absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>, - absl::negation<internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>::value, - int> = 0> - explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {} - - template < - typename U = absl::Status, - absl::enable_if_t< - absl::conjunction< - std::is_convertible<U&&, absl::Status>, - std::is_constructible<absl::Status, U&&>, - absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>, - absl::negation<std::is_same<absl::decay_t<U>, T>>, - absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>, - absl::negation<internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>::value, - int> = 0> - StatusOr& operator=(U&& v) { - this->AssignStatus(std::forward<U>(v)); - return *this; - } - - // Perfect-forwarding value assignment operator. - - // If `*this` contains a `T` value before the call, the contained value is - // assigned from `std::forward<U>(v)`; Otherwise, it is directly-initialized - // from `std::forward<U>(v)`. - // This function does not participate in overload unless: - // 1. `std::is_constructible_v<T, U>` is true, - // 2. `std::is_assignable_v<T&, U>` is true. - // 3. `std::is_same_v<StatusOr<T>, std::remove_cvref_t<U>>` is false. - // 4. Assigning `U` to `T` is not ambiguous: - // If `U` is `StatusOr<V>` and `T` is constructible and assignable from - // both `StatusOr<V>` and `V`, the assignment is considered bug-prone and - // ambiguous thus will fail to compile. For example: - // StatusOr<bool> s1 = true; // s1.ok() && *s1 == true - // StatusOr<bool> s2 = false; // s2.ok() && *s2 == false - // s1 = s2; // ambiguous, `s1 = *s2` or `s1 = bool(s2)`? - template < - typename U = T, - typename = typename std::enable_if<absl::conjunction< - std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>, - absl::disjunction< - std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, T>, - absl::conjunction< - absl::negation<std::is_convertible<U&&, absl::Status>>, - absl::negation<internal_statusor:: - HasConversionOperatorToStatusOr<T, U&&>>>>, - internal_statusor::IsForwardingAssignmentValid<T, U&&>>::value>::type> - StatusOr& operator=(U&& v) { - this->Assign(std::forward<U>(v)); - return *this; - } - - // Constructs the inner value `T` in-place using the provided args, using the - // `T(args...)` constructor. - template <typename... Args> - explicit StatusOr(absl::in_place_t, Args&&... args); - template <typename U, typename... Args> - explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist, - Args&&... args); - - // Constructs the inner value `T` in-place using the provided args, using the - // `T(U)` (direct-initialization) constructor. This constructor is only valid - // if `T` can be constructed from a `U`. Can accept move or copy constructors. - // - // This constructor is explicit if `U` is not convertible to `T`. To avoid - // ambiguity, this constuctor is disabled if `U` is a `StatusOr<J>`, where `J` - // is convertible to `T`. - template < - typename U = T, - absl::enable_if_t< - absl::conjunction< - internal_statusor::IsDirectInitializationValid<T, U&&>, - std::is_constructible<T, U&&>, std::is_convertible<U&&, T>, - absl::disjunction< - std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, - T>, - absl::conjunction< - absl::negation<std::is_convertible<U&&, absl::Status>>, - absl::negation< - internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>>>::value, - int> = 0> - StatusOr(U&& u) // NOLINT - : StatusOr(absl::in_place, std::forward<U>(u)) { - } - - template < - typename U = T, - absl::enable_if_t< - absl::conjunction< - internal_statusor::IsDirectInitializationValid<T, U&&>, - absl::disjunction< - std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, - T>, - absl::conjunction< - absl::negation<std::is_constructible<absl::Status, U&&>>, - absl::negation< - internal_statusor::HasConversionOperatorToStatusOr< - T, U&&>>>>, - std::is_constructible<T, U&&>, - absl::negation<std::is_convertible<U&&, T>>>::value, - int> = 0> - explicit StatusOr(U&& u) // NOLINT - : StatusOr(absl::in_place, std::forward<U>(u)) { - } - - // StatusOr<T>::ok() - // - // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This - // member function is analagous to `absl::Status::ok()` and should be used - // similarly to check the status of return values. - // - // Example: - // - // StatusOr<Foo> result = DoBigCalculationThatCouldFail(); - // if (result.ok()) { - // // Handle result - // else { - // // Handle error - // } - ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); } - - // StatusOr<T>::status() - // - // Returns a reference to the current `absl::Status` contained within the - // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this - // function returns `absl::OkStatus()`. - const Status& status() const &; - Status status() &&; - - // StatusOr<T>::value() - // - // Returns a reference to the held value if `this->ok()`. Otherwise, throws - // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to - // terminate the process if exceptions are disabled. - // - // If you have already checked the status using `this->ok()`, you probably - // want to use `operator*()` or `operator->()` to access the value instead of - // `value`. - // - // Note: for value types that are cheap to copy, prefer simple code: - // - // T value = statusor.value(); - // - // Otherwise, if the value type is expensive to copy, but can be left - // in the StatusOr, simply assign to a reference: - // - // T& value = statusor.value(); // or `const T&` - // - // Otherwise, if the value type supports an efficient move, it can be - // used as follows: - // - // T value = std::move(statusor).value(); - // - // The `std::move` on statusor instead of on the whole expression enables - // warnings about possible uses of the statusor object after the move. - const T& value() const&; - T& value() &; - const T&& value() const&&; - T&& value() &&; - - // StatusOr<T>:: operator*() - // - // Returns a reference to the current value. - // - // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined. - // - // Use `this->ok()` to verify that there is a current value within the - // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a - // similar API that guarantees crashing or throwing an exception if there is - // no current value. - const T& operator*() const&; - T& operator*() &; - const T&& operator*() const&&; - T&& operator*() &&; - - // StatusOr<T>::operator->() - // - // Returns a pointer to the current value. - // - // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined. - // - // Use `this->ok()` to verify that there is a current value. - const T* operator->() const; - T* operator->(); - - // StatusOr<T>::value_or() - // - // Returns the current value if `this->ok() == true`. Otherwise constructs a - // value using the provided `default_value`. - // - // Unlike `value`, this function returns by value, copying the current value - // if necessary. If the value type supports an efficient move, it can be used - // as follows: - // - // T value = std::move(statusor).value_or(def); - // - // Unlike with `value`, calling `std::move()` on the result of `value_or` will - // still trigger a copy. - template <typename U> - T value_or(U&& default_value) const&; - template <typename U> - T value_or(U&& default_value) &&; - - // StatusOr<T>::IgnoreError() - // - // Ignores any errors. This method does nothing except potentially suppress - // complaints from any tools that are checking that errors are not dropped on - // the floor. - void IgnoreError() const; - - // StatusOr<T>::emplace() - // - // Reconstructs the inner value T in-place using the provided args, using the - // T(args...) constructor. Returns reference to the reconstructed `T`. - template <typename... Args> - T& emplace(Args&&... args) { - if (ok()) { - this->Clear(); - this->MakeValue(std::forward<Args>(args)...); - } else { - this->MakeValue(std::forward<Args>(args)...); - this->status_ = absl::OkStatus(); - } - return this->data_; - } - - template < - typename U, typename... Args, - absl::enable_if_t< - std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, - int> = 0> - T& emplace(std::initializer_list<U> ilist, Args&&... args) { - if (ok()) { - this->Clear(); - this->MakeValue(ilist, std::forward<Args>(args)...); - } else { - this->MakeValue(ilist, std::forward<Args>(args)...); - this->status_ = absl::OkStatus(); - } - return this->data_; - } - - private: - using internal_statusor::StatusOrData<T>::Assign; - template <typename U> - void Assign(const absl::StatusOr<U>& other); - template <typename U> - void Assign(absl::StatusOr<U>&& other); -}; - -// operator==() -// -// This operator checks the equality of two `absl::StatusOr<T>` objects. -template <typename T> -bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) { - if (lhs.ok() && rhs.ok()) return *lhs == *rhs; - return lhs.status() == rhs.status(); -} - -// operator!=() -// -// This operator checks the inequality of two `absl::StatusOr<T>` objects. -template <typename T> -bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) { - return !(lhs == rhs); -} - -//------------------------------------------------------------------------------ -// Implementation details for StatusOr<T> -//------------------------------------------------------------------------------ - -// TODO(sbenza): avoid the string here completely. -template <typename T> -StatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, "")) {} - -template <typename T> -template <typename U> -inline void StatusOr<T>::Assign(const StatusOr<U>& other) { - if (other.ok()) { - this->Assign(*other); - } else { - this->AssignStatus(other.status()); - } -} - -template <typename T> -template <typename U> -inline void StatusOr<T>::Assign(StatusOr<U>&& other) { - if (other.ok()) { - this->Assign(*std::move(other)); - } else { - this->AssignStatus(std::move(other).status()); - } -} -template <typename T> -template <typename... Args> -StatusOr<T>::StatusOr(absl::in_place_t, Args&&... args) - : Base(absl::in_place, std::forward<Args>(args)...) {} - -template <typename T> -template <typename U, typename... Args> -StatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist, - Args&&... args) - : Base(absl::in_place, ilist, std::forward<Args>(args)...) {} - -template <typename T> -const Status& StatusOr<T>::status() const & { return this->status_; } -template <typename T> -Status StatusOr<T>::status() && { - return ok() ? OkStatus() : std::move(this->status_); -} - -template <typename T> -const T& StatusOr<T>::value() const& { - if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_); - return this->data_; -} - -template <typename T> -T& StatusOr<T>::value() & { - if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_); - return this->data_; -} - -template <typename T> -const T&& StatusOr<T>::value() const&& { - if (!this->ok()) { - internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_)); - } - return std::move(this->data_); -} - -template <typename T> -T&& StatusOr<T>::value() && { - if (!this->ok()) { - internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_)); - } - return std::move(this->data_); -} - -template <typename T> -const T& StatusOr<T>::operator*() const& { - this->EnsureOk(); - return this->data_; -} - -template <typename T> -T& StatusOr<T>::operator*() & { - this->EnsureOk(); - return this->data_; -} - -template <typename T> -const T&& StatusOr<T>::operator*() const&& { - this->EnsureOk(); - return std::move(this->data_); -} - -template <typename T> -T&& StatusOr<T>::operator*() && { - this->EnsureOk(); - return std::move(this->data_); -} - -template <typename T> -const T* StatusOr<T>::operator->() const { - this->EnsureOk(); - return &this->data_; -} - -template <typename T> -T* StatusOr<T>::operator->() { - this->EnsureOk(); - return &this->data_; -} - -template <typename T> -template <typename U> -T StatusOr<T>::value_or(U&& default_value) const& { - if (ok()) { - return this->data_; - } - return std::forward<U>(default_value); -} - -template <typename T> -template <typename U> -T StatusOr<T>::value_or(U&& default_value) && { - if (ok()) { - return std::move(this->data_); - } - return std::forward<U>(default_value); -} - -template <typename T> -void StatusOr<T>::IgnoreError() const { - // no-op -} - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_STATUSOR_H_ diff --git a/third_party/abseil_cpp/absl/status/statusor_internals.h b/third_party/abseil_cpp/absl/status/statusor_internals.h deleted file mode 100644 index 5366c2840c37..000000000000 --- a/third_party/abseil_cpp/absl/status/statusor_internals.h +++ /dev/null @@ -1,250 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -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 - - http://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. -==============================================================================*/ - -#ifndef ABSL_STATUS_STATUSOR_INTERNALS_H_ -#define ABSL_STATUS_STATUSOR_INTERNALS_H_ - -#include "absl/status/status.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN - -namespace internal_statusor { - -class Helper { - public: - // Move type-agnostic error handling to the .cc. - static void HandleInvalidStatusCtorArg(Status*); - ABSL_ATTRIBUTE_NORETURN static void Crash(const Status& status); -}; - -// Construct an instance of T in `p` through placement new, passing Args... to -// the constructor. -// This abstraction is here mostly for the gcc performance fix. -template <typename T, typename... Args> -void PlacementNew(void* p, Args&&... args) { -#if defined(__GNUC__) && !defined(__clang__) - // Teach gcc that 'p' cannot be null, fixing code size issues. - if (p == nullptr) __builtin_unreachable(); -#endif - new (p) T(std::forward<Args>(args)...); -} - -// Helper base class to hold the data and all operations. -// We move all this to a base class to allow mixing with the appropriate -// TraitsBase specialization. -template <typename T> -class StatusOrData { - template <typename U> - friend class StatusOrData; - - public: - StatusOrData() = delete; - - StatusOrData(const StatusOrData& other) { - if (other.ok()) { - MakeValue(other.data_); - MakeStatus(); - } else { - MakeStatus(other.status_); - } - } - - StatusOrData(StatusOrData&& other) noexcept { - if (other.ok()) { - MakeValue(std::move(other.data_)); - MakeStatus(); - } else { - MakeStatus(other.status_); - } - } - - template <typename U> - StatusOrData(const StatusOrData<U>& other) { - if (other.ok()) { - MakeValue(other.data_); - MakeStatus(); - } else { - MakeStatus(other.status_); - } - } - - template <typename U> - StatusOrData(StatusOrData<U>&& other) { - if (other.ok()) { - MakeValue(std::move(other.data_)); - MakeStatus(); - } else { - MakeStatus(other.status_); - } - } - - explicit StatusOrData(const T& value) : data_(value) { MakeStatus(); } - explicit StatusOrData(T&& value) : data_(std::move(value)) { MakeStatus(); } - - explicit StatusOrData(const Status& status) : status_(status) { - EnsureNotOk(); - } - explicit StatusOrData(Status&& status) : status_(std::move(status)) { - EnsureNotOk(); - } - - StatusOrData& operator=(const StatusOrData& other) { - if (this == &other) return *this; - if (other.ok()) - Assign(other.data_); - else - Assign(other.status_); - return *this; - } - - StatusOrData& operator=(StatusOrData&& other) { - if (this == &other) return *this; - if (other.ok()) - Assign(std::move(other.data_)); - else - Assign(std::move(other.status_)); - return *this; - } - - ~StatusOrData() { - if (ok()) { - status_.~Status(); - data_.~T(); - } else { - status_.~Status(); - } - } - - void Assign(const T& value) { - if (ok()) { - data_.~T(); - MakeValue(value); - } else { - MakeValue(value); - status_ = OkStatus(); - } - } - - void Assign(T&& value) { - if (ok()) { - data_.~T(); - MakeValue(std::move(value)); - } else { - MakeValue(std::move(value)); - status_ = OkStatus(); - } - } - - void Assign(const Status& status) { - Clear(); - status_ = status; - EnsureNotOk(); - } - - void Assign(Status&& status) { - Clear(); - // Note that we copy instead of moving the status here so that - // status.~StatusOrData() can call ok() without invoking UB. - status_ = status; - EnsureNotOk(); - } - - bool ok() const { return status_.ok(); } - - protected: - // status_ will always be active after the constructor. - // We make it a union to be able to initialize exactly how we need without - // waste. - // Eg. in the copy constructor we use the default constructor of Status in - // the ok() path to avoid an extra Ref call. - union { - Status status_; - }; - - // data_ is active iff status_.ok()==true - struct Dummy {}; - union { - // When T is const, we need some non-const object we can cast to void* for - // the placement new. dummy_ is that object. - Dummy dummy_; - T data_; - }; - - void Clear() { - if (ok()) data_.~T(); - } - - void EnsureOk() const { - if (!ok()) Helper::Crash(status_); - } - - void EnsureNotOk() { - if (ok()) Helper::HandleInvalidStatusCtorArg(&status_); - } - - // Construct the value (ie. data_) through placement new with the passed - // argument. - template <typename Arg> - void MakeValue(Arg&& arg) { - internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)); - } - - // Construct the status (ie. status_) through placement new with the passed - // argument. - template <typename... Args> - void MakeStatus(Args&&... args) { - internal_statusor::PlacementNew<Status>(&status_, - std::forward<Args>(args)...); - } -}; - -// Helper base class to allow implicitly deleted constructors and assignment -// operations in StatusOr. -// TraitsBase will explicitly delete what it can't support and StatusOr will -// inherit that behavior implicitly. -template <bool Copy, bool Move> -struct TraitsBase { - TraitsBase() = default; - TraitsBase(const TraitsBase&) = default; - TraitsBase(TraitsBase&&) = default; - TraitsBase& operator=(const TraitsBase&) = default; - TraitsBase& operator=(TraitsBase&&) = default; -}; - -template <> -struct TraitsBase<false, true> { - TraitsBase() = default; - TraitsBase(const TraitsBase&) = delete; - TraitsBase(TraitsBase&&) = default; - TraitsBase& operator=(const TraitsBase&) = delete; - TraitsBase& operator=(TraitsBase&&) = default; -}; - -template <> -struct TraitsBase<false, false> { - TraitsBase() = default; - TraitsBase(const TraitsBase&) = delete; - TraitsBase(TraitsBase&&) = delete; - TraitsBase& operator=(const TraitsBase&) = delete; - TraitsBase& operator=(TraitsBase&&) = delete; -}; - -} // namespace internal_statusor - -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STATUS_STATUSOR_INTERNALS_H_ 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 |