blob: 0caf73dce8ad741548218383b2fc7a96a8791c79 [file] [log] [blame]
#include "aos/util/status.h"
#include <filesystem>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "aos/realtime.h"
#include "aos/testing/path.h"
DECLARE_bool(die_on_malloc);
namespace aos::testing {
class StatusTest : public ::testing::Test {
protected:
StatusTest() {}
};
// Tests that we can construct an "Ok" status and that it presents the correct
// interface.
TEST_F(StatusTest, Okay) {
std::optional<Status> ok;
{
aos::ScopedRealtime realtime;
ok = Status::Ok();
}
ASSERT_TRUE(ok.has_value());
EXPECT_TRUE(ok->ok());
EXPECT_EQ(0, ok->code());
EXPECT_EQ("", ok->message());
EXPECT_FALSE(ok->source_location().has_value());
EXPECT_EQ(std::string("Status is okay with code of 0 and message: "),
ok->ToString());
}
// Tests that we can construct an errored status in realtime code.
TEST_F(StatusTest, RealtimeError) {
std::optional<Status> error;
{
aos::ScopedRealtime realtime;
error = Status::Error("Hello, World!");
}
const int line = __LINE__ - 2;
ASSERT_TRUE(error.has_value());
EXPECT_FALSE(error->ok());
EXPECT_NE(0, error->code());
EXPECT_EQ(std::string("Hello, World!"), error->message());
ASSERT_TRUE(error->source_location().has_value());
EXPECT_EQ(
std::string("status_test.cc"),
std::filesystem::path(error->source_location()->file_name()).filename());
EXPECT_EQ(
std::string("virtual void "
"aos::testing::StatusTest_RealtimeError_Test::TestBody()"),
error->source_location()->function_name());
EXPECT_EQ(line, error->source_location()->line());
EXPECT_LT(1, error->source_location()->column());
EXPECT_THAT(
error->ToString(),
::testing::HasSubstr(absl::StrFormat(
"status_test.cc:%d in virtual void "
"aos::testing::StatusTest_RealtimeError_Test::TestBody(): Status is "
"errored with code of 1 and message: Hello, World!",
line)));
}
// Tests that we do indeed malloc (and catch it) on an extra-long error message
// (this is mostly intended to ensure that the test setup is working correctly).
TEST(StatusDeatTest, BlowsUpOnRealtimeAllocation) {
std::string message(" ", Status::kStaticMessageLength + 1);
EXPECT_DEATH(
{
aos::ScopedRealtime realtime;
aos::CheckRealtime();
Status foo = Status::Error(message);
},
"Malloced");
}
// Tests that we can use arbitrarily-sized string literals for error messages.
TEST(StatusDeatTest, StringLiteralError) {
std::optional<Status> error;
const char *message =
"Hellllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll"
"llllllllllllllloooooooooooooooooooooooooooooooooooooooooooo, "
"World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
"!!!!!!!!!!!!!!";
ASSERT_LT(Status::kStaticMessageLength, strlen(message));
{
aos::ScopedRealtime realtime;
error = Status::StringLiteralError(message);
}
ASSERT_TRUE(error.has_value());
EXPECT_FALSE(error->ok());
EXPECT_EQ(message, error->message());
ASSERT_TRUE(error->source_location().has_value());
EXPECT_EQ(
std::string("status_test.cc"),
std::filesystem::path(error->source_location()->file_name()).filename());
}
// Tests that the CheckExpected() call works as intended.
TEST(StatusDeathTest, CheckExpected) {
tl::expected<int, Status> expected;
expected.emplace(971);
EXPECT_EQ(971, CheckExpected(expected))
<< "Should have gotten out the emplaced value on no error.";
expected = Status::UnexpectedError("Hello, World!");
EXPECT_DEATH(CheckExpected(expected), "Hello, World!")
<< "An error message including the error string should have been printed "
"on death.";
EXPECT_DEATH(CheckExpected<void>(Status::UnexpectedError("void expected")),
"void expected")
<< "A void expected should work with CheckExpected().";
}
} // namespace aos::testing