blob: d8eafe88273171787a70497c552d4a98dd72e8e3 [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include "base/command_line.h"
#include "base/memory/discardable_memory_allocator.h"
#include "base/test/launcher/test_launcher.h"
#include "base/test/test_discardable_memory_allocator.h"
#include "base/test/test_switches.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/ssl/https_upgrades_navigation_throttle.h"
#include "chrome/test/base/chrome_test_launcher.h"
#include "chrome/test/base/chrome_test_suite.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "content/public/common/content_switches.h"
#include "gpu/ipc/service/image_transport_surface.h"
#include "ui/base/interaction/interactive_test_internal.h"
#include "ui/base/test/ui_controls.h"
#include "ui/compositor/compositor_switches.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "ash/test/ui_controls_ash.h"
#elif BUILDFLAG(IS_WIN)
#include "ui/aura/test/ui_controls_aurawin.h"
#endif
#if defined(USE_AURA) && BUILDFLAG(IS_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#include "ui/platform_window/common/platform_window_defaults.h"
#endif // defined(USE_AURA) && BUILDFLAG(IS_OZONE)
#if BUILDFLAG(IS_WIN)
#include "base/win/scoped_com_initializer.h"
#include "base/win/win_util.h"
#include "chrome/test/base/always_on_top_window_killer_win.h"
#endif
class InteractiveUITestSuite : public ChromeTestSuite {
public:
InteractiveUITestSuite(int argc, char** argv) : ChromeTestSuite(argc, argv) {}
~InteractiveUITestSuite() override = default;
protected:
// ChromeTestSuite overrides:
void Initialize() override {
ChromeTestSuite::Initialize();
#if BUILDFLAG(IS_CHROMEOS)
ash::test::EnableUIControlsAsh();
#elif BUILDFLAG(IS_WIN)
com_initializer_ = std::make_unique<base::win::ScopedCOMInitializer>();
aura::test::EnableUIControlsAuraWin();
#elif BUILDFLAG(IS_OZONE)
// Notifies the platform that test config is needed. For Wayland, for
// example, makes it possible to use emulated input.
ui::test::EnableTestConfigForPlatformWindows();
ui::OzonePlatform::InitParams params;
params.single_process = true;
ui::OzonePlatform::InitializeForUI(params);
ui_controls::EnableUIControls();
#else
ui_controls::EnableUIControls();
#endif
// Allow interactive Kombucha test verbs in interactive UI tests.
ui::test::internal::InteractiveTestPrivate::
set_interactive_test_verbs_allowed(
base::PassKey<InteractiveUITestSuite>());
// TODO(crbug.com/40263135) Investigate why https upgrade causes
// interactive_ui_tests to run longer.
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
// Force the HTTPS-Upgrades timeout to zero.
HttpsUpgradesNavigationThrottle::set_timeout_for_testing(base::TimeDelta());
#endif
base::DiscardableMemoryAllocator::SetInstance(
&discardable_memory_allocator_);
}
void Shutdown() override {
#if BUILDFLAG(IS_WIN)
com_initializer_.reset();
#endif
}
private:
#if BUILDFLAG(IS_WIN)
std::unique_ptr<base::win::ScopedCOMInitializer> com_initializer_;
#endif
base::TestDiscardableMemoryAllocator discardable_memory_allocator_;
};
class InteractiveUITestLauncherDelegate : public ChromeTestLauncherDelegate {
public:
explicit InteractiveUITestLauncherDelegate(ChromeTestSuiteRunner* runner)
: ChromeTestLauncherDelegate(runner) {}
InteractiveUITestLauncherDelegate(const InteractiveUITestLauncherDelegate&) =
delete;
InteractiveUITestLauncherDelegate& operator=(
const InteractiveUITestLauncherDelegate&) = delete;
protected:
// content::TestLauncherDelegate:
void PreSharding() override {
ChromeTestLauncherDelegate::PreSharding();
#if BUILDFLAG(IS_WIN)
// Check for any always-on-top windows present before any tests are run.
// Take a snapshot if any are found and attempt to close any that are system
// dialogs.
KillAlwaysOnTopWindows(RunType::BEFORE_SHARD);
#endif
}
void OnTestTimedOut(const base::CommandLine& command_line) override {
#if BUILDFLAG(IS_WIN)
// Take a snapshot of the screen and check for any always-on-top windows
// present before terminating the test. Attempt to close any that are system
// dialogs.
KillAlwaysOnTopWindows(RunType::AFTER_TEST_TIMEOUT, &command_line);
#endif
ChromeTestLauncherDelegate::OnTestTimedOut(command_line);
}
#if BUILDFLAG(IS_MAC)
void PreRunTest() override {
// Clear currently pressed modifier keys (if any) before the test starts.
ui_test_utils::ClearKeyEventModifiers();
}
void PostRunTest(base::TestResult* test_result) override {
// Clear currently pressed modifier keys (if any) after the test finishes
// and report an error if there were some.
bool had_hanging_modifiers = ui_test_utils::ClearKeyEventModifiers();
if (had_hanging_modifiers &&
test_result->status == base::TestResult::TEST_SUCCESS) {
test_result->status = base::TestResult::TEST_FAILURE_ON_EXIT;
}
ChromeTestLauncherDelegate::PostRunTest(test_result);
}
#endif // BUILDFLAG(IS_MAC)
};
class InteractiveUITestSuiteRunner : public ChromeTestSuiteRunner {
public:
int RunTestSuite(int argc, char** argv) override {
InteractiveUITestSuite test_suite(argc, argv);
return RunTestSuiteInternal(&test_suite);
}
};
int main(int argc, char** argv) {
base::CommandLine::Init(argc, argv);
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
#if BUILDFLAG(IS_CHROMEOS) && defined(MEMORY_SANITIZER)
// Force software-gl. This is necessary for mus tests to avoid an msan warning
// in gl init.
command_line->AppendSwitch(switches::kOverrideUseSoftwareGLForTests);
#endif
// Without this it's possible for the first browser to start up in the
// background, generally because the last test did something that causes the
// test to run in the background. Most interactive ui tests assume they are in
// the foreground and fail in weird ways if they aren't (for example, clicks
// go to the wrong place). This ensures the first browser is always in the
// foreground.
InProcessBrowserTest::set_global_browser_set_up_function(
&ui_test_utils::BringBrowserWindowToFront);
#if BUILDFLAG(IS_WIN)
base::win::EnableHighDPISupport();
#endif // BUILDFLAG(IS_WIN)
// For ash chrome, it's using multiple X11 windows to host the browser.
// Also, {emulating|injecting} keyboard and mouse events happen at ozone
// level, not OS level. So it is fine to run tests in parallel.
#if BUILDFLAG(IS_CHROMEOS)
size_t parallel_jobs = base::NumParallelJobs(/*cores_per_job=*/2);
if (parallel_jobs == 0) {
parallel_jobs = 1;
}
#else
// Run interactive_ui_tests serially, they do not support running in parallel.
size_t parallel_jobs = 1;
#endif
// Adjust switches for interactive tests where the user is expected to
// manually verify results.
if (command_line->HasSwitch(switches::kTestLauncherInteractive)) {
// Since the test is interactive, the invoker will want to have pixel output
// to actually see the result.
command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
#if BUILDFLAG(IS_WIN)
// Under Windows, dialogs (but not the browser window) created in the
// spawned browser_test process are invisible for some unknown reason.
// Pass in --disable-gpu to resolve this for now. See
// http://crbug.com/687387.
command_line->AppendSwitch(switches::kDisableGpu);
#endif // BUILDFLAG(IS_WIN)
}
InteractiveUITestSuiteRunner runner;
InteractiveUITestLauncherDelegate delegate(&runner);
return LaunchChromeTests(parallel_jobs, &delegate, argc, argv);
}