summaryrefslogtreecommitdiff
path: root/absl/status/status_test.cc
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-02-20 12:34:37 -0800
committerGravatar Xiaoyi Zhang <zhangxy@google.com>2020-02-20 15:37:22 -0500
commit914ff44510505f209d8e85a01e31f4c5fb1b6a5b (patch)
tree1214a2d25654bd73cdecf18f77798ab044beb369 /absl/status/status_test.cc
parent3c814105108680997d0821077694f663693b5382 (diff)
Export of internal Abseil changes
-- bffb14058bb46137d42c7a113a36b6b582997cda by Xiaoyi Zhang <zhangxy@google.com>: Add ABSL_MUST_USE_RESULT to Status. PiperOrigin-RevId: 296272498 -- b426fdd3b3f687d7a8aeb644925923bbab503778 by CJ Johnson <johnsoncj@google.com>: Optimizes absl::InlinedVector::clear() by not deallocating the data, if allocated. This allows allocations to be reused. This matches the behavior of std::vector::clear() PiperOrigin-RevId: 296197235 -- 8cb9fbfe20e749816065c1a042e84f72dac9bfc0 by CJ Johnson <johnsoncj@google.com>: Optimizes absl::InlinedVector::clear() by not deallocating the data, if allocated. This allows allocations to be reused. This matches the behavior of std::vector::clear() PiperOrigin-RevId: 296058092 -- 2558d3369a482879919155b6f46317ccafe0ca13 by Matthew Brown <matthewbr@google.com>: Internal cleanup PiperOrigin-RevId: 296025806 -- cf7ee57228534021c15ed7421df92acf6c27c9c7 by Gennadiy Rozental <rogeeff@google.com>: Make FlagOps enum class. We also add comments to all the functions used to invoke flag ops. PiperOrigin-RevId: 295975809 -- 74bbdbd12fbc54e9c4ebcb3005e727becf0e509d by Xiaoyi Zhang <zhangxy@google.com>: Release `absl::Status`. PiperOrigin-RevId: 295777662 -- 3dbc622b4e2227863525da2f7de7ecbeb3ede21f by Xiaoyi Zhang <zhangxy@google.com>: Internal change. PiperOrigin-RevId: 295733658 -- 48d74aa0ab01d611da6012b377f038d8b26c712e by Abseil Team <absl-team@google.com>: Fix typo in container/CMakeLists.txt for container_common PiperOrigin-RevId: 295491438 GitOrigin-RevId: bffb14058bb46137d42c7a113a36b6b582997cda Change-Id: Ia966857b07fa7412cd6489ac37b5fa26640e4141
Diffstat (limited to 'absl/status/status_test.cc')
-rw-r--r--absl/status/status_test.cc401
1 files changed, 401 insertions, 0 deletions
diff --git a/absl/status/status_test.cc b/absl/status/status_test.cc
new file mode 100644
index 00000000..7cc65e45
--- /dev/null
+++ b/absl/status/status_test.cc
@@ -0,0 +1,401 @@
+// 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);
+}
+
+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']")));
+}
+
+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, 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