blob: 5ebc8b33944bf3484abcbe291ec56c7405344918 [file] [log] [blame]
// Copyright 2018 The Chromium 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 "chrome/chrome_cleaner/logging/reporter_logging_service.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "chrome/chrome_cleaner/http/http_agent_factory.h"
#include "chrome/chrome_cleaner/http/mock_http_agent_factory.h"
#include "chrome/chrome_cleaner/logging/proto/reporter_logs.pb.h"
#include "chrome/chrome_cleaner/logging/safe_browsing_reporter.h"
#include "chrome/chrome_cleaner/logging/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chrome_cleaner {
namespace {
constexpr UwSId kDefaultUwSId = 1;
void NoSleep(base::TimeDelta) {}
PUPData::PUP CreateSimpleDetectedPUP() {
// Use a static signature object so that it will outlive any PUP object
// pointing to it.
static PUPData::UwSSignature signature{kDefaultUwSId,
PUPData::FLAGS_STATE_CONFIRMED_UWS,
/*name=*/"This is nasty"};
return PUPData::PUP(&signature);
}
} // namespace
class ReporterLoggingServiceTest : public testing::Test {
public:
ReporterLoggingServiceTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
// LoggingServiceAPI::UploadResultCallback implementation.
void LoggingServiceDone(base::OnceClosure run_loop_quit, bool success) {
done_callback_called_ = true;
upload_success_ = success;
// A RunLoop will be waiting for this callback to run before proceeding
// with the test. Now that the callback has run, we can quit the RunLoop.
std::move(run_loop_quit).Run();
}
void SetUp() override {
registry_logger_.reset(new RegistryLogger(RegistryLogger::Mode::REPORTER));
reporter_logging_service_ = ReporterLoggingService::GetInstance();
reporter_logging_service_->Initialize(registry_logger_.get());
done_callback_called_ = false;
upload_success_ = false;
// Use a mock HttpAgent instead of making real network requests.
SafeBrowsingReporter::SetHttpAgentFactoryForTesting(
http_agent_factory_.get());
SafeBrowsingReporter::SetSleepCallbackForTesting(
base::BindRepeating(&NoSleep));
SafeBrowsingReporter::SetNetworkCheckerForTesting(&network_checker_);
}
void TearDown() override { reporter_logging_service_->Terminate(); }
// Sends logs to Safe Browsing, and waits for LoggingServiceDone to be called
// before returning.
void DoSendLogsToSafeBrowsing() {
base::RunLoop run_loop;
reporter_logging_service_->SendLogsToSafeBrowsing(
base::BindRepeating(&ReporterLoggingServiceTest::LoggingServiceDone,
base::Unretained(this), run_loop.QuitClosure()),
registry_logger_.get());
run_loop.Run();
}
LoggingServiceAPI* reporter_logging_service_;
// Needed for the current task runner to be available.
base::test::ScopedTaskEnvironment scoped_task_environment_;
// |done_callback_called_| is set to true in |LoggingServiceDone| to confirm
// it was called appropriately.
bool done_callback_called_;
// Set with the value given to the done callback.
bool upload_success_;
std::unique_ptr<RegistryLogger> registry_logger_;
MockHttpAgentConfig http_agent_config_;
std::unique_ptr<HttpAgentFactory> http_agent_factory_{
std::make_unique<MockHttpAgentFactory>(&http_agent_config_)};
MockNetworkChecker network_checker_;
};
TEST_F(ReporterLoggingServiceTest, Disabled) {
reporter_logging_service_->EnableUploads(false, registry_logger_.get());
DoSendLogsToSafeBrowsing();
// No URLRequest should have been made when not enabled.
EXPECT_EQ(0UL, http_agent_config_.num_request_data());
// But the done callback should have been called.
EXPECT_TRUE(done_callback_called_);
// With a failure.
EXPECT_FALSE(upload_success_);
}
TEST_F(ReporterLoggingServiceTest, Empty) {
reporter_logging_service_->EnableUploads(true, registry_logger_.get());
DoSendLogsToSafeBrowsing();
// No URLRequest should have been made when there is nothing to report.
EXPECT_EQ(0UL, http_agent_config_.num_request_data());
// But the done callback should have been called.
EXPECT_TRUE(done_callback_called_);
// With a failure.
EXPECT_FALSE(upload_success_);
}
TEST_F(ReporterLoggingServiceTest, ExitCodeNotSet) {
reporter_logging_service_->EnableUploads(true, registry_logger_.get());
// Adding UwS data, but exit code is not set.
PUPData::PUP pup = CreateSimpleDetectedPUP();
reporter_logging_service_->AddDetectedUwS(&pup, kUwSDetectedFlagsNone);
DoSendLogsToSafeBrowsing();
// No URLRequest should have been made when the exit code has not been set.
EXPECT_EQ(0UL, http_agent_config_.num_request_data());
// But the done callback should have been called.
EXPECT_TRUE(done_callback_called_);
// With a failure.
EXPECT_FALSE(upload_success_);
}
TEST_F(ReporterLoggingServiceTest, NoUwSFound) {
reporter_logging_service_->EnableUploads(true, registry_logger_.get());
reporter_logging_service_->SetExitCode(RESULT_CODE_NO_PUPS_FOUND);
MockHttpAgentConfig::Calls calls(HttpStatus::kOk);
ChromeFoilResponse response;
response.SerializeToString(&calls.read_data_result);
http_agent_config_.AddCalls(calls);
DoSendLogsToSafeBrowsing();
// No URLRequest should have been made when no UwS was found.
EXPECT_EQ(0UL, http_agent_config_.num_request_data());
// But the done callback should have been called.
EXPECT_TRUE(done_callback_called_);
// With a failure.
EXPECT_FALSE(upload_success_);
}
TEST_F(ReporterLoggingServiceTest, BothExitCodeSetAndUwSDetected) {
reporter_logging_service_->EnableUploads(true, registry_logger_.get());
// Set the exit code and add detected UwS.
reporter_logging_service_->SetExitCode(RESULT_CODE_EXAMINED_FOR_REMOVAL_ONLY);
PUPData::PUP pup = CreateSimpleDetectedPUP();
reporter_logging_service_->AddDetectedUwS(&pup, kUwSDetectedFlagsNone);
MockHttpAgentConfig::Calls calls(HttpStatus::kOk);
ChromeFoilResponse response;
response.SerializeToString(&calls.read_data_result);
http_agent_config_.AddCalls(calls);
DoSendLogsToSafeBrowsing();
// One URLRequest should have been made.
EXPECT_EQ(1UL, http_agent_config_.num_request_data());
// The done callback should have been called.
EXPECT_TRUE(done_callback_called_);
// With success.
EXPECT_TRUE(upload_success_);
std::string upload_data(http_agent_config_.request_data(0).body);
FoilReporterLogs reporter_logs;
ASSERT_TRUE(reporter_logs.ParseFromString(upload_data));
EXPECT_EQ(RESULT_CODE_EXAMINED_FOR_REMOVAL_ONLY,
static_cast<chrome_cleaner::ResultCode>(reporter_logs.exit_code()));
ASSERT_EQ(1, reporter_logs.detected_uws_size());
const UwS& uws = reporter_logs.detected_uws(0);
EXPECT_EQ(pup.signature().id, uws.id());
EXPECT_EQ(pup.signature().name, uws.name());
EXPECT_EQ(UwS::REPORT_ONLY, uws.state());
EXPECT_FALSE(uws.detail_level().only_one_footprint());
// TODO Add tests for matched files, folders, registry entries,
// and scheduled tasks, once the corresponding utility functions have been
// moved from logging_service_unittest.cc to a shared lib.
}
TEST_F(ReporterLoggingServiceTest, AddDetectedUwS) {
UwS uws;
uws.set_id(kDefaultUwSId);
reporter_logging_service_->AddDetectedUwS(uws);
FoilReporterLogs report;
ASSERT_TRUE(
report.ParseFromString(reporter_logging_service_->RawReportContent()));
ASSERT_EQ(1, report.detected_uws_size());
ASSERT_EQ(kDefaultUwSId, report.detected_uws(0).id());
}
TEST_F(ReporterLoggingServiceTest, LogProcessInformation) {
base::IoCounters io_counters;
io_counters.ReadOperationCount = 1;
io_counters.WriteOperationCount = 2;
io_counters.OtherOperationCount = 3;
io_counters.ReadTransferCount = 4;
io_counters.WriteTransferCount = 5;
io_counters.OtherTransferCount = 6;
SystemResourceUsage usage = {io_counters, base::TimeDelta::FromSeconds(10),
base::TimeDelta::FromSeconds(20), 123456};
reporter_logging_service_->LogProcessInformation(SandboxType::kEset, usage);
FoilReporterLogs report;
ASSERT_TRUE(
report.ParseFromString(reporter_logging_service_->RawReportContent()));
ASSERT_EQ(1, report.process_information_size());
EXPECT_EQ(ProcessInformation::ESET_SANDBOX,
report.process_information(0).process());
ProcessInformation::SystemResourceUsage usage_msg =
report.process_information(0).resource_usage();
EXPECT_TRUE(IoCountersEqual(io_counters, usage_msg));
EXPECT_EQ(10U, usage_msg.user_time());
EXPECT_EQ(20U, usage_msg.kernel_time());
EXPECT_EQ(123456U, usage_msg.peak_working_set_size());
}
} // namespace chrome_cleaner