blob: fe77c61d065d9fb8f68afd624ebdfacf137c0330 [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
James Kuszmaul847927d2024-05-23 15:33:18 -070011namespace aos::testing {
James Kuszmaul053d42a2024-05-30 16:46:08 -070012class ErrorTest : public ::testing::Test {
James Kuszmaul847927d2024-05-23 15:33:18 -070013 protected:
James Kuszmaul053d42a2024-05-30 16:46:08 -070014 ErrorTest() {}
James Kuszmaul847927d2024-05-23 15:33:18 -070015};
16
James Kuszmaul847927d2024-05-23 15:33:18 -070017// Tests that we can construct an errored status in realtime code.
James Kuszmaul053d42a2024-05-30 16:46:08 -070018TEST_F(ErrorTest, RealtimeError) {
19 std::optional<Error> error;
James Kuszmaul847927d2024-05-23 15:33:18 -070020 {
21 aos::ScopedRealtime realtime;
James Kuszmaul053d42a2024-05-30 16:46:08 -070022 error = Error::MakeError("Hello, World!");
James Kuszmaul847927d2024-05-23 15:33:18 -070023 }
24 const int line = __LINE__ - 2;
25 ASSERT_TRUE(error.has_value());
James Kuszmaul847927d2024-05-23 15:33:18 -070026 EXPECT_NE(0, error->code());
27 EXPECT_EQ(std::string("Hello, World!"), error->message());
28 ASSERT_TRUE(error->source_location().has_value());
29 EXPECT_EQ(
30 std::string("status_test.cc"),
31 std::filesystem::path(error->source_location()->file_name()).filename());
32 EXPECT_EQ(
33 std::string("virtual void "
James Kuszmaul053d42a2024-05-30 16:46:08 -070034 "aos::testing::ErrorTest_RealtimeError_Test::TestBody()"),
James Kuszmaul847927d2024-05-23 15:33:18 -070035 error->source_location()->function_name());
36 EXPECT_EQ(line, error->source_location()->line());
37 EXPECT_LT(1, error->source_location()->column());
38 EXPECT_THAT(
39 error->ToString(),
40 ::testing::HasSubstr(absl::StrFormat(
41 "status_test.cc:%d in virtual void "
James Kuszmaul053d42a2024-05-30 16:46:08 -070042 "aos::testing::ErrorTest_RealtimeError_Test::TestBody(): Errored "
43 "with code of 1 and message: Hello, World!",
James Kuszmaul847927d2024-05-23 15:33:18 -070044 line)));
45}
46
James Kuszmaul053d42a2024-05-30 16:46:08 -070047// Tests that the ResultExitCode() function will correctly transform a Result<>
48// object into an exit code suitable for exiting a program.
49TEST_F(ErrorTest, ExitCode) {
50 static_assert(0 == static_cast<int>(Error::StatusCode::kOk));
51 EXPECT_EQ(static_cast<int>(Error::StatusCode::kOk),
52 ResultExitCode(Result<void>{}));
53 EXPECT_EQ(static_cast<int>(Error::StatusCode::kError),
54 ResultExitCode(Error::MakeUnexpectedError("")));
55}
56
James Kuszmaul04942022024-05-29 10:57:56 -070057// Malloc hooks don't work with asan/msan.
58#if !__has_feature(address_sanitizer) && !__has_feature(memory_sanitizer)
James Kuszmaul847927d2024-05-23 15:33:18 -070059// Tests that we do indeed malloc (and catch it) on an extra-long error message
60// (this is mostly intended to ensure that the test setup is working correctly).
James Kuszmaul053d42a2024-05-30 16:46:08 -070061TEST(ErrorDeathTest, BlowsUpOnRealtimeAllocation) {
62 std::string message(" ", Error::kStaticMessageLength + 1);
James Kuszmaul847927d2024-05-23 15:33:18 -070063 EXPECT_DEATH(
64 {
65 aos::ScopedRealtime realtime;
66 aos::CheckRealtime();
James Kuszmaul053d42a2024-05-30 16:46:08 -070067 Error foo = Error::MakeError(message);
James Kuszmaul847927d2024-05-23 15:33:18 -070068 },
69 "Malloced");
70}
71
James Kuszmaul04942022024-05-29 10:57:56 -070072#endif
73
James Kuszmaul847927d2024-05-23 15:33:18 -070074// Tests that we can use arbitrarily-sized string literals for error messages.
James Kuszmaul053d42a2024-05-30 16:46:08 -070075TEST_F(ErrorTest, StringLiteralError) {
76 std::optional<Error> error;
James Kuszmaul847927d2024-05-23 15:33:18 -070077 const char *message =
78 "Hellllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll"
79 "llllllllllllllloooooooooooooooooooooooooooooooooooooooooooo, "
80 "World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
81 "!!!!!!!!!!!!!!";
James Kuszmaul053d42a2024-05-30 16:46:08 -070082 ASSERT_LT(Error::kStaticMessageLength, strlen(message));
James Kuszmaul847927d2024-05-23 15:33:18 -070083 {
84 aos::ScopedRealtime realtime;
James Kuszmaul053d42a2024-05-30 16:46:08 -070085 error = Error::MakeStringLiteralError(message);
James Kuszmaul847927d2024-05-23 15:33:18 -070086 }
87 ASSERT_TRUE(error.has_value());
James Kuszmaul847927d2024-05-23 15:33:18 -070088 EXPECT_EQ(message, error->message());
89 ASSERT_TRUE(error->source_location().has_value());
90 EXPECT_EQ(
91 std::string("status_test.cc"),
92 std::filesystem::path(error->source_location()->file_name()).filename());
93}
94
95// Tests that the CheckExpected() call works as intended.
James Kuszmaul053d42a2024-05-30 16:46:08 -070096TEST(ErrorDeathTest, CheckExpected) {
97 tl::expected<int, Error> expected;
James Kuszmaul847927d2024-05-23 15:33:18 -070098 expected.emplace(971);
99 EXPECT_EQ(971, CheckExpected(expected))
100 << "Should have gotten out the emplaced value on no error.";
James Kuszmaul053d42a2024-05-30 16:46:08 -0700101 expected = Error::MakeUnexpectedError("Hello, World!");
James Kuszmaul847927d2024-05-23 15:33:18 -0700102 EXPECT_DEATH(CheckExpected(expected), "Hello, World!")
103 << "An error message including the error string should have been printed "
104 "on death.";
James Kuszmaul053d42a2024-05-30 16:46:08 -0700105 EXPECT_DEATH(CheckExpected<void>(Error::MakeUnexpectedError("void expected")),
James Kuszmaul847927d2024-05-23 15:33:18 -0700106 "void expected")
107 << "A void expected should work with CheckExpected().";
108}
109} // namespace aos::testing