blob: 0caf73dce8ad741548218383b2fc7a96a8791c79 [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
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).
69TEST(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.
81TEST(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.
103TEST(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