status_test.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. // Copyright 2019 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "absl/status/status.h"
  15. #include "gmock/gmock.h"
  16. #include "gtest/gtest.h"
  17. #include "absl/strings/str_cat.h"
  18. namespace {
  19. using ::testing::Eq;
  20. using ::testing::HasSubstr;
  21. using ::testing::Optional;
  22. using ::testing::UnorderedElementsAreArray;
  23. TEST(StatusCode, InsertionOperator) {
  24. const absl::StatusCode code = absl::StatusCode::kUnknown;
  25. std::ostringstream oss;
  26. oss << code;
  27. EXPECT_EQ(oss.str(), absl::StatusCodeToString(code));
  28. }
  29. // This structure holds the details for testing a single error code,
  30. // its creator, and its classifier.
  31. struct ErrorTest {
  32. absl::StatusCode code;
  33. using Creator = absl::Status (*)(
  34. absl::string_view
  35. );
  36. using Classifier = bool (*)(const absl::Status&);
  37. Creator creator;
  38. Classifier classifier;
  39. };
  40. constexpr ErrorTest kErrorTests[]{
  41. {absl::StatusCode::kCancelled, absl::CancelledError, absl::IsCancelled},
  42. {absl::StatusCode::kUnknown, absl::UnknownError, absl::IsUnknown},
  43. {absl::StatusCode::kInvalidArgument, absl::InvalidArgumentError,
  44. absl::IsInvalidArgument},
  45. {absl::StatusCode::kDeadlineExceeded, absl::DeadlineExceededError,
  46. absl::IsDeadlineExceeded},
  47. {absl::StatusCode::kNotFound, absl::NotFoundError, absl::IsNotFound},
  48. {absl::StatusCode::kAlreadyExists, absl::AlreadyExistsError,
  49. absl::IsAlreadyExists},
  50. {absl::StatusCode::kPermissionDenied, absl::PermissionDeniedError,
  51. absl::IsPermissionDenied},
  52. {absl::StatusCode::kResourceExhausted, absl::ResourceExhaustedError,
  53. absl::IsResourceExhausted},
  54. {absl::StatusCode::kFailedPrecondition, absl::FailedPreconditionError,
  55. absl::IsFailedPrecondition},
  56. {absl::StatusCode::kAborted, absl::AbortedError, absl::IsAborted},
  57. {absl::StatusCode::kOutOfRange, absl::OutOfRangeError, absl::IsOutOfRange},
  58. {absl::StatusCode::kUnimplemented, absl::UnimplementedError,
  59. absl::IsUnimplemented},
  60. {absl::StatusCode::kInternal, absl::InternalError, absl::IsInternal},
  61. {absl::StatusCode::kUnavailable, absl::UnavailableError,
  62. absl::IsUnavailable},
  63. {absl::StatusCode::kDataLoss, absl::DataLossError, absl::IsDataLoss},
  64. {absl::StatusCode::kUnauthenticated, absl::UnauthenticatedError,
  65. absl::IsUnauthenticated},
  66. };
  67. TEST(Status, CreateAndClassify) {
  68. for (const auto& test : kErrorTests) {
  69. SCOPED_TRACE(absl::StatusCodeToString(test.code));
  70. // Ensure that the creator does, in fact, create status objects with the
  71. // expected error code and message.
  72. std::string message =
  73. absl::StrCat("error code ", test.code, " test message");
  74. absl::Status status = test.creator(
  75. message
  76. );
  77. EXPECT_EQ(test.code, status.code());
  78. EXPECT_EQ(message, status.message());
  79. // Ensure that the classifier returns true for a status produced by the
  80. // creator.
  81. EXPECT_TRUE(test.classifier(status));
  82. // Ensure that the classifier returns false for status with a different
  83. // code.
  84. for (const auto& other : kErrorTests) {
  85. if (other.code != test.code) {
  86. EXPECT_FALSE(test.classifier(absl::Status(other.code, "")))
  87. << " other.code = " << other.code;
  88. }
  89. }
  90. }
  91. }
  92. TEST(Status, DefaultConstructor) {
  93. absl::Status status;
  94. EXPECT_TRUE(status.ok());
  95. EXPECT_EQ(absl::StatusCode::kOk, status.code());
  96. EXPECT_EQ("", status.message());
  97. }
  98. TEST(Status, OkStatus) {
  99. absl::Status status = absl::OkStatus();
  100. EXPECT_TRUE(status.ok());
  101. EXPECT_EQ(absl::StatusCode::kOk, status.code());
  102. EXPECT_EQ("", status.message());
  103. }
  104. TEST(Status, ConstructorWithCodeMessage) {
  105. {
  106. absl::Status status(absl::StatusCode::kCancelled, "");
  107. EXPECT_FALSE(status.ok());
  108. EXPECT_EQ(absl::StatusCode::kCancelled, status.code());
  109. EXPECT_EQ("", status.message());
  110. }
  111. {
  112. absl::Status status(absl::StatusCode::kInternal, "message");
  113. EXPECT_FALSE(status.ok());
  114. EXPECT_EQ(absl::StatusCode::kInternal, status.code());
  115. EXPECT_EQ("message", status.message());
  116. }
  117. }
  118. TEST(Status, ConstructOutOfRangeCode) {
  119. const int kRawCode = 9999;
  120. absl::Status status(static_cast<absl::StatusCode>(kRawCode), "");
  121. EXPECT_EQ(absl::StatusCode::kUnknown, status.code());
  122. EXPECT_EQ(kRawCode, status.raw_code());
  123. }
  124. constexpr char kUrl1[] = "url.payload.1";
  125. constexpr char kUrl2[] = "url.payload.2";
  126. constexpr char kUrl3[] = "url.payload.3";
  127. constexpr char kUrl4[] = "url.payload.xx";
  128. constexpr char kPayload1[] = "aaaaa";
  129. constexpr char kPayload2[] = "bbbbb";
  130. constexpr char kPayload3[] = "ccccc";
  131. using PayloadsVec = std::vector<std::pair<std::string, absl::Cord>>;
  132. TEST(Status, TestGetSetPayload) {
  133. absl::Status ok_status = absl::OkStatus();
  134. ok_status.SetPayload(kUrl1, absl::Cord(kPayload1));
  135. ok_status.SetPayload(kUrl2, absl::Cord(kPayload2));
  136. EXPECT_FALSE(ok_status.GetPayload(kUrl1));
  137. EXPECT_FALSE(ok_status.GetPayload(kUrl2));
  138. absl::Status bad_status(absl::StatusCode::kInternal, "fail");
  139. bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
  140. bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
  141. EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload1)));
  142. EXPECT_THAT(bad_status.GetPayload(kUrl2), Optional(Eq(kPayload2)));
  143. EXPECT_FALSE(bad_status.GetPayload(kUrl3));
  144. bad_status.SetPayload(kUrl1, absl::Cord(kPayload3));
  145. EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload3)));
  146. // Testing dynamically generated type_url
  147. bad_status.SetPayload(absl::StrCat(kUrl1, ".1"), absl::Cord(kPayload1));
  148. EXPECT_THAT(bad_status.GetPayload(absl::StrCat(kUrl1, ".1")),
  149. Optional(Eq(kPayload1)));
  150. }
  151. TEST(Status, TestErasePayload) {
  152. absl::Status bad_status(absl::StatusCode::kInternal, "fail");
  153. bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
  154. bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
  155. bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));
  156. EXPECT_FALSE(bad_status.ErasePayload(kUrl4));
  157. EXPECT_TRUE(bad_status.GetPayload(kUrl2));
  158. EXPECT_TRUE(bad_status.ErasePayload(kUrl2));
  159. EXPECT_FALSE(bad_status.GetPayload(kUrl2));
  160. EXPECT_FALSE(bad_status.ErasePayload(kUrl2));
  161. EXPECT_TRUE(bad_status.ErasePayload(kUrl1));
  162. EXPECT_TRUE(bad_status.ErasePayload(kUrl3));
  163. bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
  164. EXPECT_TRUE(bad_status.ErasePayload(kUrl1));
  165. }
  166. TEST(Status, TestComparePayloads) {
  167. absl::Status bad_status1(absl::StatusCode::kInternal, "fail");
  168. bad_status1.SetPayload(kUrl1, absl::Cord(kPayload1));
  169. bad_status1.SetPayload(kUrl2, absl::Cord(kPayload2));
  170. bad_status1.SetPayload(kUrl3, absl::Cord(kPayload3));
  171. absl::Status bad_status2(absl::StatusCode::kInternal, "fail");
  172. bad_status2.SetPayload(kUrl2, absl::Cord(kPayload2));
  173. bad_status2.SetPayload(kUrl3, absl::Cord(kPayload3));
  174. bad_status2.SetPayload(kUrl1, absl::Cord(kPayload1));
  175. EXPECT_EQ(bad_status1, bad_status2);
  176. }
  177. TEST(Status, TestComparePayloadsAfterErase) {
  178. absl::Status payload_status(absl::StatusCode::kInternal, "");
  179. payload_status.SetPayload(kUrl1, absl::Cord(kPayload1));
  180. payload_status.SetPayload(kUrl2, absl::Cord(kPayload2));
  181. absl::Status empty_status(absl::StatusCode::kInternal, "");
  182. // Different payloads, not equal
  183. EXPECT_NE(payload_status, empty_status);
  184. EXPECT_TRUE(payload_status.ErasePayload(kUrl1));
  185. // Still Different payloads, still not equal.
  186. EXPECT_NE(payload_status, empty_status);
  187. EXPECT_TRUE(payload_status.ErasePayload(kUrl2));
  188. // Both empty payloads, should be equal
  189. EXPECT_EQ(payload_status, empty_status);
  190. }
  191. PayloadsVec AllVisitedPayloads(const absl::Status& s) {
  192. PayloadsVec result;
  193. s.ForEachPayload([&](absl::string_view type_url, const absl::Cord& payload) {
  194. result.push_back(std::make_pair(std::string(type_url), payload));
  195. });
  196. return result;
  197. }
  198. TEST(Status, TestForEachPayload) {
  199. absl::Status bad_status(absl::StatusCode::kInternal, "fail");
  200. bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
  201. bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
  202. bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));
  203. int count = 0;
  204. bad_status.ForEachPayload(
  205. [&count](absl::string_view, const absl::Cord&) { ++count; });
  206. EXPECT_EQ(count, 3);
  207. PayloadsVec expected_payloads = {{kUrl1, absl::Cord(kPayload1)},
  208. {kUrl2, absl::Cord(kPayload2)},
  209. {kUrl3, absl::Cord(kPayload3)}};
  210. // Test that we visit all the payloads in the status.
  211. PayloadsVec visited_payloads = AllVisitedPayloads(bad_status);
  212. EXPECT_THAT(visited_payloads, UnorderedElementsAreArray(expected_payloads));
  213. // Test that visitation order is not consistent between run.
  214. std::vector<absl::Status> scratch;
  215. while (true) {
  216. scratch.emplace_back(absl::StatusCode::kInternal, "fail");
  217. scratch.back().SetPayload(kUrl1, absl::Cord(kPayload1));
  218. scratch.back().SetPayload(kUrl2, absl::Cord(kPayload2));
  219. scratch.back().SetPayload(kUrl3, absl::Cord(kPayload3));
  220. if (AllVisitedPayloads(scratch.back()) != visited_payloads) {
  221. break;
  222. }
  223. }
  224. }
  225. TEST(Status, ToString) {
  226. absl::Status s(absl::StatusCode::kInternal, "fail");
  227. EXPECT_EQ("INTERNAL: fail", s.ToString());
  228. s.SetPayload("foo", absl::Cord("bar"));
  229. EXPECT_EQ("INTERNAL: fail [foo='bar']", s.ToString());
  230. s.SetPayload("bar", absl::Cord("\377"));
  231. EXPECT_THAT(s.ToString(),
  232. AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
  233. HasSubstr("[bar='\\xff']")));
  234. }
  235. TEST(Status, ToStringMode) {
  236. absl::Status s(absl::StatusCode::kInternal, "fail");
  237. s.SetPayload("foo", absl::Cord("bar"));
  238. s.SetPayload("bar", absl::Cord("\377"));
  239. EXPECT_EQ("INTERNAL: fail",
  240. s.ToString(absl::StatusToStringMode::kWithNoExtraData));
  241. EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload),
  242. AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
  243. HasSubstr("[bar='\\xff']")));
  244. EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithEverything),
  245. AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
  246. HasSubstr("[bar='\\xff']")));
  247. EXPECT_THAT(s.ToString(~absl::StatusToStringMode::kWithPayload),
  248. AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")),
  249. Not(HasSubstr("[bar='\\xff']"))));
  250. }
  251. absl::Status EraseAndReturn(const absl::Status& base) {
  252. absl::Status copy = base;
  253. EXPECT_TRUE(copy.ErasePayload(kUrl1));
  254. return copy;
  255. }
  256. TEST(Status, CopyOnWriteForErasePayload) {
  257. {
  258. absl::Status base(absl::StatusCode::kInvalidArgument, "fail");
  259. base.SetPayload(kUrl1, absl::Cord(kPayload1));
  260. EXPECT_TRUE(base.GetPayload(kUrl1).has_value());
  261. absl::Status copy = EraseAndReturn(base);
  262. EXPECT_TRUE(base.GetPayload(kUrl1).has_value());
  263. EXPECT_FALSE(copy.GetPayload(kUrl1).has_value());
  264. }
  265. {
  266. absl::Status base(absl::StatusCode::kInvalidArgument, "fail");
  267. base.SetPayload(kUrl1, absl::Cord(kPayload1));
  268. absl::Status copy = base;
  269. EXPECT_TRUE(base.GetPayload(kUrl1).has_value());
  270. EXPECT_TRUE(copy.GetPayload(kUrl1).has_value());
  271. EXPECT_TRUE(base.ErasePayload(kUrl1));
  272. EXPECT_FALSE(base.GetPayload(kUrl1).has_value());
  273. EXPECT_TRUE(copy.GetPayload(kUrl1).has_value());
  274. }
  275. }
  276. TEST(Status, CopyConstructor) {
  277. {
  278. absl::Status status;
  279. absl::Status copy(status);
  280. EXPECT_EQ(copy, status);
  281. }
  282. {
  283. absl::Status status(absl::StatusCode::kInvalidArgument, "message");
  284. absl::Status copy(status);
  285. EXPECT_EQ(copy, status);
  286. }
  287. {
  288. absl::Status status(absl::StatusCode::kInvalidArgument, "message");
  289. status.SetPayload(kUrl1, absl::Cord(kPayload1));
  290. absl::Status copy(status);
  291. EXPECT_EQ(copy, status);
  292. }
  293. }
  294. TEST(Status, CopyAssignment) {
  295. absl::Status assignee;
  296. {
  297. absl::Status status;
  298. assignee = status;
  299. EXPECT_EQ(assignee, status);
  300. }
  301. {
  302. absl::Status status(absl::StatusCode::kInvalidArgument, "message");
  303. assignee = status;
  304. EXPECT_EQ(assignee, status);
  305. }
  306. {
  307. absl::Status status(absl::StatusCode::kInvalidArgument, "message");
  308. status.SetPayload(kUrl1, absl::Cord(kPayload1));
  309. assignee = status;
  310. EXPECT_EQ(assignee, status);
  311. }
  312. }
  313. TEST(Status, CopyAssignmentIsNotRef) {
  314. const absl::Status status_orig(absl::StatusCode::kInvalidArgument, "message");
  315. absl::Status status_copy = status_orig;
  316. EXPECT_EQ(status_orig, status_copy);
  317. status_copy.SetPayload(kUrl1, absl::Cord(kPayload1));
  318. EXPECT_NE(status_orig, status_copy);
  319. }
  320. TEST(Status, MoveConstructor) {
  321. {
  322. absl::Status status;
  323. absl::Status copy(absl::Status{});
  324. EXPECT_EQ(copy, status);
  325. }
  326. {
  327. absl::Status status(absl::StatusCode::kInvalidArgument, "message");
  328. absl::Status copy(
  329. absl::Status(absl::StatusCode::kInvalidArgument, "message"));
  330. EXPECT_EQ(copy, status);
  331. }
  332. {
  333. absl::Status status(absl::StatusCode::kInvalidArgument, "message");
  334. status.SetPayload(kUrl1, absl::Cord(kPayload1));
  335. absl::Status copy1(status);
  336. absl::Status copy2(std::move(status));
  337. EXPECT_EQ(copy1, copy2);
  338. }
  339. }
  340. TEST(Status, MoveAssignment) {
  341. absl::Status assignee;
  342. {
  343. absl::Status status;
  344. assignee = absl::Status();
  345. EXPECT_EQ(assignee, status);
  346. }
  347. {
  348. absl::Status status(absl::StatusCode::kInvalidArgument, "message");
  349. assignee = absl::Status(absl::StatusCode::kInvalidArgument, "message");
  350. EXPECT_EQ(assignee, status);
  351. }
  352. {
  353. absl::Status status(absl::StatusCode::kInvalidArgument, "message");
  354. status.SetPayload(kUrl1, absl::Cord(kPayload1));
  355. absl::Status copy(status);
  356. assignee = std::move(status);
  357. EXPECT_EQ(assignee, copy);
  358. }
  359. {
  360. absl::Status status(absl::StatusCode::kInvalidArgument, "message");
  361. absl::Status copy(status);
  362. status = static_cast<absl::Status&&>(status);
  363. EXPECT_EQ(status, copy);
  364. }
  365. }
  366. TEST(Status, Update) {
  367. absl::Status s;
  368. s.Update(absl::OkStatus());
  369. EXPECT_TRUE(s.ok());
  370. const absl::Status a(absl::StatusCode::kCancelled, "message");
  371. s.Update(a);
  372. EXPECT_EQ(s, a);
  373. const absl::Status b(absl::StatusCode::kInternal, "other message");
  374. s.Update(b);
  375. EXPECT_EQ(s, a);
  376. s.Update(absl::OkStatus());
  377. EXPECT_EQ(s, a);
  378. EXPECT_FALSE(s.ok());
  379. }
  380. TEST(Status, Equality) {
  381. absl::Status ok;
  382. absl::Status no_payload = absl::CancelledError("no payload");
  383. absl::Status one_payload = absl::InvalidArgumentError("one payload");
  384. one_payload.SetPayload(kUrl1, absl::Cord(kPayload1));
  385. absl::Status two_payloads = one_payload;
  386. two_payloads.SetPayload(kUrl2, absl::Cord(kPayload2));
  387. const std::array<absl::Status, 4> status_arr = {ok, no_payload, one_payload,
  388. two_payloads};
  389. for (int i = 0; i < status_arr.size(); i++) {
  390. for (int j = 0; j < status_arr.size(); j++) {
  391. if (i == j) {
  392. EXPECT_TRUE(status_arr[i] == status_arr[j]);
  393. EXPECT_FALSE(status_arr[i] != status_arr[j]);
  394. } else {
  395. EXPECT_TRUE(status_arr[i] != status_arr[j]);
  396. EXPECT_FALSE(status_arr[i] == status_arr[j]);
  397. }
  398. }
  399. }
  400. }
  401. TEST(Status, Swap) {
  402. auto test_swap = [](const absl::Status& s1, const absl::Status& s2) {
  403. absl::Status copy1 = s1, copy2 = s2;
  404. swap(copy1, copy2);
  405. EXPECT_EQ(copy1, s2);
  406. EXPECT_EQ(copy2, s1);
  407. };
  408. const absl::Status ok;
  409. const absl::Status no_payload(absl::StatusCode::kAlreadyExists, "no payload");
  410. absl::Status with_payload(absl::StatusCode::kInternal, "with payload");
  411. with_payload.SetPayload(kUrl1, absl::Cord(kPayload1));
  412. test_swap(ok, no_payload);
  413. test_swap(no_payload, ok);
  414. test_swap(ok, with_payload);
  415. test_swap(with_payload, ok);
  416. test_swap(no_payload, with_payload);
  417. test_swap(with_payload, no_payload);
  418. }
  419. } // namespace