blob: 0fe9dd3e20a292b02aa37cd9c09884d98a825287 [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 <memory>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/windows_version.h"
#include "chrome/chrome_cleaner/crash/crash_client.h"
#include "chrome/chrome_cleaner/ipc/sandbox.h"
#include "chrome/chrome_cleaner/logging/scoped_logging.h"
#include "chrome/chrome_cleaner/os/rebooter.h"
#include "chrome/chrome_cleaner/os/secure_dll_loading.h"
#include "chrome/chrome_cleaner/os/system_util_cleaner.h"
#include "chrome/chrome_cleaner/os/task_scheduler.h"
#include "chrome/chrome_cleaner/settings/settings_types.h"
#include "chrome/chrome_cleaner/test/test_util.h"
#include "sandbox/win/src/sandbox_factory.h"
namespace {
bool IsSandboxedProcess() {
static const bool is_sandboxed_process =
(sandbox::SandboxFactory::GetTargetServices() != nullptr);
return is_sandboxed_process;
}
// base::TestSuite's Initialize method initializes logging differently than we
// do. This subclass ensures logging is properly initialized using ScopedLogging
// after base::TestSuite::Initialize has run.
class ChromeCleanerTestSuite : public base::TestSuite {
public:
// Inherit constructors.
using base::TestSuite::TestSuite;
protected:
void Initialize() override {
base::TestSuite::Initialize();
scoped_logging.reset(new chrome_cleaner::ScopedLogging(
IsSandboxedProcess() ? chrome_cleaner::kSandboxLogFileSuffix
: nullptr));
}
private:
std::unique_ptr<chrome_cleaner::ScopedLogging> scoped_logging;
};
} // namespace
namespace chrome_cleaner {
// Gives each test executable a chance to modify |command_line|. Each
// executable must link with exactly one implementation of this.
void OverrideTestCommandLine(base::CommandLine* command_line);
} // namespace chrome_cleaner
int main(int argc, char** argv) {
// This must be executed as soon as possible to reduce the number of dlls that
// the code might try to load before we can lock things down.
//
// We enable secure DLL loading in the test suite to be sure that it doesn't
// affect the behaviour of functionality that's tested.
chrome_cleaner::EnableSecureDllLoading();
ChromeCleanerTestSuite test_suite(argc, argv);
if (!chrome_cleaner::SetupTestConfigs())
return 1;
if (!chrome_cleaner::CheckTestPrivileges())
return 1;
// Make sure tests will not end up in an infinite reboot loop.
if (chrome_cleaner::Rebooter::IsPostReboot())
return 0;
chrome_cleaner::OverrideTestCommandLine(
base::CommandLine::ForCurrentProcess());
// ScopedCOMInitializer keeps COM initialized in a specific scope. We don't
// want to initialize it for sandboxed processes, so manage its lifetime with
// a unique_ptr, which will call ScopedCOMInitializer's destructor when it
// goes out of scope below.
std::unique_ptr<base::win::ScopedCOMInitializer> scoped_com_initializer;
if (!IsSandboxedProcess()) {
scoped_com_initializer = std::make_unique<base::win::ScopedCOMInitializer>(
base::win::ScopedCOMInitializer::kMTA);
bool success = chrome_cleaner::InitializeCOMSecurity();
DCHECK(success) << "InitializeCOMSecurity() failed.";
success = chrome_cleaner::TaskScheduler::Initialize();
DCHECK(success) << "TaskScheduler::Initialize() failed.";
// Crash reporting must be initialized only once, so it cannot be
// initialized by individual tests or fixtures. Also, since crashpad does
// not actually enable uploading of crash reports in non-official builds
// (unless forced to by the --enable-crash-reporting flag) we don't need to
// disable crash reporting.
chrome_cleaner::CrashClient::GetInstance()->InitializeCrashReporting(
chrome_cleaner::CrashClient::Mode::CLEANER,
chrome_cleaner::SandboxType::kNonSandboxed);
}
// Some tests spawn sandbox targets using job objects. Windows 7 doesn't
// support nested job objects, so don't use them in the test suite. Otherwise
// all sandbox tests will fail as they try to create a second job object.
bool use_job_objects = base::win::GetVersion() >= base::win::VERSION_WIN8;
// Some tests will fail if two tests try to launch test_process.exe
// simultaneously, so run the tests serially. This will still shard them and
// distribute the shards to different swarming bots, but tests will run
// serially on each bot.
const int result = base::LaunchUnitTestsWithOptions(
argc, argv,
/*parallel_jobs=*/1U, // Like LaunchUnitTestsSerially
/*default_batch_limit=*/10, // Like LaunchUnitTestsSerially
use_job_objects,
base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
if (!IsSandboxedProcess())
chrome_cleaner::TaskScheduler::Terminate();
return result;
}