James Kuszmaul | 847927d | 2024-05-23 15:33:18 -0700 | [diff] [blame] | 1 | #include "aos/util/status.h" |
| 2 | |
| 3 | #include <filesystem> |
| 4 | |
| 5 | #include "gmock/gmock.h" |
| 6 | #include "gtest/gtest.h" |
| 7 | |
| 8 | #include "aos/realtime.h" |
| 9 | #include "aos/testing/path.h" |
| 10 | |
| 11 | DECLARE_bool(die_on_malloc); |
| 12 | |
| 13 | namespace aos::testing { |
| 14 | class StatusTest : public ::testing::Test { |
| 15 | protected: |
| 16 | StatusTest() {} |
| 17 | }; |
| 18 | |
| 19 | // Tests that we can construct an "Ok" status and that it presents the correct |
| 20 | // interface. |
| 21 | TEST_F(StatusTest, Okay) { |
| 22 | std::optional<Status> ok; |
| 23 | { |
| 24 | aos::ScopedRealtime realtime; |
| 25 | ok = Status::Ok(); |
| 26 | } |
| 27 | ASSERT_TRUE(ok.has_value()); |
| 28 | EXPECT_TRUE(ok->ok()); |
| 29 | EXPECT_EQ(0, ok->code()); |
| 30 | EXPECT_EQ("", ok->message()); |
| 31 | EXPECT_FALSE(ok->source_location().has_value()); |
| 32 | EXPECT_EQ(std::string("Status is okay with code of 0 and message: "), |
| 33 | ok->ToString()); |
| 34 | } |
| 35 | |
| 36 | // Tests that we can construct an errored status in realtime code. |
| 37 | TEST_F(StatusTest, RealtimeError) { |
| 38 | std::optional<Status> error; |
| 39 | { |
| 40 | aos::ScopedRealtime realtime; |
| 41 | error = Status::Error("Hello, World!"); |
| 42 | } |
| 43 | const int line = __LINE__ - 2; |
| 44 | ASSERT_TRUE(error.has_value()); |
| 45 | EXPECT_FALSE(error->ok()); |
| 46 | EXPECT_NE(0, error->code()); |
| 47 | EXPECT_EQ(std::string("Hello, World!"), error->message()); |
| 48 | ASSERT_TRUE(error->source_location().has_value()); |
| 49 | EXPECT_EQ( |
| 50 | std::string("status_test.cc"), |
| 51 | std::filesystem::path(error->source_location()->file_name()).filename()); |
| 52 | EXPECT_EQ( |
| 53 | std::string("virtual void " |
| 54 | "aos::testing::StatusTest_RealtimeError_Test::TestBody()"), |
| 55 | error->source_location()->function_name()); |
| 56 | EXPECT_EQ(line, error->source_location()->line()); |
| 57 | EXPECT_LT(1, error->source_location()->column()); |
| 58 | EXPECT_THAT( |
| 59 | error->ToString(), |
| 60 | ::testing::HasSubstr(absl::StrFormat( |
| 61 | "status_test.cc:%d in virtual void " |
| 62 | "aos::testing::StatusTest_RealtimeError_Test::TestBody(): Status is " |
| 63 | "errored with code of 1 and message: Hello, World!", |
| 64 | line))); |
| 65 | } |
| 66 | |
| 67 | // Tests that we do indeed malloc (and catch it) on an extra-long error message |
| 68 | // (this is mostly intended to ensure that the test setup is working correctly). |
| 69 | TEST(StatusDeatTest, BlowsUpOnRealtimeAllocation) { |
| 70 | std::string message(" ", Status::kStaticMessageLength + 1); |
| 71 | EXPECT_DEATH( |
| 72 | { |
| 73 | aos::ScopedRealtime realtime; |
| 74 | aos::CheckRealtime(); |
| 75 | Status foo = Status::Error(message); |
| 76 | }, |
| 77 | "Malloced"); |
| 78 | } |
| 79 | |
| 80 | // Tests that we can use arbitrarily-sized string literals for error messages. |
| 81 | TEST(StatusDeatTest, StringLiteralError) { |
| 82 | std::optional<Status> error; |
| 83 | const char *message = |
| 84 | "Hellllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll" |
| 85 | "llllllllllllllloooooooooooooooooooooooooooooooooooooooooooo, " |
| 86 | "World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" |
| 87 | "!!!!!!!!!!!!!!"; |
| 88 | ASSERT_LT(Status::kStaticMessageLength, strlen(message)); |
| 89 | { |
| 90 | aos::ScopedRealtime realtime; |
| 91 | error = Status::StringLiteralError(message); |
| 92 | } |
| 93 | ASSERT_TRUE(error.has_value()); |
| 94 | EXPECT_FALSE(error->ok()); |
| 95 | EXPECT_EQ(message, error->message()); |
| 96 | ASSERT_TRUE(error->source_location().has_value()); |
| 97 | EXPECT_EQ( |
| 98 | std::string("status_test.cc"), |
| 99 | std::filesystem::path(error->source_location()->file_name()).filename()); |
| 100 | } |
| 101 | |
| 102 | // Tests that the CheckExpected() call works as intended. |
| 103 | TEST(StatusDeathTest, CheckExpected) { |
| 104 | tl::expected<int, Status> expected; |
| 105 | expected.emplace(971); |
| 106 | EXPECT_EQ(971, CheckExpected(expected)) |
| 107 | << "Should have gotten out the emplaced value on no error."; |
| 108 | expected = Status::UnexpectedError("Hello, World!"); |
| 109 | EXPECT_DEATH(CheckExpected(expected), "Hello, World!") |
| 110 | << "An error message including the error string should have been printed " |
| 111 | "on death."; |
| 112 | EXPECT_DEATH(CheckExpected<void>(Status::UnexpectedError("void expected")), |
| 113 | "void expected") |
| 114 | << "A void expected should work with CheckExpected()."; |
| 115 | } |
| 116 | } // namespace aos::testing |