blob: 46c9e40f1d1b2dc98c15eb07cec7ce837580341b [file] [log] [blame]
James Kuszmaul847927d2024-05-23 15:33:18 -07001#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
11DECLARE_bool(die_on_malloc);
12
13namespace aos::testing {
14class 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.
21TEST_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.
37TEST_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
James Kuszmaul04942022024-05-29 10:57:56 -070067// Malloc hooks don't work with asan/msan.
68#if !__has_feature(address_sanitizer) && !__has_feature(memory_sanitizer)
James Kuszmaul847927d2024-05-23 15:33:18 -070069// Tests that we do indeed malloc (and catch it) on an extra-long error message
70// (this is mostly intended to ensure that the test setup is working correctly).
James Kuszmaul04942022024-05-29 10:57:56 -070071TEST(StatusDeathTest, BlowsUpOnRealtimeAllocation) {
James Kuszmaul847927d2024-05-23 15:33:18 -070072 std::string message(" ", Status::kStaticMessageLength + 1);
73 EXPECT_DEATH(
74 {
75 aos::ScopedRealtime realtime;
76 aos::CheckRealtime();
77 Status foo = Status::Error(message);
78 },
79 "Malloced");
80}
81
James Kuszmaul04942022024-05-29 10:57:56 -070082#endif
83
James Kuszmaul847927d2024-05-23 15:33:18 -070084// Tests that we can use arbitrarily-sized string literals for error messages.
James Kuszmaul04942022024-05-29 10:57:56 -070085TEST_F(StatusTest, StringLiteralError) {
James Kuszmaul847927d2024-05-23 15:33:18 -070086 std::optional<Status> error;
87 const char *message =
88 "Hellllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll"
89 "llllllllllllllloooooooooooooooooooooooooooooooooooooooooooo, "
90 "World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
91 "!!!!!!!!!!!!!!";
92 ASSERT_LT(Status::kStaticMessageLength, strlen(message));
93 {
94 aos::ScopedRealtime realtime;
95 error = Status::StringLiteralError(message);
96 }
97 ASSERT_TRUE(error.has_value());
98 EXPECT_FALSE(error->ok());
99 EXPECT_EQ(message, error->message());
100 ASSERT_TRUE(error->source_location().has_value());
101 EXPECT_EQ(
102 std::string("status_test.cc"),
103 std::filesystem::path(error->source_location()->file_name()).filename());
104}
105
106// Tests that the CheckExpected() call works as intended.
107TEST(StatusDeathTest, CheckExpected) {
108 tl::expected<int, Status> expected;
109 expected.emplace(971);
110 EXPECT_EQ(971, CheckExpected(expected))
111 << "Should have gotten out the emplaced value on no error.";
112 expected = Status::UnexpectedError("Hello, World!");
113 EXPECT_DEATH(CheckExpected(expected), "Hello, World!")
114 << "An error message including the error string should have been printed "
115 "on death.";
116 EXPECT_DEATH(CheckExpected<void>(Status::UnexpectedError("void expected")),
117 "void expected")
118 << "A void expected should work with CheckExpected().";
119}
120} // namespace aos::testing