Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(949)

Side by Side Diff: chrome/test/page_cycler/page_cycler_test.cc

Issue 7578004: Move more files from chrome/test to chrome/test/base, part #7 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/test/memory_test/memory_test.cc ('k') | chrome/test/perf/dom_checker_uitest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 #include "base/basictypes.h"
6 #include "base/command_line.h"
7 #include "base/file_path.h"
8 #include "base/file_util.h"
9 #include "base/path_service.h"
10 #include "base/process_util.h"
11 #include "base/string_number_conversions.h"
12 #include "base/sys_string_conversions.h"
13 #include "base/test/test_timeouts.h"
14 #include "base/utf_string_conversions.h"
15 #include "chrome/browser/net/url_fixer_upper.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/test/automation/tab_proxy.h"
20 #include "chrome/test/automation/window_proxy.h"
21 #include "chrome/test/base/chrome_process_util.h"
22 #include "chrome/test/base/test_switches.h"
23 #include "chrome/test/ui/ui_perf_test.h"
24 #include "googleurl/src/gurl.h"
25 #include "net/base/net_util.h"
26
27 #ifndef NDEBUG
28 static const int kTestIterations = 2;
29 static const int kDatabaseTestIterations = 2;
30 #else
31 static const int kTestIterations = 10;
32 // For some unknown reason, the DB perf tests are much much slower on the
33 // Vista perf bot, so we have to cut down the number of iterations to 5
34 // to make sure each test finishes in less than 10 minutes.
35 static const int kDatabaseTestIterations = 5;
36 #endif
37 static const int kIDBTestIterations = 5;
38
39 // URL at which data files may be found for HTTP tests. The document root of
40 // this URL's server should point to data/page_cycler/.
41 static const char kBaseUrl[] = "http://localhost:8000/";
42
43 namespace {
44
45 void PopulateBufferCache(const FilePath& test_dir) {
46 // This will recursively walk the directory given and read all the
47 // files it finds. This is done so the system file cache is likely
48 // to have as much loaded as possible. Without this, the tests of
49 // this build gets one set of timings and then the reference build
50 // test, gets slightly faster ones (even if the reference build is
51 // the same binary). The hope is by forcing all the possible data
52 // into the cache we equalize the tests for comparing timing data.
53
54 // We don't want to walk into .svn dirs, so we have to do the tree walk
55 // ourselves.
56
57 std::vector<FilePath> dirs;
58 dirs.push_back(test_dir);
59 const FilePath svn_dir(FILE_PATH_LITERAL(".svn"));
60
61 for (size_t idx = 0; idx < dirs.size(); ++idx) {
62 file_util::FileEnumerator dir_enumerator(dirs[idx], false,
63 file_util::FileEnumerator::DIRECTORIES);
64 FilePath path;
65 for (path = dir_enumerator.Next();
66 !path.empty();
67 path = dir_enumerator.Next()) {
68 if (path.BaseName() != svn_dir)
69 dirs.push_back(path);
70 }
71 }
72
73 unsigned int loaded = 0;
74
75 // We seem to have some files in the data dirs that are just there for
76 // reference, make a quick attempt to skip them by matching suffixes.
77 std::vector<FilePath::StringType> ignore_suffixes;
78 ignore_suffixes.push_back(FILE_PATH_LITERAL(".orig.html"));
79 ignore_suffixes.push_back(FILE_PATH_LITERAL(".html-original"));
80
81 std::vector<FilePath>::const_iterator iter;
82 for (iter = dirs.begin(); iter != dirs.end(); ++iter) {
83 file_util::FileEnumerator file_enumerator(*iter, false,
84 file_util::FileEnumerator::FILES);
85 FilePath path;
86 for (path = file_enumerator.Next();
87 !path.empty();
88 path = file_enumerator.Next()) {
89 const FilePath base_name = path.BaseName();
90 const size_t base_name_size = base_name.value().size();
91
92 bool should_skip = false;
93 std::vector<FilePath::StringType>::const_iterator ignore_iter;
94 for (ignore_iter = ignore_suffixes.begin();
95 ignore_iter != ignore_suffixes.end();
96 ++ignore_iter) {
97 const FilePath::StringType &suffix = *ignore_iter;
98
99 if ((base_name_size > suffix.size()) &&
100 (base_name.value().compare(base_name_size - suffix.size(),
101 suffix.size(), suffix) == 0)) {
102 should_skip = true;
103 break;
104 }
105 }
106 if (should_skip)
107 continue;
108
109 // Read the file fully to get it into the cache.
110 // We don't care what the contents are.
111 if (file_util::ReadFileToString(path, NULL))
112 ++loaded;
113 }
114 }
115 VLOG(1) << "Buffer cache should be primed with " << loaded << " files.";
116 }
117
118 class PageCyclerTest : public UIPerfTest {
119 protected:
120 bool print_times_only_;
121 int num_test_iterations_;
122 public:
123 PageCyclerTest()
124 : print_times_only_(false) {
125 show_window_ = true;
126 dom_automation_enabled_ = true;
127
128 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
129 num_test_iterations_ = kTestIterations;
130
131 if (parsed_command_line.HasSwitch(switches::kPageCyclerIterations)) {
132 std::string str = parsed_command_line.GetSwitchValueASCII(
133 switches::kPageCyclerIterations);
134 base::StringToInt(str, &num_test_iterations_);
135 }
136
137 // Expose garbage collection for the page cycler tests.
138 launch_arguments_.AppendSwitchASCII(switches::kJavaScriptFlags,
139 "--expose_gc");
140 }
141
142 virtual FilePath GetDataPath(const char* name) {
143 // Make sure the test data is checked out
144 FilePath test_path;
145 PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
146 test_path = test_path.Append(FILE_PATH_LITERAL("data"));
147 test_path = test_path.Append(FILE_PATH_LITERAL("page_cycler"));
148 test_path = test_path.AppendASCII(name);
149 return test_path;
150 }
151
152 virtual bool HasErrors(const std::string /*timings*/) {
153 return false;
154 }
155
156 virtual int GetTestIterations() {
157 return num_test_iterations_;
158 }
159
160 // For HTTP tests, the name must be safe for use in a URL without escaping.
161 void RunPageCycler(const char* name, std::wstring* pages,
162 std::string* timings, bool use_http) {
163 FilePath test_path = GetDataPath(name);
164 ASSERT_TRUE(file_util::DirectoryExists(test_path))
165 << "Missing test directory " << test_path.value();
166
167 PopulateBufferCache(test_path);
168
169 GURL test_url;
170 if (use_http) {
171 test_url = GURL(std::string(kBaseUrl) + name + "/start.html");
172 } else {
173 test_path = test_path.Append(FILE_PATH_LITERAL("start.html"));
174 test_url = net::FilePathToFileURL(test_path);
175 }
176
177 // run N iterations
178 GURL::Replacements replacements;
179 const std::string query_string =
180 "iterations=" + base::IntToString(GetTestIterations()) + "&auto=1";
181 replacements.SetQuery(
182 query_string.c_str(),
183 url_parse::Component(0, query_string.length()));
184 test_url = test_url.ReplaceComponents(replacements);
185
186 scoped_refptr<TabProxy> tab(GetActiveTab());
187 ASSERT_TRUE(tab.get());
188 ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab->NavigateToURL(test_url));
189
190 // Wait for the test to finish.
191 ASSERT_TRUE(WaitUntilCookieValue(
192 tab.get(), test_url, "__pc_done",
193 TestTimeouts::huge_test_timeout_ms(), "1"));
194
195 std::string cookie;
196 ASSERT_TRUE(tab->GetCookieByName(test_url, "__pc_pages", &cookie));
197 pages->assign(UTF8ToWide(cookie));
198 ASSERT_FALSE(pages->empty());
199
200 // Get the timing cookie value from the DOM automation.
201 std::wstring wcookie;
202 ASSERT_TRUE(tab->ExecuteAndExtractString(L"",
203 L"window.domAutomationController.send("
204 L"JSON.stringify(__get_timings()));",
205 &wcookie));
206 cookie = base::SysWideToNativeMB(wcookie);
207
208 // JSON.stringify() encapsulates the returned string in quotes, strip them.
209 std::string::size_type start_idx = cookie.find("\"");
210 std::string::size_type end_idx = cookie.find_last_of("\"");
211 if (start_idx != std::string::npos &&
212 end_idx != std::string::npos &&
213 start_idx < end_idx) {
214 cookie = cookie.substr(start_idx+1, end_idx-start_idx-1);
215 }
216
217 timings->assign(cookie);
218 ASSERT_FALSE(timings->empty());
219 }
220
221 // When use_http is true, the test name passed here will be used directly in
222 // the path to the test data, so it must be safe for use in a URL without
223 // escaping. (No pound (#), question mark (?), semicolon (;), non-ASCII, or
224 // other funny stuff.)
225 void RunTestWithSuffix(const char* graph, const char* name, bool use_http,
226 const char* suffix) {
227 std::wstring pages;
228 std::string timings;
229 size_t start_size = base::GetSystemCommitCharge();
230 RunPageCycler(name, &pages, &timings, use_http);
231 if (timings.empty() || HasErrors(timings))
232 return;
233 size_t stop_size = base::GetSystemCommitCharge();
234
235 if (!print_times_only_) {
236 PrintMemoryUsageInfo(suffix);
237 PrintIOPerfInfo(suffix);
238 PrintSystemCommitCharge(suffix, stop_size - start_size,
239 false /* not important */);
240 }
241
242 std::string trace_name = "t" + std::string(suffix);
243
244 printf("Pages: [%s]\n", base::SysWideToNativeMB(pages).c_str());
245
246 PrintResultList(graph, "", trace_name, timings, "ms",
247 true /* important */);
248 }
249
250 void RunTest(const char* graph, const char* name, bool use_http) {
251 RunTestWithSuffix(graph, name, use_http, "");
252 }
253 };
254
255 class PageCyclerReferenceTest : public PageCyclerTest {
256 public:
257 void SetUp() {
258 UseReferenceBuild();
259 PageCyclerTest::SetUp();
260 }
261
262 void RunTest(const char* graph, const char* name, bool use_http) {
263 // Run the test.
264 PageCyclerTest::RunTestWithSuffix(graph, name, use_http, "_ref");
265 }
266 };
267
268 class PageCyclerExtensionTest : public PageCyclerTest {
269 public:
270 // Note: we delay the SetUp until RunTest is called so that we can set
271 // the user_data_dir based on the test name.
272 virtual void SetUp() {}
273 void RunTest(const char* graph, const char* extension_profile,
274 const char* output_suffix, const char* name, bool use_http) {
275 // Set up the extension profile directory.
276 ASSERT_TRUE(extension_profile != NULL);
277 FilePath data_dir;
278 PathService::Get(chrome::DIR_TEST_DATA, &data_dir);
279 data_dir = data_dir.AppendASCII("extensions").AppendASCII("profiles").
280 AppendASCII(extension_profile);
281 ASSERT_TRUE(file_util::DirectoryExists(data_dir));
282 set_template_user_data(data_dir);
283
284 // Now run the test.
285 PageCyclerTest::SetUp();
286 PageCyclerTest::RunTestWithSuffix(graph, name, use_http, output_suffix);
287 }
288 };
289
290 class PageCyclerExtensionWebRequestTest : public PageCyclerExtensionTest {
291 public:
292 PageCyclerExtensionWebRequestTest()
293 : PageCyclerExtensionTest()
294 {
295 // Enable experimental extension APIs for webrequest tests.
296 launch_arguments_.AppendSwitch(switches::kEnableExperimentalExtensionApis);
297 }
298 };
299
300 static FilePath GetDatabaseDataPath(const char* name) {
301 FilePath test_path;
302 PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
303 test_path = test_path.Append(FILE_PATH_LITERAL("tools"));
304 test_path = test_path.Append(FILE_PATH_LITERAL("page_cycler"));
305 test_path = test_path.Append(FILE_PATH_LITERAL("database"));
306 test_path = test_path.AppendASCII(name);
307 return test_path;
308 }
309
310 static FilePath GetIndexedDatabaseDataPath(const char* name) {
311 FilePath test_path;
312 PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
313 test_path = test_path.Append(FILE_PATH_LITERAL("tools"));
314 test_path = test_path.Append(FILE_PATH_LITERAL("page_cycler"));
315 test_path = test_path.Append(FILE_PATH_LITERAL("indexed_db"));
316 test_path = test_path.AppendASCII(name);
317 return test_path;
318 }
319
320 static bool HasDatabaseErrors(const std::string timings) {
321 size_t pos = 0;
322 size_t new_pos = 0;
323 std::string time_str;
324 int time = 0;
325 do {
326 new_pos = timings.find(',', pos);
327 if (new_pos == std::string::npos)
328 new_pos = timings.length();
329 if (!base::StringToInt(timings.begin() + pos,
330 timings.begin() + new_pos,
331 &time)) {
332 LOG(ERROR) << "Invalid time reported: " << time_str;
333 return true;
334 }
335 if (time < 0) {
336 switch (time) {
337 case -1:
338 LOG(ERROR) << "Error while opening the database.";
339 break;
340 case -2:
341 LOG(ERROR) << "Error while setting up the database.";
342 break;
343 case -3:
344 LOG(ERROR) << "Error while running the transactions.";
345 break;
346 default:
347 LOG(ERROR) << "Unknown error: " << time;
348 }
349 return true;
350 }
351
352 pos = new_pos + 1;
353 } while (pos < timings.length());
354
355 return false;
356 }
357
358 class PageCyclerDatabaseTest : public PageCyclerTest {
359 public:
360 PageCyclerDatabaseTest() {
361 print_times_only_ = true;
362 }
363
364 virtual FilePath GetDataPath(const char* name) {
365 return GetDatabaseDataPath(name);
366 }
367
368 virtual bool HasErrors(const std::string timings) {
369 return HasDatabaseErrors(timings);
370 }
371
372 virtual int GetTestIterations() {
373 return kDatabaseTestIterations;
374 }
375 };
376
377 class PageCyclerDatabaseReferenceTest : public PageCyclerReferenceTest {
378 public:
379 PageCyclerDatabaseReferenceTest() {
380 print_times_only_ = true;
381 }
382
383 virtual FilePath GetDataPath(const char* name) {
384 return GetDatabaseDataPath(name);
385 }
386
387 virtual bool HasErrors(const std::string timings) {
388 return HasDatabaseErrors(timings);
389 }
390
391 virtual int GetTestIterations() {
392 return kDatabaseTestIterations;
393 }
394 };
395
396 class PageCyclerIndexedDatabaseTest : public PageCyclerTest {
397 public:
398 PageCyclerIndexedDatabaseTest() {
399 print_times_only_ = true;
400 }
401
402 virtual FilePath GetDataPath(const char* name) {
403 return GetIndexedDatabaseDataPath(name);
404 }
405
406 virtual bool HasErrors(const std::string timings) {
407 return HasDatabaseErrors(timings);
408 }
409
410 virtual int GetTestIterations() {
411 return kIDBTestIterations;
412 }
413 };
414
415 class PageCyclerIndexedDatabaseReferenceTest : public PageCyclerReferenceTest {
416 public:
417 PageCyclerIndexedDatabaseReferenceTest() {
418 print_times_only_ = true;
419 }
420
421 virtual FilePath GetDataPath(const char* name) {
422 return GetIndexedDatabaseDataPath(name);
423 }
424
425 virtual bool HasErrors(const std::string timings) {
426 return HasDatabaseErrors(timings);
427 }
428
429 virtual int GetTestIterations() {
430 return kIDBTestIterations;
431 }
432 };
433
434 // This macro simplifies setting up regular and reference build tests.
435 #define PAGE_CYCLER_TESTS(test, name, use_http) \
436 TEST_F(PageCyclerTest, name) { \
437 RunTest("times", test, use_http); \
438 } \
439 TEST_F(PageCyclerReferenceTest, name) { \
440 RunTest("times", test, use_http); \
441 }
442
443 // This macro simplifies setting up regular and reference build tests
444 // for HTML5 database tests.
445 // FLAKY http://crbug.com/67918
446 #define PAGE_CYCLER_DATABASE_TESTS(test, name) \
447 TEST_F(PageCyclerDatabaseTest, FLAKY_Database##name##File) { \
448 RunTest(test, test, false); \
449 } \
450 TEST_F(PageCyclerDatabaseReferenceTest, FLAKY_Database##name##File) { \
451 RunTest(test, test, false); \
452 }
453
454 // This macro simplifies setting up regular and reference build tests
455 // for HTML5 Indexed DB tests.
456 // FLAKY http://crbug.com/67918
457 #define PAGE_CYCLER_IDB_TESTS(test, name) \
458 TEST_F(PageCyclerIndexedDatabaseTest, FLAKY_IndexedDB##name##File) { \
459 RunTest(test, test, false); \
460 } \
461 TEST_F(PageCyclerIndexedDatabaseReferenceTest, IndexedDB##name##File) { \
462 RunTest(test, test, false); \
463 }
464
465 // These are shorthand for File vs. Http tests.
466 #define PAGE_CYCLER_FILE_TESTS(test, name) \
467 PAGE_CYCLER_TESTS(test, name, false)
468 #define PAGE_CYCLER_HTTP_TESTS(test, name) \
469 PAGE_CYCLER_TESTS(test, name, true)
470
471 // This macro lets us define tests with 1 and 10 extensions with 1 content
472 // script each. The name for the 10-extension case is changed so as not
473 // to run by default on the buildbots.
474 #define PAGE_CYCLER_EXTENSIONS_FILE_TESTS(test, name) \
475 TEST_F(PageCyclerExtensionTest, name) { \
476 RunTest("times", "content_scripts1", "_extcs1", test, false); \
477 } \
478 TEST_F(PageCyclerExtensionTest, name##10) { \
479 RunTest("times", "content_scripts10", "_extcs10", test, false); \
480 }
481
482 // This macro lets us define tests with an extension that listens to the
483 // webrequest.onBeforeRequest. It measures the effect that a blocking event
484 // for every request has on page cycle time.
485 #define PAGE_CYCLER_EXTENSIONS_WEBREQUEST_FILE_TESTS(test, name) \
486 TEST_F(PageCyclerExtensionWebRequestTest, name) { \
487 RunTest("times", "extension_webrequest", "_extwr", test, false); \
488 }
489
490 // file-URL tests
491 PAGE_CYCLER_FILE_TESTS("moz", MozFile);
492 PAGE_CYCLER_EXTENSIONS_FILE_TESTS("moz", MozFile);
493 PAGE_CYCLER_EXTENSIONS_WEBREQUEST_FILE_TESTS("moz", MozFile)
494 PAGE_CYCLER_FILE_TESTS("intl1", Intl1File);
495 PAGE_CYCLER_FILE_TESTS("intl2", Intl2File);
496 PAGE_CYCLER_EXTENSIONS_WEBREQUEST_FILE_TESTS("intl2", Intl2File);
497 PAGE_CYCLER_FILE_TESTS("dom", DomFile);
498 PAGE_CYCLER_FILE_TESTS("dhtml", DhtmlFile);
499 PAGE_CYCLER_FILE_TESTS("morejs", MorejsFile);
500 PAGE_CYCLER_EXTENSIONS_FILE_TESTS("morejs", MorejsFile);
501 // added more tests here:
502 PAGE_CYCLER_FILE_TESTS("alexa_us", Alexa_usFile);
503 PAGE_CYCLER_FILE_TESTS("moz2", Moz2File);
504 PAGE_CYCLER_FILE_TESTS("morejsnp", MorejsnpFile);
505 PAGE_CYCLER_FILE_TESTS("bloat", BloatFile);
506
507 // http (localhost) tests
508 PAGE_CYCLER_HTTP_TESTS("moz", MozHttp);
509 PAGE_CYCLER_HTTP_TESTS("intl1", Intl1Http);
510 PAGE_CYCLER_HTTP_TESTS("intl2", Intl2Http);
511 PAGE_CYCLER_HTTP_TESTS("dom", DomHttp);
512 PAGE_CYCLER_HTTP_TESTS("bloat", BloatHttp);
513
514 // HTML5 database tests
515 // These tests are _really_ slow on XP/Vista.
516 #if !defined(OS_WIN)
517 PAGE_CYCLER_DATABASE_TESTS("select-transactions",
518 SelectTransactions);
519 PAGE_CYCLER_DATABASE_TESTS("select-readtransactions",
520 SelectReadTransactions);
521 PAGE_CYCLER_DATABASE_TESTS("select-readtransactions-read-results",
522 SelectReadTransactionsReadResults);
523 PAGE_CYCLER_DATABASE_TESTS("insert-transactions",
524 InsertTransactions);
525 PAGE_CYCLER_DATABASE_TESTS("update-transactions",
526 UpdateTransactions);
527 PAGE_CYCLER_DATABASE_TESTS("delete-transactions",
528 DeleteTransactions);
529 PAGE_CYCLER_DATABASE_TESTS("pseudo-random-transactions",
530 PseudoRandomTransactions);
531 #endif
532
533 // Indexed DB tests.
534 PAGE_CYCLER_IDB_TESTS("basic_insert", BasicInsert);
535
536 } // namespace
OLDNEW
« no previous file with comments | « chrome/test/memory_test/memory_test.cc ('k') | chrome/test/perf/dom_checker_uitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698