1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
|
// Copyright (c) 2010 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_UI_UI_TEST_H_
#define CHROME_TEST_UI_UI_TEST_H_
#pragma once
// This file provides a common base for running UI unit tests, which operate
// the entire browser application in a separate process for holistic
// functional testing.
//
// Tests should #include this file, subclass UITest, and use the TEST_F macro
// to declare individual test cases. This provides a running browser window
// during the test, accessible through the window_ member variable. The window
// will close when the test ends, regardless of whether the test passed.
//
// Tests which need to launch the browser with a particular set of command-line
// arguments should set the value of launch_arguments_ in their constructors.
#include <string>
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/process.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
#include "build/build_config.h"
// TODO(evanm): we should be able to just forward-declare
// AutomationProxy here, but many files that #include this one don't
// themselves #include automation_proxy.h.
#include "chrome/test/automation/automation_proxy.h"
#include "testing/platform_test.h"
class AutomationProxy;
class BrowserProxy;
class DictionaryValue;
class FilePath;
class GURL;
class ScopedTempDir;
class TabProxy;
// Base class for UI Tests. This implements the core of the functions.
// This base class decouples all automation functionality from testing
// infrastructure, for use without gtest.
// If using gtest, you probably want to inherit from UITest (declared below)
// rather than UITestBase.
class UITestBase {
protected:
// String to display when a test fails because the crash service isn't
// running.
static const wchar_t kFailedNoCrashService[];
// Constructor
UITestBase();
explicit UITestBase(MessageLoop::Type msg_loop_type);
virtual ~UITestBase();
// Starts the browser using the arguments in launch_arguments_, and
// sets up member variables.
virtual void SetUp();
// Closes the browser window.
virtual void TearDown();
// Set up the test time out values.
virtual void InitializeTimeouts();
public:
// ********* Utility functions *********
// Launches the browser and IPC testing server.
void LaunchBrowserAndServer();
// Overridable so that derived classes can provide their own AutomationProxy.
virtual AutomationProxy* CreateAutomationProxy(int execution_timeout);
// Closes the browser and IPC testing server.
void CloseBrowserAndServer();
// Launches the browser with the given command line.
// TODO(phajdan.jr): Make LaunchBrowser private. Tests should use
// LaunchAnotherBrowserBlockUntilClosed.
void LaunchBrowser(const CommandLine& cmdline, bool clear_profile);
// Launches an another browser process and waits for it to finish. Returns
// true on success.
bool LaunchAnotherBrowserBlockUntilClosed(const CommandLine& cmdline);
// Exits out browser instance.
void QuitBrowser();
// Terminates the browser, simulates end of session.
void TerminateBrowser();
// Tells the browser to navigato to the givne URL in the active tab
// of the first app window.
// Does not wait for the navigation to complete to return.
void NavigateToURLAsync(const GURL& url);
// Tells the browser to navigate to the given URL in the active tab
// of the first app window.
// This method doesn't return until the navigation is complete.
void NavigateToURL(const GURL& url);
// Same as above, except in the given tab and window.
void NavigateToURL(const GURL& url, int window_index, int tab_index);
// Tells the browser to navigate to the given URL in the active tab
// of the first app window.
// This method doesn't return until the |number_of_navigations| navigations
// complete.
void NavigateToURLBlockUntilNavigationsComplete(const GURL& url,
int number_of_navigations);
// Same as above, except in the given tab and window.
void NavigateToURLBlockUntilNavigationsComplete(const GURL& url,
int number_of_navigations, int tab_index, int window_index);
// Returns the URL of the currently active tab. Only looks in the first
// window, for backward compatibility. If there is no active tab, or some
// other error, the returned URL will be empty.
GURL GetActiveTabURL() { return GetActiveTabURL(0); }
// Like above, but looks at the window at the given index.
GURL GetActiveTabURL(int window_index);
// Returns the title of the currently active tab. Only looks in the first
// window, for backward compatibility.
std::wstring GetActiveTabTitle() { return GetActiveTabTitle(0); }
// Like above, but looks at the window at the given index.
std::wstring GetActiveTabTitle(int window_index);
// Returns the tabstrip index of the currently active tab in the window at
// the given index, or -1 on error. Only looks in the first window, for
// backward compatibility.
int GetActiveTabIndex() { return GetActiveTabIndex(0); }
// Like above, but looks at the window at the given index.
int GetActiveTabIndex(int window_index);
// Returns true when the browser process is running, independent if any
// renderer process exists or not. It will returns false if an user closed the
// window or if the browser process died by itself.
bool IsBrowserRunning();
// Returns true when time_out_ms milliseconds have elapsed.
// Returns false if the browser process died while waiting.
bool CrashAwareSleep(int time_out_ms);
// Returns the number of tabs in the first window. If no windows exist,
// causes a test failure and returns 0.
int GetTabCount();
// Same as GetTabCount(), except with the window at the given index.
int GetTabCount(int window_index);
// Polls the tab for the cookie_name cookie and returns once one of the
// following conditions hold true:
// - The cookie is of expected_value.
// - The browser process died.
// - The time_out value has been exceeded.
bool WaitUntilCookieValue(TabProxy* tab, const GURL& url,
const char* cookie_name,
int time_out_ms,
const char* expected_value);
// Polls the tab for the cookie_name cookie and returns once one of the
// following conditions hold true:
// - The cookie is set to any value.
// - The browser process died.
// - The time_out value has been exceeded.
std::string WaitUntilCookieNonEmpty(TabProxy* tab,
const GURL& url,
const char* cookie_name,
int time_out_ms);
// Polls the tab for a JavaScript condition and returns once one of the
// following conditions hold true:
// - The JavaScript condition evaluates to true (return true).
// - The browser process died (return false).
// - The time_out value has been exceeded (return false).
//
// The JavaScript expression is executed in the context of the frame that
// matches the provided xpath.
bool WaitUntilJavaScriptCondition(TabProxy* tab,
const std::wstring& frame_xpath,
const std::wstring& jscript,
int time_out_ms);
// Polls up to kWaitForActionMaxMsec ms to attain a specific tab count. Will
// assert that the tab count is valid at the end of the wait.
void WaitUntilTabCount(int tab_count);
// Checks whether the download shelf is visible in the current browser, giving
// it a chance to appear (we don't know the exact timing) while finishing as
// soon as possible.
bool WaitForDownloadShelfVisible(BrowserProxy* browser);
// Checks whether the download shelf is invisible in the current browser,
// giving it a chance to appear (we don't know the exact timing) while
// finishing as soon as possible.
bool WaitForDownloadShelfInvisible(BrowserProxy* browser);
private:
// Waits for download shelf visibility or invisibility.
bool WaitForDownloadShelfVisibilityChange(BrowserProxy* browser,
bool wait_for_open);
public:
// Waits until the Find window has become fully visible (if |wait_for_open| is
// true) or fully hidden (if |wait_for_open| is false). This function can time
// out (return false) if the window doesn't appear within a specific time.
bool WaitForFindWindowVisibilityChange(BrowserProxy* browser,
bool wait_for_open);
// Waits until the Bookmark bar has stopped animating and become fully visible
// (if |wait_for_open| is true) or fully hidden (if |wait_for_open| is false).
// This function can time out (in which case it returns false).
bool WaitForBookmarkBarVisibilityChange(BrowserProxy* browser,
bool wait_for_open);
// Sends the request to close the browser without blocking.
// This is so we can interact with dialogs opened on browser close,
// e.g. the beforeunload confirm dialog.
void CloseBrowserAsync(BrowserProxy* browser) const;
// Closes the specified browser. Returns true if the browser was closed.
// This call is blocking. |application_closed| is set to true if this was
// the last browser window (and therefore as a result of it closing the
// browser process terminated). Note that in that case this method returns
// after the browser process has terminated.
bool CloseBrowser(BrowserProxy* browser, bool* application_closed) const;
// Prints numerical information to stdout in a controlled format, for
// post-processing. |measurement| is a description of the quantity being
// measured, e.g. "vm_peak"; |modifier| is provided as a convenience and
// will be appended directly to the name of the |measurement|, e.g.
// "_browser"; |trace| is a description of the particular data point, e.g.
// "reference"; |value| is the measured value; and |units| is a description
// of the units of measure, e.g. "bytes". If |important| is true, the output
// line will be specially marked, to notify the post-processor. The strings
// may be empty. They should not contain any colons (:) or equals signs (=).
// A typical post-processing step would be to produce graphs of the data
// produced for various builds, using the combined |measurement| + |modifier|
// string to specify a particular graph and the |trace| to identify a trace
// (i.e., data series) on that graph.
void PrintResult(const std::string& measurement,
const std::string& modifier,
const std::string& trace,
size_t value,
const std::string& units,
bool important);
// Like the above version of PrintResult(), but takes a std::string value
// instead of a size_t.
void PrintResult(const std::string& measurement,
const std::string& modifier,
const std::string& trace,
const std::string& value,
const std::string& units,
bool important);
// Like PrintResult(), but prints a (mean, standard deviation) result pair.
// The |<values>| should be two comma-seaprated numbers, the mean and
// standard deviation (or other error metric) of the measurement.
void PrintResultMeanAndError(const std::string& measurement,
const std::string& modifier,
const std::string& trace,
const std::string& mean_and_error,
const std::string& units,
bool important);
// Like PrintResult(), but prints an entire list of results. The |values|
// will generally be a list of comma-separated numbers. A typical
// post-processing step might produce plots of their mean and standard
// deviation.
void PrintResultList(const std::string& measurement,
const std::string& modifier,
const std::string& trace,
const std::string& values,
const std::string& units,
bool important);
// Gets the directory for the currently active profile in the browser.
FilePath GetDownloadDirectory();
// Get the handle of browser process connected to the automation. This
// function only retruns a reference to the handle so the caller does not
// own the handle returned.
base::ProcessHandle process() { return process_; }
// Wait for |generated_file| to be ready and then compare it with
// |original_file| to see if they're identical or not if |compare_file| is
// true. If |need_equal| is true, they need to be identical. Otherwise,
// they should be different. This function will delete the generated file if
// the parameter |delete_generated_file| is true.
void WaitForGeneratedFileAndCheck(const FilePath& generated_file,
const FilePath& original_file,
bool compare_files,
bool need_equal,
bool delete_generated_file);
// Get/Set a flag to run the renderer in process when running the
// tests.
static bool in_process_renderer() { return in_process_renderer_; }
static void set_in_process_renderer(bool value) {
in_process_renderer_ = value;
}
// Get/Set a flag to run the renderer outside the sandbox when running the
// tests
static bool no_sandbox() { return no_sandbox_; }
static void set_no_sandbox(bool value) {
no_sandbox_ = value;
}
// Get/Set a flag to run with DCHECKs enabled in release.
static bool enable_dcheck() { return enable_dcheck_; }
static void set_enable_dcheck(bool value) {
enable_dcheck_ = value;
}
// Get/Set a flag to dump the process memory without crashing on DCHECKs.
static bool silent_dump_on_dcheck() { return silent_dump_on_dcheck_; }
static void set_silent_dump_on_dcheck(bool value) {
silent_dump_on_dcheck_ = value;
}
// Get/Set a flag to disable breakpad handling.
static bool disable_breakpad() { return disable_breakpad_; }
static void set_disable_breakpad(bool value) {
disable_breakpad_ = value;
}
// Get/Set a flag to run the plugin processes inside the sandbox when running
// the tests
static bool safe_plugins() { return safe_plugins_; }
static void set_safe_plugins(bool value) {
safe_plugins_ = value;
}
static bool show_error_dialogs() { return show_error_dialogs_; }
static void set_show_error_dialogs(bool value) {
show_error_dialogs_ = value;
}
static bool full_memory_dump() { return full_memory_dump_; }
static void set_full_memory_dump(bool value) {
full_memory_dump_ = value;
}
static bool dump_histograms_on_exit() { return dump_histograms_on_exit_; }
static void set_dump_histograms_on_exit(bool value) {
dump_histograms_on_exit_ = value;
}
static int test_timeout_ms() { return timeout_ms_; }
static void set_test_timeout_ms(int value) {
timeout_ms_ = value;
}
static std::wstring js_flags() { return js_flags_; }
static void set_js_flags(const std::wstring& value) {
js_flags_ = value;
}
static std::wstring log_level() { return log_level_; }
static void set_log_level(const std::wstring& value) {
log_level_ = value;
}
// Profile theme type choices.
typedef enum {
DEFAULT_THEME = 0,
COMPLEX_THEME = 1,
NATIVE_THEME = 2,
CUSTOM_FRAME = 3,
CUSTOM_FRAME_NATIVE_THEME = 4,
} ProfileType;
// Returns the directory name where the "typical" user data is that we use
// for testing.
static FilePath ComputeTypicalUserDataSource(ProfileType profile_type);
// Rewrite the preferences file to point to the proper image directory.
static void RewritePreferencesFile(const FilePath& user_data_dir);
// Called by some tests that wish to have a base profile to start from. This
// "user data directory" (containing one or more profiles) will be recursively
// copied into the user data directory for the test and the files will be
// evicted from the OS cache. To start with a blank profile, supply an empty
// string (the default).
const FilePath& template_user_data() const { return template_user_data_; }
void set_template_user_data(const FilePath& template_user_data) {
template_user_data_ = template_user_data;
}
// Return the user data directory being used by the browser instance in
// UITest::SetUp().
FilePath user_data_dir() const;
// Return the process id of the browser process (-1 on error).
base::ProcessId browser_process_id() const { return process_id_; }
// Timeout accessors.
void set_command_execution_timeout_ms(int timeout) {
command_execution_timeout_ms_ = timeout;
}
int action_timeout_ms() const { return action_timeout_ms_; }
void set_action_timeout_ms(int timeout) {
action_timeout_ms_ = timeout;
}
int action_max_timeout_ms() const { return action_max_timeout_ms_; }
int sleep_timeout_ms() const { return sleep_timeout_ms_; }
std::wstring ui_test_name() const { return ui_test_name_; }
void set_ui_test_name(const std::wstring& name) {
ui_test_name_ = name;
}
// Fetch the state which determines whether the profile will be cleared on
// next startup.
bool get_clear_profile() const {
return clear_profile_;
}
// Sets clear_profile_. Should be called before launching browser to have
// any effect.
void set_clear_profile(bool clear_profile) {
clear_profile_ = clear_profile;
}
// Sets homepage_. Should be called before launching browser to have
// any effect.
void set_homepage(const std::wstring& homepage) {
homepage_ = homepage;
}
// Different ways to quit the browser.
typedef enum {
WINDOW_CLOSE,
USER_QUIT,
SESSION_ENDING,
} ShutdownType;
// Sets the shutdown type, which defaults to WINDOW_CLOSE.
void set_shutdown_type(ShutdownType value) {
shutdown_type_ = value;
}
// Count the number of active browser processes launched by this test.
// The count includes browser sub-processes.
int GetBrowserProcessCount();
// Returns a copy of local state preferences. The caller is responsible for
// deleting the returned object. Returns NULL if there is an error.
DictionaryValue* GetLocalState();
// Returns a copy of the default profile preferences. The caller is
// responsible for deleting the returned object. Returns NULL if there is an
// error.
DictionaryValue* GetDefaultProfilePreferences();
// Waits for the test case to finish.
// ASSERTS if there are test failures.
void WaitForFinish(const std::string &name,
const std::string &id, const GURL &url,
const std::string& test_complete_cookie,
const std::string& expected_cookie_value,
const int wait_time);
// Wrapper around EvictFileFromSystemCache to retry 10 times in case of
// error.
// Apparently needed for Windows buildbots (to workaround an error when
// file is in use).
// TODO(phajdan.jr): Move to test_file_util if we need it in more places.
bool EvictFileFromSystemCacheWrapper(const FilePath& path);
// Synchronously launches local http server normally used to run LayoutTests.
void StartHttpServer(const FilePath& root_directory);
// Launches local http server on the specified port.
void StartHttpServerWithPort(const FilePath& root_directory,
const std::wstring& port);
void StopHttpServer();
// Prints IO performance data for use by perf graphs.
void PrintIOPerfInfo(const char* test_name);
// Prints memory usage data for use by perf graphs.
void PrintMemoryUsageInfo(const char* test_name);
// Prints memory commit charge stats for use by perf graphs.
void PrintSystemCommitCharge(const char* test_name,
size_t charge,
bool important);
// Configures the test to use the reference build.
void UseReferenceBuild();
// Use Chromium binaries from the given directory.
void SetBrowserDirectory(const FilePath& dir);
private:
// Check that no processes related to Chrome exist, displaying
// the given message if any do.
void AssertAppNotRunning(const std::wstring& error_message);
// Common functionality for the public PrintResults methods.
void PrintResultsImpl(const std::string& measurement,
const std::string& modifier,
const std::string& trace,
const std::string& values,
const std::string& prefix,
const std::string& suffix,
const std::string& units,
bool important);
protected:
AutomationProxy* automation() {
EXPECT_TRUE(server_.get());
return server_.get();
}
virtual bool ShouldFilterInet() {
return true;
}
// Wait a certain amount of time for all the app processes to exit,
// forcibly killing them if they haven't exited by then.
// It has the side-effect of killing every browser window opened in your
// session, even those unrelated in the test.
void CleanupAppProcesses();
// Returns the proxy for the currently active tab, or NULL if there is no
// tab or there was some kind of error. Only looks at the first window, for
// backward compatibility. The returned pointer MUST be deleted by the
// caller if non-NULL.
scoped_refptr<TabProxy> GetActiveTab();
// Like above, but looks at the window at the given index.
scoped_refptr<TabProxy> GetActiveTab(int window_index);
// ********* Member variables *********
FilePath browser_directory_; // Path to the browser executable.
FilePath test_data_directory_; // Path to the unit test data.
CommandLine launch_arguments_; // Command to launch the browser
size_t expected_errors_; // The number of errors expected during
// the run (generally 0).
int expected_crashes_; // The number of crashes expected during
// the run (generally 0).
std::wstring homepage_; // Homepage used for testing.
bool wait_for_initial_loads_; // Wait for initial loads to complete
// in SetUp() before running test body.
base::TimeTicks browser_launch_time_; // Time when the browser was run.
base::TimeDelta browser_quit_time_; // How long the shutdown took.
bool dom_automation_enabled_; // This can be set to true to have the
// test run the dom automation case.
FilePath template_user_data_; // See set_template_user_data().
base::ProcessHandle process_; // Handle to the first Chrome process.
base::ProcessId process_id_; // PID of |process_| (for debugging).
static bool in_process_renderer_; // true if we're in single process mode
bool show_window_; // Determines if the window is shown or
// hidden. Defaults to hidden.
bool clear_profile_; // If true the profile is cleared before
// launching. Default is true.
bool include_testing_id_; // Should we supply the testing channel
// id on the command line? Default is
// true.
bool enable_file_cookies_; // Enable file cookies, default is true.
ProfileType profile_type_; // Are we using a profile with a
// complex theme?
FilePath websocket_pid_file_; // PID file for websocket server.
ShutdownType shutdown_type_; // The method for shutting down
// the browser. Used in ShutdownTest.
private:
bool LaunchBrowserHelper(const CommandLine& arguments,
bool wait,
base::ProcessHandle* process);
// We want to have a current history database when we start the browser so
// things like the NTP will have thumbnails. This method updates the dates
// in the history to be more recent.
void UpdateHistoryDates();
base::Time test_start_time_; // Time the test was started
// (so we can check for new crash dumps)
static bool no_sandbox_;
static bool safe_plugins_;
static bool full_memory_dump_; // If true, write full memory dump
// during crash.
static bool show_error_dialogs_; // If true, a user is paying attention
// to the test, so show error dialogs.
static bool dump_histograms_on_exit_; // Include histograms in log on exit.
static bool enable_dcheck_; // Enable dchecks in release mode.
static bool silent_dump_on_dcheck_; // Dump process memory on dcheck without
// crashing.
static bool disable_breakpad_; // Disable breakpad on the browser.
static int timeout_ms_; // Timeout in milliseconds to wait
// for an test to finish.
static std::wstring js_flags_; // Flags passed to the JS engine.
static std::wstring log_level_; // Logging level.
scoped_ptr<AutomationProxy> server_;
int command_execution_timeout_ms_;
int action_timeout_ms_;
int action_max_timeout_ms_;
int sleep_timeout_ms_;
int terminate_timeout_ms_;
std::wstring ui_test_name_;
// We use a temporary directory for profile to avoid issues with being
// unable to delete some files because they're in use, etc.
scoped_ptr<ScopedTempDir> temp_profile_dir_;
};
class UITest : public UITestBase, public PlatformTest {
protected:
UITest() {}
explicit UITest(MessageLoop::Type msg_loop_type)
: UITestBase(), PlatformTest(), message_loop_(msg_loop_type) {
}
virtual void SetUp();
virtual void TearDown();
private:
MessageLoop message_loop_; // Enables PostTask to main thread.
};
// These exist only to support the gTest assertion macros, and
// shouldn't be used in normal program code.
#ifdef UNIT_TEST
std::ostream& operator<<(std::ostream& out, const std::wstring& wstr);
template<typename T>
std::ostream& operator<<(std::ostream& out, const ::scoped_ptr<T>& ptr) {
return out << ptr.get();
}
#endif // UNIT_TEST
#endif // CHROME_TEST_UI_UI_TEST_H_
|