// Copyright (c) 2011 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. #ifndef CHROME_TEST_IN_PROCESS_BROWSER_TEST_H_ #define CHROME_TEST_IN_PROCESS_BROWSER_TEST_H_ #pragma once #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/scoped_temp_dir.h" #include "content/common/page_transition_types.h" #include "net/test/test_server.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/cros/cros_library.h" #endif // defined(OS_CHROMEOS) class Browser; class CommandLine; class Profile; namespace content { class ContentRendererClient; } namespace net { class RuleBasedHostResolverProc; } // Base class for tests wanting to bring up a browser in the unit test process. // Writing tests with InProcessBrowserTest is slightly different than that of // other tests. This is necessitated by InProcessBrowserTest running a message // loop. To use InProcessBrowserTest do the following: // . Use the macro IN_PROC_BROWSER_TEST_F to define your test. // . Your test method is invoked on the ui thread. If you need to block until // state changes you'll need to run the message loop from your test method. // For example, if you need to wait till a find bar has completely been shown // you'll need to invoke ui_test_utils::RunMessageLoop. When the message bar // is shown, invoke MessageLoop::current()->Quit() to return control back to // your test method. // . If you subclass and override SetUp, be sure and invoke // InProcessBrowserTest::SetUp. (But see also SetUpOnMainThread, // SetUpInProcessBrowserTestFixture and other related hook methods for a // cleaner alternative). // // Following three hook methods are called in sequence before calling // BrowserMain(), thus no browser has been created yet. They are mainly for // setting up the environment for running the browser. // . SetUpUserDataDirectory() // . SetUpCommandLine() // . SetUpInProcessBrowserTestFixture() // // SetUpOnMainThread() is called just after creating the default browser object // and before executing the real test code. It's mainly for setting up things // related to the browser object and associated window, like opening a new Tab // with a testing page loaded. // // CleanUpOnMainThread() is called just after executing the real test code to // do necessary cleanup before the browser is torn down. // // TearDownInProcessBrowserTestFixture() is called after BrowserMain() exits to // cleanup things setup for running the browser. // // By default InProcessBrowserTest creates a single Browser (as returned from // the CreateBrowser method). You can obviously create more as needed. // Browsers created while InProcessBrowserTest is running are shown hidden. Use // the command line switch --show-windows to make them visible when debugging. // // InProcessBrowserTest disables the sandbox when running. // // See ui_test_utils for a handful of methods designed for use with this class. class InProcessBrowserTest : public testing::Test { public: InProcessBrowserTest(); virtual ~InProcessBrowserTest(); // We do this so we can be used in a Task. void AddRef() {} void Release() {} static bool ImplementsThreadSafeReferenceCounting() { return false; } // Configures everything for an in process browser test, then invokes // BrowserMain. BrowserMain ends up invoking RunTestOnMainThreadLoop. virtual void SetUp(); // Restores state configured in SetUp. virtual void TearDown(); protected: // Returns the browser created by CreateBrowser. Browser* browser() const { return browser_; } // Convenience methods for adding tabs to a Browser. void AddTabAtIndexToBrowser(Browser* browser, int index, const GURL& url, PageTransition::Type transition); void AddTabAtIndex(int index, const GURL& url, PageTransition::Type transition); // Adds a selected tab at |index| to |url| with the specified |transition|. void AddTabAt(int index, const GURL& url, PageTransition::Type transition); // Override this to add any custom setup code that needs to be done on the // main thread after the browser is created and just before calling // RunTestOnMainThread(). virtual void SetUpOnMainThread() {} // Override this rather than TestBody. virtual void RunTestOnMainThread() = 0; // Initializes the contents of the user data directory. Called by SetUp() // after creating the user data directory, but before any browser is launched. // If a test wishes to set up some initial non-empty state in the user data // directory before the browser starts up, it can do so here. Returns true if // successful. virtual bool SetUpUserDataDirectory() WARN_UNUSED_RESULT; // We need these special methods because InProcessBrowserTest::SetUp is the // bottom of the stack that winds up calling your test method, so it is not // always an option to do what you want by overriding it and calling the // superclass version. // // Override this for things you would normally override SetUp for. It will be // called before your individual test fixture method is run, but after most // of the overhead initialization has occured. virtual void SetUpInProcessBrowserTestFixture() {} // Override this for things you would normally override TearDown for. virtual void TearDownInProcessBrowserTestFixture() {} // Override this to add command line flags specific to your test. virtual void SetUpCommandLine(CommandLine* command_line) {} // Override this to add any custom cleanup code that needs to be done on the // main thread before the browser is torn down. virtual void CleanUpOnMainThread() {} // Returns the testing server. Guaranteed to be non-NULL. net::TestServer* test_server() { return test_server_.get(); } // Creates a browser with a single tab (about:blank), waits for the tab to // finish loading and shows the browser. // // This is invoked from Setup. virtual Browser* CreateBrowser(Profile* profile); // Similar to |CreateBrowser|, but creates an incognito browser. virtual Browser* CreateIncognitoBrowser(); // Creates a browser for a popup window with a single tab (about:blank), waits // for the tab to finish loading, and shows the browser. Browser* CreateBrowserForPopup(Profile* profile); // Returns the host resolver being used for the tests. Subclasses might want // to configure it inside tests. net::RuleBasedHostResolverProc* host_resolver() { return host_resolver_.get(); } // Sets some test states (see below for comments). Call this in your test // constructor. void set_show_window(bool show) { show_window_ = show; } void EnableDOMAutomation() { dom_automation_enabled_ = true; } void EnableTabCloseableStateWatcher() { tab_closeable_state_watcher_enabled_ = true; } private: // Creates a user data directory for the test if one is needed. Returns true // if successful. virtual bool CreateUserDataDirectory() WARN_UNUSED_RESULT; // This is invoked from main after browser_init/browser_main have completed. // This prepares for the test by creating a new browser, runs the test // (RunTestOnMainThread), quits the browsers and returns. void RunTestOnMainThreadLoop(); // Quits all open browsers and waits until there are no more browsers. void QuitBrowsers(); // Prepare command line that will be used to launch the child browser process // with an in-process test. void PrepareTestCommandLine(CommandLine* command_line); // Browser created from CreateBrowser. Browser* browser_; // Testing server, started on demand. scoped_ptr test_server_; // ContentRendererClient when running in single-process mode. scoped_ptr single_process_renderer_client_; // Whether this test requires the browser windows to be shown (interactive // tests for example need the windows shown). bool show_window_; // Whether the JavaScript can access the DOMAutomationController (a JS object // that can send messages back to the browser). bool dom_automation_enabled_; // Whether this test requires the TabCloseableStateWatcher. bool tab_closeable_state_watcher_enabled_; // Host resolver to use during the test. scoped_refptr host_resolver_; // Temporary user data directory. Used only when a user data directory is not // specified in the command line. ScopedTempDir temp_user_data_dir_; #if defined(OS_CHROMEOS) chromeos::ScopedStubCrosEnabler stub_cros_enabler_; #endif // defined(OS_CHROMEOS) DISALLOW_COPY_AND_ASSIGN(InProcessBrowserTest); }; // We only want to use InProcessBrowserTest in test targets which properly // isolate each test case by running each test in a separate process. // This way if a test hangs the test launcher can reliably terminate it. // // InProcessBrowserTest cannot be run more than once in the same address space // anyway - otherwise the second test crashes. #if defined(HAS_OUT_OF_PROC_TEST_RUNNER) #define IN_PROC_BROWSER_TEST_(test_case_name, test_name, parent_class,\ parent_id)\ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ public:\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ protected:\ virtual void RunTestOnMainThread();\ private:\ virtual void TestBody() {}\ static ::testing::TestInfo* const test_info_;\ GTEST_DISALLOW_COPY_AND_ASSIGN_(\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ };\ \ ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ ::test_info_ =\ ::testing::internal::MakeAndRegisterTestInfo(\ #test_case_name, #test_name, "", "", \ (parent_id), \ parent_class::SetUpTestCase, \ parent_class::TearDownTestCase, \ new ::testing::internal::TestFactoryImpl<\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::RunTestOnMainThread() #define IN_PROC_BROWSER_TEST_F(test_fixture, test_name)\ IN_PROC_BROWSER_TEST_(test_fixture, test_name, test_fixture,\ ::testing::internal::GetTypeId()) #define IN_PROC_BROWSER_TEST_P(test_case_name, test_name) \ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ : public test_case_name { \ public: \ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ protected: \ virtual void RunTestOnMainThread(); \ private: \ virtual void TestBody() {} \ static int AddToRegistry() { \ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ GetTestCasePatternHolder(\ #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ #test_case_name, \ #test_name, \ new ::testing::internal::TestMetaFactory< \ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ return 0; \ } \ static int gtest_registering_dummy_; \ GTEST_DISALLOW_COPY_AND_ASSIGN_(\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ }; \ int GTEST_TEST_CLASS_NAME_(test_case_name, \ test_name)::gtest_registering_dummy_ = \ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::RunTestOnMainThread() #endif // defined(HAS_OUT_OF_PROC_TEST_RUNNER) #endif // CHROME_TEST_IN_PROCESS_BROWSER_TEST_H_