blob: 8b462ffefcd12a9783e965ba438f32928f9fda70 [file] [log] [blame]
// Copyright 2019 The Chromium OS 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 "crash-reporter/anomaly_detector.h"
#include <base/files/file_path.h>
#include <base/optional.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/message.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "crash-reporter/anomaly_detector_test_utils.h"
namespace {
using ::testing::_;
using ::testing::Eq;
using ::testing::IsEmpty;
using ::testing::Return;
using ::anomaly::KernelParser;
using ::anomaly::ParserRun;
using ::anomaly::ParserTest;
using ::anomaly::SELinuxParser;
using ::anomaly::ServiceParser;
using ::anomaly::SuspendParser;
using ::anomaly::TerminaParser;
const ParserRun simple_run;
const ParserRun empty{.expected_size = 0};
} // namespace
TEST(AnomalyDetectorTest, KernelWarning) {
ParserRun second{
.find_this = "ttm_bo_vm.c",
.replace_with = "file_one.c",
.expected_text = "0x19e/0x1ab [ttm]()\n[ 3955.309298] Modules linked in"};
ParserTest<KernelParser>("TEST_WARNING", {simple_run, second});
}
TEST(AnomalyDetectorTest, KernelWarningNoDuplicate) {
ParserRun identical_warning{.expected_size = 0};
ParserTest<KernelParser>("TEST_WARNING", {simple_run, identical_warning});
}
TEST(AnomalyDetectorTest, KernelWarningHeader) {
ParserRun warning_message{.expected_text = "Test Warning message asdfghjkl"};
ParserTest<KernelParser>("TEST_WARNING_HEADER", {warning_message});
}
TEST(AnomalyDetectorTest, KernelWarningOld) {
ParserTest<KernelParser>("TEST_WARNING_OLD", {simple_run});
}
TEST(AnomalyDetectorTest, KernelWarningOldARM64) {
ParserRun unknown_function{.expected_text = "-unknown-function\n"};
ParserTest<KernelParser>("TEST_WARNING_OLD_ARM64", {unknown_function});
}
TEST(AnomalyDetectorTest, KernelWarningWifi) {
ParserRun wifi_warning = {.find_this = "gpu/drm/ttm",
.replace_with = "net/wireless",
.expected_flags = {{"--kernel_wifi_warning"}}};
ParserTest<KernelParser>("TEST_WARNING", {wifi_warning});
}
TEST(AnomalyDetectorTest, KernelWarningSuspend) {
ParserRun suspend_warning = {
.find_this = "gpu/drm/ttm",
.replace_with = "idle",
.expected_flags = {{"--kernel_suspend_warning"}}};
ParserTest<KernelParser>("TEST_WARNING", {suspend_warning});
}
TEST(AnomalyDetectorTest, CrashReporterCrash) {
ParserRun crash_reporter_crash = {
.expected_flags = {{"--crash_reporter_crashed"}}};
ParserTest<KernelParser>("TEST_CR_CRASH", {crash_reporter_crash});
}
TEST(AnomalyDetectorTest, CrashReporterCrashRateLimit) {
ParserRun crash_reporter_crash = {
.expected_flags = {{"--crash_reporter_crashed"}}};
ParserTest<KernelParser>("TEST_CR_CRASH",
{crash_reporter_crash, empty, empty});
}
TEST(AnomalyDetectorTest, ServiceFailure) {
ParserRun one{.expected_text = "-exit2-"};
ParserRun two{.find_this = "crash-crash", .replace_with = "fresh-fresh"};
ServiceParser parser(true);
ParserTest("TEST_SERVICE_FAILURE", {one, two}, &parser);
}
TEST(AnomalyDetectorTest, ServiceFailureArc) {
ParserRun service_failure = {
.find_this = "crash-crash",
.replace_with = "arc-crash",
.expected_text = "-exit2-arc-",
.expected_flags = {{"--arc_service_failure=arc-crash"}}};
ServiceParser parser(true);
ParserTest("TEST_SERVICE_FAILURE", {service_failure}, &parser);
}
TEST(AnomalyDetectorTest, SELinuxViolation) {
ParserRun selinux_violation = {
.expected_text =
"-selinux-u:r:init:s0-u:r:kernel:s0-module_request-init-",
.expected_flags = {{"--selinux_violation"}}};
SELinuxParser parser(true);
ParserTest("TEST_SELINUX", {selinux_violation}, &parser);
}
TEST(AnomalyDetectorTest, SELinuxViolationPermissive) {
ParserRun selinux_violation = {.find_this = "permissive=0",
.replace_with = "permissive=1",
.expected_size = 0};
SELinuxParser parser(true);
ParserTest("TEST_SELINUX", {selinux_violation}, &parser);
}
TEST(AnomalyDetectorTest, SuspendFailure) {
ParserRun suspend_failure = {
.expected_text =
"-suspend failure: device: dummy_dev step: suspend errno: -22",
.expected_flags = {{"--suspend_failure"}}};
ParserTest<SuspendParser>("TEST_SUSPEND_FAILURE", {suspend_failure});
}
MATCHER_P2(SignalEq, interface, member, "") {
return (arg->GetInterface() == interface && arg->GetMember() == member);
}
TEST(AnomalyDetectorTest, BTRFSExtentCorruption) {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<dbus::MockBus> bus = new dbus::MockBus(options);
auto obj_path = dbus::ObjectPath(anomaly_detector::kAnomalyEventServicePath);
scoped_refptr<dbus::MockExportedObject> exported_object =
new dbus::MockExportedObject(bus.get(), obj_path);
EXPECT_CALL(*bus, GetExportedObject(Eq(obj_path)))
.WillOnce(Return(exported_object.get()));
EXPECT_CALL(*exported_object,
SendSignal(SignalEq(
anomaly_detector::kAnomalyEventServiceInterface,
anomaly_detector::kAnomalyGuestFileCorruptionSignalName)))
.Times(1);
TerminaParser parser(bus);
parser.ParseLogEntry(
"VM(3)",
"BTRFS warning (device vdb): csum failed root 5 ino 257 off 409600 csum "
"0x76ad9387 expected csum 0xd8d34542 mirror 1");
}
TEST(AnomalyDetectorTest, BTRFSTreeCorruption) {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<dbus::MockBus> bus = new dbus::MockBus(options);
auto obj_path = dbus::ObjectPath(anomaly_detector::kAnomalyEventServicePath);
scoped_refptr<dbus::MockExportedObject> exported_object =
new dbus::MockExportedObject(bus.get(), obj_path);
EXPECT_CALL(*bus, GetExportedObject(Eq(obj_path)))
.WillOnce(Return(exported_object.get()));
EXPECT_CALL(*exported_object,
SendSignal(SignalEq(
anomaly_detector::kAnomalyEventServiceInterface,
anomaly_detector::kAnomalyGuestFileCorruptionSignalName)))
.Times(1);
TerminaParser parser(bus);
parser.ParseLogEntry("VM(3)",
"BTRFS warning (device vdb): vdb checksum verify failed "
"on 122798080 wanted 4E5B4C99 found 5F261FEB level 0");
}