diff options
author | ambrosin <ambrosin@google.com> | 2023-03-08 06:17:50 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-03-08 06:19:10 -0800 |
commit | a1b31d0a4aad80263ea1fcea13a296893986be72 (patch) | |
tree | f45c2b1b56c85056bbe37eb2c2fb01687ada322f /cc/util | |
parent | ef7dc3bbbef14814639ebe152e2f65a1d545e6c5 (diff) | |
download | tink-a1b31d0a4aad80263ea1fcea13a296893986be72.tar.gz |
Remove the custom crypto::tink::util::Staus{|Or} implementation
Also remove Kokoro test scripts that used `--//config:tink_use_absl_statusor=True`.
PiperOrigin-RevId: 515018353
Diffstat (limited to 'cc/util')
-rw-r--r-- | cc/util/BUILD.bazel | 43 | ||||
-rw-r--r-- | cc/util/CMakeLists.txt | 31 | ||||
-rw-r--r-- | cc/util/enums.cc | 1 | ||||
-rw-r--r-- | cc/util/errors.h | 11 | ||||
-rw-r--r-- | cc/util/errors_test.cc | 38 | ||||
-rw-r--r-- | cc/util/status.cc | 162 | ||||
-rw-r--r-- | cc/util/status.h | 197 | ||||
-rw-r--r-- | cc/util/status_test.cc | 60 | ||||
-rw-r--r-- | cc/util/statusor.h | 236 | ||||
-rw-r--r-- | cc/util/statusor_test.cc | 242 |
10 files changed, 9 insertions, 1012 deletions
diff --git a/cc/util/BUILD.bazel b/cc/util/BUILD.bazel index 0f1956d6f..55845211c 100644 --- a/cc/util/BUILD.bazel +++ b/cc/util/BUILD.bazel @@ -76,6 +76,7 @@ cc_library( include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ + ":status", ":statusor", "//proto:common_cc_proto", "//proto:ecdsa_cc_proto", @@ -88,63 +89,23 @@ cc_library( cc_library( name = "status", - srcs = ["status.cc"], hdrs = ["status.h"], - defines = select({ - "//config:absl_status_enabled": ["TINK_USE_ABSL_STATUS"], - "//conditions:default": [], - }), include_prefix = "tink/util", visibility = ["//visibility:public"], - deps = [ - "@com_google_absl//absl/base:core_headers", - "@com_google_absl//absl/status", - "@com_google_absl//absl/strings", - ], -) - -cc_test( - name = "status_test", - srcs = ["status_test.cc"], - deps = [ - ":status", - "@com_google_absl//absl/status", - "@com_google_googletest//:gtest_main", - ], + deps = ["@com_google_absl//absl/status"], ) cc_library( name = "statusor", - srcs = ["statusor.h"], hdrs = ["statusor.h"], - defines = select({ - "//config:absl_statusor_enabled": ["TINK_USE_ABSL_STATUSOR"], - "//conditions:default": [], - }), include_prefix = "tink/util", visibility = ["//visibility:public"], deps = [ ":status", - "@com_google_absl//absl/log", - "@com_google_absl//absl/log:check", "@com_google_absl//absl/status:statusor", ], ) -cc_test( - name = "statusor_test", - srcs = ["statusor_test.cc"], - deps = [ - ":status", - ":statusor", - ":test_matchers", - "@com_google_absl//absl/memory", - "@com_google_absl//absl/status", - "@com_google_absl//absl/status:statusor", - "@com_google_googletest//:gtest_main", - ], -) - cc_library( name = "validation", srcs = ["validation.cc"], diff --git a/cc/util/CMakeLists.txt b/cc/util/CMakeLists.txt index 96a906dfc..bed5f9f1e 100644 --- a/cc/util/CMakeLists.txt +++ b/cc/util/CMakeLists.txt @@ -36,6 +36,7 @@ tink_cc_library( enums.cc enums.h DEPS + tink::util::status tink::util::statusor absl::status absl::strings @@ -48,12 +49,9 @@ tink_cc_library( tink_cc_library( NAME status SRCS - status.cc status.h DEPS - absl::core_headers absl::status - absl::strings PUBLIC ) @@ -61,11 +59,8 @@ tink_cc_library( NAME statusor SRCS statusor.h - statusor.h DEPS tink::util::status - absl::check - absl::log absl::statusor PUBLIC ) @@ -525,27 +520,3 @@ tink_cc_test( tink::proto::kms_aead_cc_proto tink::proto::kms_envelope_cc_proto ) - -tink_cc_test( - NAME status_test - SRCS - status_test.cc - DEPS - tink::util::status - gmock - absl::status -) - -tink_cc_test( - NAME statusor_test - SRCS - statusor_test.cc - DEPS - tink::util::status - tink::util::statusor - tink::util::test_matchers - gmock - absl::memory - absl::status - absl::statusor -) diff --git a/cc/util/enums.cc b/cc/util/enums.cc index 201ca1be2..5100162a4 100644 --- a/cc/util/enums.cc +++ b/cc/util/enums.cc @@ -18,6 +18,7 @@ #include "absl/status/status.h" #include "absl/strings/str_cat.h" +#include "tink/util/status.h" #include "proto/common.pb.h" #include "proto/ecdsa.pb.h" #include "proto/tink.pb.h" diff --git a/cc/util/errors.h b/cc/util/errors.h index cbb0ebeb7..5086ce493 100644 --- a/cc/util/errors.h +++ b/cc/util/errors.h @@ -23,17 +23,6 @@ namespace crypto { namespace tink { -#ifndef TINK_USE_ABSL_STATUS -// Constructs a Status with formatted error message. -template <typename... Args> -ABSL_DEPRECATED("Prefer using absl::StatusCode as a first argument.") -util::Status ToStatusF(util::error::Code code, - const absl::FormatSpec<Args...>& format, - const Args&... args) { - return util::Status(code, absl::StrFormat(format, args...)); -} -#endif - // Constructs a Status with formatted error message using absl::StatusCode. template <typename... Args> util::Status ToStatusF(absl::StatusCode code, diff --git a/cc/util/errors_test.cc b/cc/util/errors_test.cc index 73e74c255..cec75e6db 100644 --- a/cc/util/errors_test.cc +++ b/cc/util/errors_test.cc @@ -24,49 +24,13 @@ namespace crypto { namespace tink { namespace { -#ifndef TINK_USE_ABSL_STATUS -TEST(ErrorsTest, ToStatusFTest) { - const char* const msg1 = "test message 1"; - const char* const msg2 = "test message %s 2 %d"; - crypto::tink::util::Status status; - - status = util::Status(crypto::tink::util::error::OK, msg1); - EXPECT_TRUE(status.ok()); - // if status is OK, error message is ignored - EXPECT_EQ("", status.message()); - EXPECT_EQ(crypto::tink::util::error::OK, status.error_code()); - - const char* expected_msg2 = "test message asdf 2 42"; - status = ToStatusF(crypto::tink::util::error::UNKNOWN, msg2, "asdf", 42); - EXPECT_FALSE(status.ok()); - EXPECT_EQ(expected_msg2, status.message()); - EXPECT_EQ(crypto::tink::util::error::UNKNOWN, status.error_code()); -} - -TEST(ErrorsTest, ToAbslStatus) { - crypto::tink::util::Status tink_status(util::error::INVALID_ARGUMENT, - "error"); - ::absl::Status g3_status(tink_status); - EXPECT_FALSE(g3_status.ok()); - EXPECT_EQ(g3_status.message(), "error"); - - EXPECT_EQ(::absl::Status(crypto::tink::util::OkStatus()), ::absl::OkStatus()); -} -#endif - TEST(ErrorsTest, ToStatusFAbslStatusCodeTest) { const char* const msg = "test message %s 2 %d"; const char* expected_msg = "test message asdf 2 42"; - crypto::tink::util::Status status = - ToStatusF(absl::StatusCode::kUnknown, msg, "asdf", 42); + util::Status status = ToStatusF(absl::StatusCode::kUnknown, msg, "asdf", 42); EXPECT_FALSE(status.ok()); EXPECT_EQ(expected_msg, status.message()); EXPECT_EQ(absl::StatusCode::kUnknown, status.code()); - - #ifndef TINK_USE_ABSL_STATUS - EXPECT_EQ(expected_msg, status.error_message()); - EXPECT_EQ(crypto::tink::util::error::UNKNOWN, status.error_code()); - #endif } } // namespace diff --git a/cc/util/status.cc b/cc/util/status.cc deleted file mode 100644 index 91bd680c8..000000000 --- a/cc/util/status.cc +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2017 Google Inc. -// -// 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "tink/util/status.h" - -#include <sstream> -#include <string> - -#include "absl/status/status.h" -#include "absl/strings/str_cat.h" - -using ::std::ostream; - -namespace crypto { -namespace tink { -namespace util { - -#ifndef TINK_USE_ABSL_STATUS -namespace { - - -const Status& GetCancelled() { - static const Status* status = - new Status(absl::StatusCode::kCancelled, ""); - return *status; -} - -const Status& GetUnknown() { - static const Status* status = - new Status(absl::StatusCode::kUnknown, ""); - return *status; -} - -const Status& GetOk() { - static const Status* status = new Status; - return *status; -} - -} // namespace - -Status::Status(const ::absl::Status& status) - : code_(absl::StatusCode::kOk) { - if (status.ok()) return; - code_ = status.code(); - message_ = std::string(status.message()); -} - -Status::operator ::absl::Status() const { - if (ok()) return ::absl::OkStatus(); - return ::absl::Status(code_, message_); -} - -Status::Status() : code_(absl::StatusCode::kOk), message_("") { -} - -Status::Status(::crypto::tink::util::error::Code error, - const std::string& error_message) - : code_(static_cast<absl::StatusCode>(error)), message_(error_message) { - if (code_ == absl::StatusCode::kOk) { - message_.clear(); - } -} - -Status::Status(absl::StatusCode code, absl::string_view error_message) - : code_(code), - message_(error_message) { - if (code_ == absl::StatusCode::kOk) { - message_.clear(); - } -} - -Status& Status::operator=(const Status& other) { - code_ = other.code_; - message_ = other.message_; - return *this; -} - -const Status& Status::CANCELLED = GetCancelled(); -const Status& Status::UNKNOWN = GetUnknown(); -const Status& Status::OK = GetOk(); - -std::string Status::ToString() const { - if (code_ == absl::StatusCode::kOk) { - return "OK"; - } - - std::ostringstream oss; - oss << code_ << ": " << message_; - return oss.str(); -} - -std::string ErrorCodeString(crypto::tink::util::error::Code error) { - switch (error) { - case crypto::tink::util::error::OK: - return "OK"; - case crypto::tink::util::error::CANCELLED: - return "CANCELLED"; - case crypto::tink::util::error::UNKNOWN: - return "UNKNOWN"; - case crypto::tink::util::error::INVALID_ARGUMENT: - return "INVALID_ARGUMENT"; - case crypto::tink::util::error::DEADLINE_EXCEEDED: - return "DEADLINE_EXCEEDED"; - case crypto::tink::util::error::NOT_FOUND: - return "NOT_FOUND"; - case crypto::tink::util::error::ALREADY_EXISTS: - return "ALREADY_EXISTS"; - case crypto::tink::util::error::PERMISSION_DENIED: - return "PERMISSION_DENIED"; - case crypto::tink::util::error::RESOURCE_EXHAUSTED: - return "RESOURCE_EXHAUSTED"; - case crypto::tink::util::error::FAILED_PRECONDITION: - return "FAILED_PRECONDITION"; - case crypto::tink::util::error::ABORTED: - return "ABORTED"; - case crypto::tink::util::error::OUT_OF_RANGE: - return "OUT_OF_RANGE"; - case crypto::tink::util::error::UNIMPLEMENTED: - return "UNIMPLEMENTED"; - case crypto::tink::util::error::INTERNAL: - return "INTERNAL"; - case crypto::tink::util::error::UNAVAILABLE: - return "UNAVAILABLE"; - case crypto::tink::util::error::DATA_LOSS: - return "DATA_LOSS"; - case crypto::tink::util::error::UNAUTHENTICATED: - return "UNAUTHENTICATED"; - } - // Avoid using a "default" in the switch, so that the compiler can - // give us a warning, but still provide a fallback here. - return absl::StrCat(error); -} - -extern ostream& operator<<(ostream& os, crypto::tink::util::error::Code code) { - os << ErrorCodeString(code); - return os; -} - -extern ostream& operator<<(ostream& os, const Status& other) { - os << other.ToString(); - return os; -} - -#endif // TINK_USE_ABSL_STATUS - - -} // namespace util -} // namespace tink -} // namespace crypto diff --git a/cc/util/status.h b/cc/util/status.h index 6fffc322e..ef5894910 100644 --- a/cc/util/status.h +++ b/cc/util/status.h @@ -20,209 +20,16 @@ #ifndef TINK_UTIL_STATUS_H_ #define TINK_UTIL_STATUS_H_ -#include <ostream> -#include <string> - -#include "absl/base/attributes.h" #include "absl/status/status.h" +#define TINK_USE_ABSL_STATUS + namespace crypto { namespace tink { namespace util { -#ifndef TINK_USE_ABSL_STATUS - -namespace error { - -// These values match the error codes in the codes.proto file of the original. -enum ABSL_DEPRECATED("Prefer using absl::StatusCode instead.") Code { - // Not an error; returned on success - OK = 0, - - // The operation was cancelled (typically by the caller). - CANCELLED = 1, - - // Unknown error. - UNKNOWN = 2, - - // Client specified an invalid argument. Note that this differs - // from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments - // that are problematic regardless of the state of the system - // (e.g., a malformed file name). - INVALID_ARGUMENT = 3, - - // Deadline expired before operation could complete. - DEADLINE_EXCEEDED = 4, - - // Some requested entity (e.g., file or directory) was not found. - NOT_FOUND = 5, - - // Some entity that we attempted to create (e.g., file or directory) - // already exists. - ALREADY_EXISTS = 6, - - // The caller does not have permission to execute the specified - // operation. - PERMISSION_DENIED = 7, - - // Some resource has been exhausted, perhaps a per-user quota, or - // perhaps the entire file system is out of space. - RESOURCE_EXHAUSTED = 8, - - // Operation was rejected because the system is not in a state - // required for the operation's execution. For example, directory - // to be deleted may be non-empty, an rmdir operation is applied to - // a non-directory, etc. - // - // A litmus test that may help a service implementor in deciding - // between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: - // (a) Use UNAVAILABLE if the client can retry just the failing call. - // (b) Use ABORTED if the client should retry at a higher-level - // (e.g., restarting a read-modify-write sequence). - // (c) Use FAILED_PRECONDITION if the client should not retry until - // the system state has been explicitly fixed. E.g., if an "rmdir" - // fails because the directory is non-empty, FAILED_PRECONDITION - // should be returned since the client should not retry unless - // they have first fixed up the directory by deleting files from it. - FAILED_PRECONDITION = 9, - - // The operation was aborted, typically due to a concurrency issue - // like sequencer check failures, transaction aborts, etc. - // - // See litmus test above for deciding between FAILED_PRECONDITION, - // ABORTED, and UNAVAILABLE. - ABORTED = 10, - - // Operation was attempted past the valid range. E.g., seeking or - // reading past end of file. - // - // Unlike INVALID_ARGUMENT, this error indicates a problem that may - // be fixed if the system state changes. For example, a 32-bit file - // system will generate INVALID_ARGUMENT if asked to read at an - // offset that is not in the range [0,2^32-1], but it will generate - // OUT_OF_RANGE if asked to read from an offset past the current - // file size. - OUT_OF_RANGE = 11, - - // Operation is not implemented or not supported/enabled in this service. - UNIMPLEMENTED = 12, - - // Internal errors. Means some invariants expected by underlying - // system has been broken. If you see one of these errors, - // something is very broken. - INTERNAL = 13, - - // The service is currently unavailable. This is a most likely a - // transient condition and may be corrected by retrying with - // a backoff. - // - // See litmus test above for deciding between FAILED_PRECONDITION, - // ABORTED, and UNAVAILABLE. - UNAVAILABLE = 14, - - // Unrecoverable data loss or corruption. - DATA_LOSS = 15, - - // Invalid authentication credentials. - UNAUTHENTICATED = 16, -}; - -} // namespace error - -// TODO(tholenst) Remove this compile time flag in Tink 1.5. This should not be -// used, except as a temporary measure. -#ifndef CPP_TINK_TEMPORARY_STATUS_MUST_NOT_USE_RESULT -class ABSL_MUST_USE_RESULT Status; -#endif - -// A Status is a combination of an error code and a string message (for non-OK -// error codes). -class Status { - public: - // Creates an OK status - Status(); - - // Make a Status from the specified error and message. - ABSL_DEPRECATED("Use the constructor with an absl::StatusCode.") - Status(::crypto::tink::util::error::Code error, - const std::string& error_message); - // Abseil-compatible constructor from an error and a message - Status(absl::StatusCode code, absl::string_view error_message); - - Status(const Status& other) = default; - - Status& operator=(const Status& other); - - // Some pre-defined Status objects - ABSL_DEPRECATED("Use OkStatus() instead.") - static const Status& OK; // Identical to 0-arg constructor - ABSL_DEPRECATED("Use Status(absl::StatusCode::kCancelled, "") instead.") - static const Status& CANCELLED; - ABSL_DEPRECATED("Use Status(absl::StatusCode::kUnknown, "") instead.") - static const Status& UNKNOWN; - - // Accessors - bool ok() const { - return code_ == absl::StatusCode::kOk; - } - ABSL_DEPRECATED("Use its absl-compatible version code() instead.") - int error_code() const { - return static_cast<int>(code_); - } - ABSL_DEPRECATED("Use its absl-compatible version code() instead.") - ::crypto::tink::util::error::Code CanonicalCode() const { - return static_cast<::crypto::tink::util::error::Code>(code_); - } - ABSL_DEPRECATED("Use its absl-compatible version message() instead.") - const std::string& error_message() const { return message_; } - - // Abseil-compatible accessors - absl::StatusCode code() const { - return static_cast<absl::StatusCode>(code_); - } - absl::string_view message() const { - return message_; - } - - bool operator==(const Status& other) const; - bool operator!=(const Status& other) const; - - // NoOp - void IgnoreError() const { - } - - std::string ToString() const; - - Status(const ::absl::Status& status); - operator ::absl::Status() const; - - private: - absl::StatusCode code_; - std::string message_; -}; - -inline bool Status::operator==(const Status& other) const { - return (this->code_ == other.code_) && (this->message_ == other.message_); -} - -inline bool Status::operator!=(const Status& other) const { - return !(*this == other); -} - -ABSL_DEPRECATED("Use absl::StatusCodeToString with a StatusCode instead.") -extern std::string ErrorCodeString(crypto::tink::util::error::Code error); - -ABSL_DEPRECATED("Use absl::StatusCode instead.") -extern ::std::ostream& operator<<(::std::ostream& os, - ::crypto::tink::util::error::Code code); -extern ::std::ostream& operator<<(::std::ostream& os, const Status& other); - -#else - using Status = absl::Status; -#endif // TINK_USE_ABSL_STATUS - // Returns an OK status, equivalent to a default constructed instance. inline Status OkStatus() { return Status(); } diff --git a/cc/util/status_test.cc b/cc/util/status_test.cc deleted file mode 100644 index 4be75422c..000000000 --- a/cc/util/status_test.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "tink/util/status.h" - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/status/status.h" - -namespace crypto { -namespace tink { -namespace util { -namespace { - -#ifndef TINK_USE_ABSL_STATUS -TEST(StatusTest, CreateNonOkStatusWithAbslStatusCode) { - Status util_status = Status(error::Code::CANCELLED, "message"); - Status absl_status = Status(absl::StatusCode::kCancelled, "message"); - ASSERT_EQ(util_status, absl_status); -} - -TEST(StatusTest, CreateOkStatusWithAbslStatusCode) { - Status util_status = Status(error::Code::OK, "message"); - Status absl_status = Status(absl::StatusCode::kOk, "message"); - ASSERT_EQ(util_status, absl_status); - ASSERT_EQ(absl_status.message(), ""); -} - -TEST(StatusTest, ConvertNonOkStatus) { - Status util_status = Status(error::Code::RESOURCE_EXHAUSTED, "message"); - absl::Status absl_status = util_status; - ASSERT_EQ(util_status.code(), absl_status.code()); - ASSERT_EQ(util_status.message(), absl_status.message()); -} - -TEST(StatusTest, ConvertOkStatus) { - Status util_status = OkStatus(); - absl::Status absl_status = util_status; - ASSERT_TRUE(absl_status.ok()); - ASSERT_EQ(absl_status.message(), ""); -} -#endif - -} // namespace -} // namespace util -} // namespace tink -} // namespace crypto diff --git a/cc/util/statusor.h b/cc/util/statusor.h index 6872cd0fb..859cf11c5 100644 --- a/cc/util/statusor.h +++ b/cc/util/statusor.h @@ -17,250 +17,18 @@ #ifndef TINK_UTIL_STATUSOR_H_ #define TINK_UTIL_STATUSOR_H_ -#include <cstdlib> -#include <iostream> -#include <utility> - -#include "absl/log/check.h" -#include "absl/log/log.h" #include "absl/status/statusor.h" #include "tink/util/status.h" +#define TINK_USE_ABSL_STATUSOR + namespace crypto { namespace tink { namespace util { -#ifndef TINK_USE_ABSL_STATUSOR - -#ifndef CPP_TINK_TEMPORARY_STATUS_MUST_NOT_USE_RESULT -template <typename T> -class ABSL_MUST_USE_RESULT StatusOr; -#endif - -// TODO(b/122292096): Migrate this to absl::StatusOr -// A StatusOr holds a Status (in the case of an error), or a value T. -template <typename T> -class StatusOr { - 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`. - using value_type = T; - - using type = T; - // Has status UNKNOWN. - inline StatusOr(); - - // Builds from a non-OK status. Crashes if an OK status is specified. - inline StatusOr(const ::crypto::tink::util::Status& status); // NOLINT - - // Builds from the specified value. - inline StatusOr(const T& value); // NOLINT - inline StatusOr(T&& value); // NOLINT - - // Copy constructor. - inline StatusOr(const StatusOr& other); - - // Move constructor. - inline StatusOr(StatusOr&& other); - - // Conversion copy constructor, T must be copy constructible from U. - template <typename U> - inline StatusOr(const StatusOr<U>& other); - - // Assignment operator. - inline const StatusOr& operator=(const StatusOr& other); - - // Conversion assignment operator, T must be assignable from U - template <typename U> - inline const StatusOr& operator=(const StatusOr<U>& other); - - // Accessors. - inline const ::crypto::tink::util::Status& status() const { - return status_; - } - - // Shorthand for status().ok(). - inline bool ok() const { - return status_.ok(); - } - - // Returns value or crashes if ok() is false. - inline const T& ValueOrDie() const& { - EnsureOk(); - return *value_; - } - inline T& ValueOrDie() & { - EnsureOk(); - return *value_; - } - inline const T&& ValueOrDie() const&& { - EnsureOk(); - return *std::move(value_); - } - inline T&& ValueOrDie() && { - EnsureOk(); - return *std::move(value_); - } - - // Returns value if ok(), otherwise crashes if exceptions are disabled OR - // throws if exceptions are enabled. - inline const T& value() const& { - if (!ok()) AbortWithMessageFrom(status_); - return *value_; - } - inline T& value() & { - if (!ok()) AbortWithMessageFrom(status_); - return *value_; - } - inline const T&& value() const&& { - if (!ok()) AbortWithMessageFrom(std::move(status_)); - return *std::move(value_); - } - inline T&& value() && { - if (!ok()) AbortWithMessageFrom(std::move(status_)); - return *std::move(value_); - } - - // Implicitly convertible to absl::StatusOr. Implicit conversions explicitly - // allowed by style arbiter waiver in cl/351594378. - operator ::absl::StatusOr<T>() const&; // NOLINT - operator ::absl::StatusOr<T>() &&; // NOLINT - - // Returns value or crashes if ok() is false. - inline const T& operator*() const& { - EnsureOk(); - return *value_; - } - - inline T& operator*() & { - EnsureOk(); - return *value_; - } - - inline T&& operator*() && { - EnsureOk(); - return *std::move(value_); - } - - inline const T&& operator*() const&& { - EnsureOk(); - return *std::move(value_); - } - - // Returns reference to value or crashes if ok() is false. - T* operator->() { - EnsureOk(); - return &(value_.value()); - } - - const T* operator->() const { - EnsureOk(); - return &(value_.value()); - } - - template <typename U> - friend class StatusOr; - - private: - void EnsureOk() const { - if (ABSL_PREDICT_FALSE(!ok())) { - LOG(FATAL) << "Attempting to fetch value of non-OK StatusOr\n" - << status(); - } - } - - void AbortWithMessageFrom(crypto::tink::util::Status status) const { - LOG(FATAL) << "Attempting to fetch value instead of handling error\n" - << status.ToString(); - } - - Status status_; - absl::optional<T> value_; -}; - -// Implementation. - -template <typename T> -inline StatusOr<T>::StatusOr() - : status_(absl::StatusCode::kUnknown, "") { -} - -template <typename T> -inline StatusOr<T>::StatusOr(const ::crypto::tink::util::Status& status) - : status_(status) { - CHECK(!status.ok()) << "::crypto::tink::util::OkStatus() " - << "is not a valid argument to StatusOr\n"; -} - -template <typename T> -inline StatusOr<T>::StatusOr(const T& value) : value_(value) { -} - -template <typename T> -inline StatusOr<T>::StatusOr(T&& value) : value_(std::move(value)) { -} - -template <typename T> -inline StatusOr<T>::StatusOr(const StatusOr& other) - : status_(other.status_), value_(other.value_) { -} - -template <typename T> -inline StatusOr<T>::StatusOr(StatusOr&& other) - : status_(other.status_), value_(std::move(other.value_)) { -} - -template <typename T> -template <typename U> -inline StatusOr<T>::StatusOr(const StatusOr<U>& other) - : status_(other.status_), value_(other.value_) { -} - -template <typename T> -inline const StatusOr<T>& StatusOr<T>::operator=(const StatusOr& other) { - status_ = other.status_; - if (status_.ok()) { - value_ = *other.value_; - } else { - value_ = absl::nullopt; - } - return *this; -} - -template <typename T> -template <typename U> -inline const StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) { - status_ = other.status_; - if (status_.ok()) { - value_ = *other.value_; - } else { - value_ = absl::nullopt; - } - return *this; -} - -template <typename T> -StatusOr<T>::operator ::absl::StatusOr<T>() const& { - if (!ok()) return ::absl::Status(status_); - return *value_; -} - -template <typename T> -StatusOr<T>::operator ::absl::StatusOr<T>() && { - if (!ok()) return ::absl::Status(std::move(status_)); - return std::move(*value_); -} - -#else - template <typename T> using StatusOr = absl::StatusOr<T>; -#endif // TINK_USE_ABSL_STATUSOR - } // namespace util } // namespace tink } // namespace crypto diff --git a/cc/util/statusor_test.cc b/cc/util/statusor_test.cc deleted file mode 100644 index 7aa85837c..000000000 --- a/cc/util/statusor_test.cc +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "tink/util/statusor.h" - -#include <memory> -#include <string> -#include <utility> - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "absl/memory/memory.h" -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "tink/util/status.h" -#include "tink/util/test_matchers.h" - -namespace crypto { -namespace tink { -namespace util { -namespace { - -using ::crypto::tink::test::IsOk; -using ::testing::Eq; -using ::testing::Not; -using ::testing::Pointee; - -TEST(StatusOrTest, ConvertOkToAbsl) { - StatusOr<int> instance = 1; - - absl::StatusOr<int> converted = instance; - ASSERT_TRUE(converted.ok()); - EXPECT_EQ(*converted, 1); -} - -TEST(StatusOrTest, ConvertErrorToAbsl) { - #ifndef TINK_USE_ABSL_STATUS - StatusOr<int> instance{ - Status(error::Code::INVALID_ARGUMENT, "Error message")}; - #else - StatusOr<int> instance{ - Status(absl::StatusCode::kInvalidArgument, "Error message")}; - #endif - - absl::StatusOr<int> converted = instance; - ASSERT_FALSE(converted.ok()); - EXPECT_EQ(converted.status().code(), absl::StatusCode::kInvalidArgument); - EXPECT_EQ(converted.status().message(), "Error message"); -} - -TEST(StatusOrTest, ConvertUncopyableToAbsl) { - StatusOr<std::unique_ptr<int>> instance = absl::make_unique<int>(1); - - absl::StatusOr<std::unique_ptr<int>> converted = std::move(instance); - ASSERT_TRUE(converted.ok()); - EXPECT_THAT(*converted, Pointee(Eq(1))); -} - -class NoDefaultConstructor { - public: - explicit NoDefaultConstructor(int i) {} - - NoDefaultConstructor() = delete; - NoDefaultConstructor(const NoDefaultConstructor&) = default; - NoDefaultConstructor& operator=(const NoDefaultConstructor&) = - default; - NoDefaultConstructor(NoDefaultConstructor&&) = default; - NoDefaultConstructor& operator=(NoDefaultConstructor&&) = default; -}; - -// Tests that we can construct a StatusOr<T> even if there is no default -// constructor for T. -TEST(StatusOrTest, WithNoDefaultConstructor) { - StatusOr<NoDefaultConstructor> value = NoDefaultConstructor(13); - StatusOr<NoDefaultConstructor> error = - Status(absl::StatusCode::kInvalidArgument, "Error message"); -} - -// This tests that when we assign to something which is previously an error, -// we create a new optional inside the StatusOr, and do not try to assign to -// the value of the optional instead. -TEST(StatusOrTest, AssignToErrorStatus) { - StatusOr<std::string> error_initially = - Status(absl::StatusCode::kInvalidArgument, "Error message"); - ASSERT_THAT(error_initially, Not(IsOk())); - StatusOr<std::string> ok_initially = std::string("Hi"); - error_initially = ok_initially; - ASSERT_THAT(error_initially, IsOk()); - ASSERT_THAT(error_initially.value(), Eq("Hi")); - -#ifndef TINK_USE_ABSL_STATUSOR - ASSERT_THAT(error_initially.ValueOrDie(), Eq("Hi")); -#endif -} - -// This tests that when we assign to something which is previously an error and -// at the same time use the implicit conversion operator, we create a new -// optional inside the StatusOr, and do not try to assign to the value of the -// optional instead. -TEST(StatusOrTest, AssignToErrorStatusImplicitConvertible) { - StatusOr<std::string> error_initially = - Status(absl::StatusCode::kInvalidArgument, "Error message"); - ASSERT_THAT(error_initially, Not(IsOk())); - StatusOr<char const*> ok_initially = "Hi"; - error_initially = ok_initially; - ASSERT_THAT(error_initially, IsOk()); - ASSERT_THAT(error_initially.value(), Eq("Hi")); - -#ifndef TINK_USE_ABSL_STATUSOR - ASSERT_THAT(error_initially.ValueOrDie(), Eq("Hi")); -#endif -} - -#ifndef TINK_USE_ABSL_STATUSOR -TEST(StatusOrTest, MoveOutMoveOnlyValueOrDie) { - StatusOr<std::unique_ptr<int>> status_or_unique_ptr_int = - absl::make_unique<int>(10); - std::unique_ptr<int> ten = std::move(status_or_unique_ptr_int.ValueOrDie()); - ASSERT_THAT(*ten, Eq(10)); -} -#endif - -TEST(StatusOrTest, MoveOutMoveOnlyValue) { - StatusOr<std::unique_ptr<int>> status_or_unique_ptr_int = - absl::make_unique<int>(10); - std::unique_ptr<int> ten = std::move(status_or_unique_ptr_int.value()); - ASSERT_THAT(*ten, Eq(10)); -} - -TEST(STatusOrTest, CallValueOnConst) { - const StatusOr<int> const_status_or_ten = 10; - ASSERT_THAT(const_status_or_ten.value(), Eq(10)); -} - -TEST(StatusOrTest, CallValueOnConstTemp) { - const StatusOr<int> const_status_or_ten = 10; - ASSERT_THAT(std::move(const_status_or_ten).value(), Eq(10)); -} - -TEST(StatusOrTest, TestValueConst) { - const int kI = 4; - const absl::StatusOr<int> thing(kI); - EXPECT_EQ(kI, *thing); -} - -TEST(StatusOrTest, TestPointerValue) { - const int kI = 0; - absl::StatusOr<const int*> thing(&kI); - EXPECT_EQ(&kI, *thing); -} - -TEST(StatusOrTest, TestPointerValueConst) { - const int kI = 0; - const absl::StatusOr<const int*> thing(&kI); - EXPECT_EQ(&kI, *thing); -} - -TEST(StatusOrTest, 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(StatusOrTest, OperatorStar) { - const util::StatusOr<std::string> const_lvalue("hello"); - EXPECT_EQ("hello", *const_lvalue); - - util::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 util::StatusOr<std::string> const_rvalue("hello"); - EXPECT_EQ("hello", *std::move(const_rvalue)); // NOLINT - - util::StatusOr<std::string> rvalue("hello"); - EXPECT_EQ("hello", *std::move(rvalue)); -} - -TEST(StatusOrTest, OperatorArrowQualifiers) { - static_assert( - std::is_same< - const int*, - decltype(std::declval<const util::StatusOr<int>&>().operator->())>(), - "Unexpected qualifiers"); - static_assert( - std::is_same< - int*, decltype(std::declval<util::StatusOr<int>&>().operator->())>(), - "Unexpected qualifiers"); - static_assert( - std::is_same< - const int*, - decltype(std::declval<const util::StatusOr<int>&&>().operator->())>(), - "Unexpected qualifiers"); - static_assert( - std::is_same< - int*, decltype(std::declval<util::StatusOr<int>&&>().operator->())>(), - "Unexpected qualifiers"); -} - -TEST(StatusOrTest, OperatorArrow) { - const util::StatusOr<std::string> const_lvalue("hello"); - EXPECT_EQ(std::string("hello"), const_lvalue->c_str()); - - util::StatusOr<std::string> lvalue("hello"); - EXPECT_EQ(std::string("hello"), lvalue->c_str()); -} - -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>(), ""); -} - -} // namespace - -} // namespace util -} // namespace tink -} // namespace crypto |