blob: b9a1d8c639c43a616bcdc5f504f790ce990fb6d9 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#include "src/developer/forensics/exceptions/handler/report_builder.h"
#include <gtest/gtest.h>
#include "src/developer/forensics/exceptions/tests/crasher_wrapper.h"
#include "src/lib/fsl/vmo/strings.h"
namespace forensics {
namespace exceptions {
namespace handler {
namespace {
class CrashReportBuilderTest : public testing::Test {
protected:
// Use an invalid process/thread becuase we don't care about the specific name and koid of each.
void SetUp() { builder_.SetProcess(zx::process{}).SetThread(zx::thread{}); }
CrashReportBuilder builder_;
};
TEST_F(CrashReportBuilderTest, SetsMinidump) {
fsl::SizedVmo minidump_vmo;
ASSERT_TRUE(fsl::VmoFromString("minidump", &minidump_vmo));
builder_.SetMinidump(std::move(minidump_vmo.vmo()));
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_specific_report());
ASSERT_TRUE(crash_report.specific_report().is_native());
std::string minidump_content;
ASSERT_TRUE(
fsl::StringFromVmo(crash_report.specific_report().native().minidump(), &minidump_content));
EXPECT_STREQ(minidump_content.c_str(), "minidump");
}
TEST_F(CrashReportBuilderTest, ExceptionReason_ChannelOverflow) {
fsl::SizedVmo minidump_vmo;
ASSERT_TRUE(fsl::VmoFromString("minidump", &minidump_vmo));
builder_.SetMinidump(std::move(minidump_vmo.vmo()))
.SetExceptionReason(ExceptionReason::kChannelOverflow);
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_crash_signature());
EXPECT_EQ(crash_report.crash_signature(), "fuchsia-unknown_process-channel-overflow");
}
TEST_F(CrashReportBuilderTest, ExceptionReason_PortObserverOverflow) {
fsl::SizedVmo minidump_vmo;
ASSERT_TRUE(fsl::VmoFromString("minidump", &minidump_vmo));
builder_.SetMinidump(std::move(minidump_vmo.vmo()))
.SetExceptionReason(ExceptionReason::kPortObserverOverflow);
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_crash_signature());
EXPECT_EQ(crash_report.crash_signature(), "fuchsia-unknown_process-port-observer-overflow");
}
TEST_F(CrashReportBuilderTest, ExceptionReason_PortPacketOverflow) {
fsl::SizedVmo minidump_vmo;
ASSERT_TRUE(fsl::VmoFromString("minidump", &minidump_vmo));
builder_.SetMinidump(std::move(minidump_vmo.vmo()))
.SetExceptionReason(ExceptionReason::kPortPacketOverflow);
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_crash_signature());
EXPECT_EQ(crash_report.crash_signature(), "fuchsia-unknown_process-port-packet-overflow");
}
TEST_F(CrashReportBuilderTest, ExceptionReason_PageFaultIo) {
fsl::SizedVmo minidump_vmo;
ASSERT_TRUE(fsl::VmoFromString("minidump", &minidump_vmo));
builder_.SetMinidump(std::move(minidump_vmo.vmo()))
.SetExceptionReason(ExceptionReason::kPageFaultIo);
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_crash_signature());
EXPECT_EQ(crash_report.crash_signature(), "fuchsia-page_fault-io");
}
TEST_F(CrashReportBuilderTest, ExceptionReason_PageFaultIoDataIntegrity) {
fsl::SizedVmo minidump_vmo;
ASSERT_TRUE(fsl::VmoFromString("minidump", &minidump_vmo));
builder_.SetMinidump(std::move(minidump_vmo.vmo()))
.SetExceptionReason(ExceptionReason::kPageFaultIoDataIntegrity);
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_crash_signature());
EXPECT_EQ(crash_report.crash_signature(), "fuchsia-page_fault-io_data_integrity");
}
TEST_F(CrashReportBuilderTest, ExceptionReason_PageFaultBadState) {
fsl::SizedVmo minidump_vmo;
ASSERT_TRUE(fsl::VmoFromString("minidump", &minidump_vmo));
builder_.SetMinidump(std::move(minidump_vmo.vmo()))
.SetExceptionReason(ExceptionReason::kPageFaultBadState);
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_crash_signature());
EXPECT_EQ(crash_report.crash_signature(), "fuchsia-page_fault-bad_state");
}
TEST_F(CrashReportBuilderTest, ProcessTerminated) {
builder_.SetProcessTerminated();
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_specific_report());
ASSERT_TRUE(crash_report.has_program_name());
ASSERT_EQ(crash_report.program_name(), "unknown_process");
ASSERT_FALSE(crash_report.has_program_uptime());
ASSERT_TRUE(crash_report.specific_report().is_native());
EXPECT_FALSE(crash_report.specific_report().native().has_minidump());
ASSERT_TRUE(crash_report.has_crash_signature());
EXPECT_EQ(crash_report.crash_signature(), "fuchsia-no-minidump-process-terminated");
}
TEST_F(CrashReportBuilderTest, ExpiredException) {
builder_.SetExceptionExpired();
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_specific_report());
ASSERT_TRUE(crash_report.specific_report().is_native());
EXPECT_FALSE(crash_report.specific_report().native().has_minidump());
ASSERT_TRUE(crash_report.has_crash_signature());
EXPECT_EQ(crash_report.crash_signature(), "fuchsia-no-minidump-exception-expired");
}
TEST_F(CrashReportBuilderTest, IsFatal) {
builder_.SetExceptionExpired();
auto crash_report = builder_.Consume();
ASSERT_TRUE(crash_report.has_is_fatal());
EXPECT_TRUE(crash_report.is_fatal());
}
TEST(ReportBuilderTest, TestUptime) {
CrashReportBuilder builder;
ExceptionContext exception;
// Spawn the 'crasher' process.
ASSERT_TRUE(SpawnCrasher(&exception));
// If we don't mark it as handled, the exception will bubble out of our environment.
ASSERT_TRUE(MarkExceptionAsHandled(&exception));
zx::process process;
zx::thread thread;
ASSERT_EQ(exception.exception.get_process(&process), ZX_OK);
ASSERT_EQ(exception.exception.get_thread(&thread), ZX_OK);
builder.SetProcess(process).SetThread(thread);
builder.SetProcessTerminated();
auto crash_report = builder.Consume();
ASSERT_TRUE(crash_report.has_program_name());
ASSERT_EQ(crash_report.program_name(), "crasher");
ASSERT_TRUE(crash_report.has_program_uptime());
ASSERT_GE(crash_report.program_uptime(), 0);
// We kill the jobs. This kills the underlying process. We do this so that the crashed process
// doesn't get rescheduled. Otherwise the exception on the crash program would bubble out of our
// environment and create noise on the overall system.
exception.job.kill();
}
} // namespace
} // namespace handler
} // namespace exceptions
} // namespace forensics