• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_TEST_UI_UI_TEST_H_
6 #define CHROME_TEST_UI_UI_TEST_H_
7 
8 // This file provides a common base for running UI unit tests, which operate
9 // the entire browser application in a separate process for holistic
10 // functional testing.
11 //
12 // Tests should #include this file, subclass UITest, and use the TEST_F macro
13 // to declare individual test cases.  This provides a running browser window
14 // during the test, accessible through the window_ member variable.  The window
15 // will close when the test ends, regardless of whether the test passed.
16 //
17 // Tests which need to launch the browser with a particular set of command-line
18 // arguments should set the value of launch_arguments_ in their constructors.
19 
20 #include <string>
21 
22 #include "base/command_line.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/message_loop/message_loop.h"
25 #include "base/process/process.h"
26 #include "base/time/time.h"
27 #include "chrome/test/automation/proxy_launcher.h"
28 #include "testing/platform_test.h"
29 #include "url/gurl.h"
30 
31 class AutomationProxy;
32 class BrowserProxy;
33 class GURL;
34 class TabProxy;
35 
36 namespace base {
37 class DictionaryValue;
38 class FilePath;
39 }
40 
41 // Base class for UI Tests. This implements the core of the functions.
42 // This base class decouples all automation functionality from testing
43 // infrastructure, for use without gtest.
44 // If using gtest, you probably want to inherit from UITest (declared below)
45 // rather than UITestBase.
46 class UITestBase {
47  public:
48   // ********* Utility functions *********
49 
50   // Launches the browser only.
51   void LaunchBrowser();
52 
53   // Launches the browser and IPC testing connection in server mode.
54   void LaunchBrowserAndServer();
55 
56   // Launches the IPC testing connection in client mode,
57   // which then attempts to connect to a browser.
58   void ConnectToRunningBrowser();
59 
60   // Only for pyauto.
61   base::TimeDelta action_timeout();
62   int action_timeout_ms();
63   void set_action_timeout(base::TimeDelta timeout);
64   void set_action_timeout_ms(int timeout);
65 
66   // Overridable so that derived classes can provide their own ProxyLauncher.
67   virtual ProxyLauncher* CreateProxyLauncher();
68 
69   // Closes the browser and IPC testing server.
70   void CloseBrowserAndServer();
71 
72   // Launches the browser with the given command line.
73   // TODO(phajdan.jr): Make LaunchBrowser private.
74   void LaunchBrowser(const CommandLine& cmdline, bool clear_profile);
75 
76   // Exits out browser instance.
77   void QuitBrowser();
78 
79   // Tells the browser to navigate to the given URL in the active tab
80   // of the first app window.
81   // This method doesn't return until the navigation is complete.
82   void NavigateToURL(const GURL& url);
83 
84   // Navigate to the given URL in the active tab of the given app window.
85   void NavigateToURL(const GURL& url, int window_index);
86 
87   // Same as above, except in the given tab and window.
88   void NavigateToURL(const GURL& url, int window_index, int tab_index);
89 
90   // Tells the browser to navigate to the given URL in the active tab
91   // of the first app window.
92   // This method doesn't return until the |number_of_navigations| navigations
93   // complete.
94   void NavigateToURLBlockUntilNavigationsComplete(const GURL& url,
95                                                   int number_of_navigations);
96 
97   // Same as above, except in the given tab and window.
98   void NavigateToURLBlockUntilNavigationsComplete(const GURL& url,
99       int number_of_navigations, int tab_index, int window_index);
100 
101   // Returns the URL of the currently active tab. Only looks in the first
102   // window, for backward compatibility. If there is no active tab, or some
103   // other error, the returned URL will be empty.
GetActiveTabURL()104   GURL GetActiveTabURL() { return GetActiveTabURL(0); }
105 
106   // Like above, but looks at the window at the given index.
107   GURL GetActiveTabURL(int window_index);
108 
109   // Returns the title of the currently active tab. Only looks in the first
110   // window, for backward compatibility.
GetActiveTabTitle()111   std::wstring GetActiveTabTitle() { return GetActiveTabTitle(0); }
112 
113   // Like above, but looks at the window at the given index.
114   std::wstring GetActiveTabTitle(int window_index);
115 
116   // Returns the tabstrip index of the currently active tab in the window at
117   // the given index, or -1 on error. Only looks in the first window, for
118   // backward compatibility.
GetActiveTabIndex()119   int GetActiveTabIndex() { return GetActiveTabIndex(0); }
120 
121   // Like above, but looks at the window at the given index.
122   int GetActiveTabIndex(int window_index);
123 
124   // Returns the number of tabs in the first window.  If no windows exist,
125   // causes a test failure and returns 0.
126   int GetTabCount();
127 
128   // Same as GetTabCount(), except with the window at the given index.
129   int GetTabCount(int window_index);
130 
131   // Polls up to kWaitForActionMaxMsec ms to attain a specific tab count. Will
132   // assert that the tab count is valid at the end of the wait.
133   void WaitUntilTabCount(int tab_count);
134 
135   // Closes the specified browser.  Returns true if the browser was closed.
136   // This call is blocking.  |application_closed| is set to true if this was
137   // the last browser window (and therefore as a result of it closing the
138   // browser process terminated).  Note that in that case this method returns
139   // after the browser process has terminated.
140   bool CloseBrowser(BrowserProxy* browser, bool* application_closed) const;
141 
142   // Gets the executable file path of the Chrome browser process.
143   const base::FilePath::CharType* GetExecutablePath();
144 
145   // Return the user data directory being used by the browser instance in
146   // UITest::SetUp().
user_data_dir()147   base::FilePath user_data_dir() const {
148     return launcher_->user_data_dir();
149   }
150 
151   // Called by some tests that wish to have a base profile to start from. This
152   // "user data directory" (containing one or more profiles) will be recursively
153   // copied into the user data directory for the test and the files will be
154   // evicted from the OS cache. To start with a blank profile, supply an empty
155   // string (the default).
template_user_data()156   const base::FilePath& template_user_data() const { return template_user_data_; }
set_template_user_data(const base::FilePath & template_user_data)157   void set_template_user_data(const base::FilePath& template_user_data) {
158     template_user_data_ = template_user_data;
159   }
160 
161   // Get the handle of browser process connected to the automation. This
162   // function only returns a reference to the handle so the caller does not
163   // own the handle returned.
process()164   base::ProcessHandle process() const { return launcher_->process(); }
165 
166   // Return the process id of the browser process (-1 on error).
browser_process_id()167   base::ProcessId browser_process_id() const { return launcher_->process_id(); }
168 
169   // Return the time when the browser was run.
browser_launch_time()170   base::TimeTicks browser_launch_time() const {
171     return launcher_->browser_launch_time();
172   }
173 
174   // Return how long the shutdown took.
browser_quit_time()175   base::TimeDelta browser_quit_time() const {
176     return launcher_->browser_quit_time();
177   }
178 
179   // Fetch the state which determines whether the profile will be cleared on
180   // next startup.
get_clear_profile()181   bool get_clear_profile() const {
182     return clear_profile_;
183   }
184   // Sets clear_profile_. Should be called before launching browser to have
185   // any effect.
set_clear_profile(bool clear_profile)186   void set_clear_profile(bool clear_profile) {
187     clear_profile_ = clear_profile;
188   }
189 
190   // homepage_ accessor.
homepage()191   std::string homepage() {
192     return homepage_;
193   }
194 
195   // Sets homepage_. Should be called before launching browser to have
196   // any effect.
set_homepage(const std::string & homepage)197   void set_homepage(const std::string& homepage) {
198     homepage_ = homepage;
199   }
200 
set_test_name(const std::string & name)201   void set_test_name(const std::string& name) {
202     test_name_ = name;
203   }
204 
205   // Sets the shutdown type, which defaults to WINDOW_CLOSE.
set_shutdown_type(ProxyLauncher::ShutdownType value)206   void set_shutdown_type(ProxyLauncher::ShutdownType value) {
207     launcher_->set_shutdown_type(value);
208   }
209 
210   // Get the number of crash dumps we've logged since the test started.
211   int GetCrashCount() const;
212 
213   // Returns empty string if there were no unexpected Chrome asserts or crashes,
214   // a string describing the failures otherwise. As a side effect, it will fail
215   // with EXPECT_EQ macros if this code runs within a gtest harness.
216   std::string CheckErrorsAndCrashes() const;
217 
218   // Use Chromium binaries from the given directory.
219   void SetBrowserDirectory(const base::FilePath& dir);
220 
221   // Appends a command-line switch (no associated value) to be passed to the
222   // browser when launched.
223   void AppendBrowserLaunchSwitch(const char* name);
224 
225   // Appends a command-line switch with associated value to be passed to the
226   // browser when launched.
227   void AppendBrowserLaunchSwitch(const char* name, const char* value);
228 
229   // Pass-through to AutomationProxy::BeginTracing.
230   bool BeginTracing(const std::string& category_patterns);
231 
232   // Pass-through to AutomationProxy::EndTracing.
233   std::string EndTracing();
234 
235  protected:
236   // String to display when a test fails because the crash service isn't
237   // running.
238   static const wchar_t kFailedNoCrashService[];
239 
240   UITestBase();
241   explicit UITestBase(base::MessageLoop::Type msg_loop_type);
242 
243   virtual ~UITestBase();
244 
245   // Starts the browser using the arguments in launch_arguments_, and
246   // sets up member variables.
247   virtual void SetUp();
248 
249   // Closes the browser window.
250   virtual void TearDown();
251 
252   virtual AutomationProxy* automation() const;
253 
254   ProxyLauncher::LaunchState DefaultLaunchState();
255 
256   // Extra command-line switches that need to be passed to the browser are
257   // added in this function. Add new command-line switches here.
258   virtual void SetLaunchSwitches();
259 
260   // Called by the ProxyLauncher just before the browser is launched, allowing
261   // setup of the profile for the runtime environment..
262   virtual void SetUpProfile();
263 
264   // Returns the proxy for the currently active tab, or NULL if there is no
265   // tab or there was some kind of error. Only looks at the first window, for
266   // backward compatibility. The returned pointer MUST be deleted by the
267   // caller if non-NULL.
268   scoped_refptr<TabProxy> GetActiveTab();
269 
270   // Like above, but looks at the window at the given index.
271   scoped_refptr<TabProxy> GetActiveTab(int window_index);
272 
273   // ********* Member variables *********
274 
275   // Path to the browser executable.
276   base::FilePath browser_directory_;
277 
278   // Path to the unit test data.
279   base::FilePath test_data_directory_;
280 
281   // Command to launch the browser
282   CommandLine launch_arguments_;
283 
284   // The number of errors expected during the run (generally 0).
285   size_t expected_errors_;
286 
287   // The number of crashes expected during the run (generally 0).
288   int expected_crashes_;
289 
290   // Homepage used for testing.
291   std::string homepage_;
292 
293   // Name of currently running automated test passed to Chrome process.
294   std::string test_name_;
295 
296   // Wait for initial loads to complete in SetUp() before running test body.
297   bool wait_for_initial_loads_;
298 
299   // This can be set to true to have the test run the dom automation case.
300   bool dom_automation_enabled_;
301 
302   // This can be set to true to enable the stats collection controller JS
303   // bindings.
304   bool stats_collection_controller_enabled_;
305 
306   // See set_template_user_data().
307   base::FilePath template_user_data_;
308 
309   // Determines if the window is shown or hidden. Defaults to hidden.
310   bool show_window_;
311 
312   // If true the profile is cleared before launching. Default is true.
313   bool clear_profile_;
314 
315   // Should we supply the testing channel id
316   // on the command line? Default is true.
317   bool include_testing_id_;
318 
319   // Enable file cookies, default is true.
320   bool enable_file_cookies_;
321 
322   // Launches browser and AutomationProxy.
323   scoped_ptr<ProxyLauncher> launcher_;
324 
325   // PID file for websocket server.
326   base::FilePath websocket_pid_file_;
327 
328  private:
329   // Time the test was started (so we can check for new crash dumps)
330   base::Time test_start_time_;
331 };
332 
333 class UITest : public UITestBase, public PlatformTest {
334  protected:
UITest()335   UITest() {}
UITest(base::MessageLoop::Type msg_loop_type)336   explicit UITest(base::MessageLoop::Type msg_loop_type)
337       : UITestBase(), PlatformTest(), message_loop_(msg_loop_type) {}
338 
339   virtual void SetUp() OVERRIDE;
340   virtual void TearDown() OVERRIDE;
341 
342   virtual ProxyLauncher* CreateProxyLauncher() OVERRIDE;
343 
344   // Count the number of active browser processes launched by this test.
345   // The count includes browser sub-processes.
346   bool GetBrowserProcessCount(int* count) WARN_UNUSED_RESULT;
347 
348   // Returns a copy of local state preferences. The caller is responsible for
349   // deleting the returned object. Returns NULL if there is an error.
350   base::DictionaryValue* GetLocalState();
351 
352   // Returns a copy of the default profile preferences. The caller is
353   // responsible for deleting the returned object. Returns NULL if there is an
354   // error.
355   base::DictionaryValue* GetDefaultProfilePreferences();
356 
357   // Waits for the test case to finish.
358   // ASSERTS if there are test failures.
359   void WaitForFinish(const std::string &name,
360                      const std::string &id, const GURL &url,
361                      const std::string& test_complete_cookie,
362                      const std::string& expected_cookie_value,
363                      const base::TimeDelta wait_time);
364 
365   // Polls the tab for a JavaScript condition and returns once one of the
366   // following conditions hold true:
367   // - The JavaScript condition evaluates to true (return true).
368   // - The browser process died (return false).
369   // - The timeout value has been exceeded (return false).
370   //
371   // The JavaScript expression is executed in the context of the frame that
372   // matches the provided xpath.
373   bool WaitUntilJavaScriptCondition(TabProxy* tab,
374                                     const std::wstring& frame_xpath,
375                                     const std::wstring& jscript,
376                                     base::TimeDelta timeout);
377 
378   // Polls the tab for the cookie_name cookie and returns once one of the
379   // following conditions hold true:
380   // - The cookie is of expected_value.
381   // - The browser process died.
382   // - The timeout value has been exceeded.
383   bool WaitUntilCookieValue(TabProxy* tab, const GURL& url,
384                             const char* cookie_name,
385                             base::TimeDelta timeout,
386                             const char* expected_value);
387 
388   // Polls the tab for the cookie_name cookie and returns once one of the
389   // following conditions hold true:
390   // - The cookie is set to any value.
391   // - The browser process died.
392   // - The timeout value has been exceeded.
393   std::string WaitUntilCookieNonEmpty(TabProxy* tab,
394                                       const GURL& url,
395                                       const char* cookie_name,
396                                       base::TimeDelta timeout);
397 
398   // Waits until the Find window has become fully visible (if |wait_for_open| is
399   // true) or fully hidden (if |wait_for_open| is false). This function can time
400   // out (return false) if the window doesn't appear within a specific time.
401   bool WaitForFindWindowVisibilityChange(BrowserProxy* browser,
402                                          bool wait_for_open);
403 
404   // Terminates the browser, simulates end of session.
405   void TerminateBrowser();
406 
407   // Tells the browser to navigate to the given URL in the active tab
408   // of the first app window.
409   // Does not wait for the navigation to complete to return.
410   // To avoid intermittent test failures, use NavigateToURL instead, if
411   // possible.
412   void NavigateToURLAsync(const GURL& url);
413 
414  private:
415   base::MessageLoop message_loop_;  // Enables PostTask to main thread.
416 };
417 
418 // These exist only to support the gTest assertion macros, and
419 // shouldn't be used in normal program code.
420 #ifdef UNIT_TEST
421 std::ostream& operator<<(std::ostream& out, const std::wstring& wstr);
422 
423 template<typename T>
424 std::ostream& operator<<(std::ostream& out, const ::scoped_ptr<T>& ptr) {
425   return out << ptr.get();
426 }
427 #endif  // UNIT_TEST
428 
429 #endif  // CHROME_TEST_UI_UI_TEST_H_
430