blob: b838636be8dae45b38717ea2b39541cfeeeffb98 [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 {
James Kuszmaul053d42a2024-05-30 16:46:08 -070014class ErrorTest : public ::testing::Test {
James Kuszmaul847927d2024-05-23 15:33:18 -070015 protected:
James Kuszmaul053d42a2024-05-30 16:46:08 -070016 ErrorTest() {}
James Kuszmaul847927d2024-05-23 15:33:18 -070017};
18
James Kuszmaul847927d2024-05-23 15:33:18 -070019// Tests that we can construct an errored status in realtime code.
James Kuszmaul053d42a2024-05-30 16:46:08 -070020TEST_F(ErrorTest, RealtimeError) {
21 std::optional<Error> error;
James Kuszmaul847927d2024-05-23 15:33:18 -070022 {
23 aos::ScopedRealtime realtime;
James Kuszmaul053d42a2024-05-30 16:46:08 -070024 error = Error::MakeError("Hello, World!");
James Kuszmaul847927d2024-05-23 15:33:18 -070025 }
26 const int line = __LINE__ - 2;
27 ASSERT_TRUE(error.has_value());
James Kuszmaul847927d2024-05-23 15:33:18 -070028 EXPECT_NE(0, error->code());
29 EXPECT_EQ(std::string("Hello, World!"), error->message());
30 ASSERT_TRUE(error->source_location().has_value());
31 EXPECT_EQ(
32 std::string("status_test.cc"),
33 std::filesystem::path(error->source_location()->file_name()).filename());
34 EXPECT_EQ(
35 std::string("virtual void "
James Kuszmaul053d42a2024-05-30 16:46:08 -070036 "aos::testing::ErrorTest_RealtimeError_Test::TestBody()"),
James Kuszmaul847927d2024-05-23 15:33:18 -070037 error->source_location()->function_name());
38 EXPECT_EQ(line, error->source_location()->line());
39 EXPECT_LT(1, error->source_location()->column());
40 EXPECT_THAT(
41 error->ToString(),
42 ::testing::HasSubstr(absl::StrFormat(
43 "status_test.cc:%d in virtual void "
James Kuszmaul053d42a2024-05-30 16:46:08 -070044 "aos::testing::ErrorTest_RealtimeError_Test::TestBody(): Errored "
45 "with code of 1 and message: Hello, World!",
James Kuszmaul847927d2024-05-23 15:33:18 -070046 line)));
47}
48
James Kuszmaul053d42a2024-05-30 16:46:08 -070049// Tests that the ResultExitCode() function will correctly transform a Result<>
50// object into an exit code suitable for exiting a program.
51TEST_F(ErrorTest, ExitCode) {
52 static_assert(0 == static_cast<int>(Error::StatusCode::kOk));
53 EXPECT_EQ(static_cast<int>(Error::StatusCode::kOk),
54 ResultExitCode(Result<void>{}));
55 EXPECT_EQ(static_cast<int>(Error::StatusCode::kError),
56 ResultExitCode(Error::MakeUnexpectedError("")));
57}
58
James Kuszmaul04942022024-05-29 10:57:56 -070059// Malloc hooks don't work with asan/msan.
60#if !__has_feature(address_sanitizer) && !__has_feature(memory_sanitizer)
James Kuszmaul847927d2024-05-23 15:33:18 -070061// Tests that we do indeed malloc (and catch it) on an extra-long error message
62// (this is mostly intended to ensure that the test setup is working correctly).
James Kuszmaul053d42a2024-05-30 16:46:08 -070063TEST(ErrorDeathTest, BlowsUpOnRealtimeAllocation) {
64 std::string message(" ", Error::kStaticMessageLength + 1);
James Kuszmaul847927d2024-05-23 15:33:18 -070065 EXPECT_DEATH(
66 {
67 aos::ScopedRealtime realtime;
68 aos::CheckRealtime();
James Kuszmaul053d42a2024-05-30 16:46:08 -070069 Error foo = Error::MakeError(message);
James Kuszmaul847927d2024-05-23 15:33:18 -070070 },
71 "Malloced");
72}
73
James Kuszmaul04942022024-05-29 10:57:56 -070074#endif
75
James Kuszmaul847927d2024-05-23 15:33:18 -070076// Tests that we can use arbitrarily-sized string literals for error messages.
James Kuszmaul053d42a2024-05-30 16:46:08 -070077TEST_F(ErrorTest, StringLiteralError) {
78 std::optional<Error> error;
James Kuszmaul847927d2024-05-23 15:33:18 -070079 const char *message =
80 "Hellllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll"
81 "llllllllllllllloooooooooooooooooooooooooooooooooooooooooooo, "
82 "World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
83 "!!!!!!!!!!!!!!";
James Kuszmaul053d42a2024-05-30 16:46:08 -070084 ASSERT_LT(Error::kStaticMessageLength, strlen(message));
James Kuszmaul847927d2024-05-23 15:33:18 -070085 {
86 aos::ScopedRealtime realtime;
James Kuszmaul053d42a2024-05-30 16:46:08 -070087 error = Error::MakeStringLiteralError(message);
James Kuszmaul847927d2024-05-23 15:33:18 -070088 }
89 ASSERT_TRUE(error.has_value());
James Kuszmaul847927d2024-05-23 15:33:18 -070090 EXPECT_EQ(message, error->message());
91 ASSERT_TRUE(error->source_location().has_value());
92 EXPECT_EQ(
93 std::string("status_test.cc"),
94 std::filesystem::path(error->source_location()->file_name()).filename());
95}
96
97// Tests that the CheckExpected() call works as intended.
James Kuszmaul053d42a2024-05-30 16:46:08 -070098TEST(ErrorDeathTest, CheckExpected) {
99 tl::expected<int, Error> expected;
James Kuszmaul847927d2024-05-23 15:33:18 -0700100 expected.emplace(971);
101 EXPECT_EQ(971, CheckExpected(expected))
102 << "Should have gotten out the emplaced value on no error.";
James Kuszmaul053d42a2024-05-30 16:46:08 -0700103 expected = Error::MakeUnexpectedError("Hello, World!");
James Kuszmaul847927d2024-05-23 15:33:18 -0700104 EXPECT_DEATH(CheckExpected(expected), "Hello, World!")
105 << "An error message including the error string should have been printed "
106 "on death.";
James Kuszmaul053d42a2024-05-30 16:46:08 -0700107 EXPECT_DEATH(CheckExpected<void>(Error::MakeUnexpectedError("void expected")),
James Kuszmaul847927d2024-05-23 15:33:18 -0700108 "void expected")
109 << "A void expected should work with CheckExpected().";
110}
111} // namespace aos::testing