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

Side by Side Diff: chrome/test/out_of_proc_test_runner.cc

Issue 6333004: Make browser_tests shardable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update+rebase Created 9 years, 11 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <string> 5 #include <string>
6 #include <vector> 6 #include <vector>
7 7
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/environment.h"
9 #include "base/file_util.h" 10 #include "base/file_util.h"
10 #include "base/hash_tables.h" 11 #include "base/hash_tables.h"
11 #include "base/linked_ptr.h" 12 #include "base/linked_ptr.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/mac/scoped_nsautorelease_pool.h" 14 #include "base/mac/scoped_nsautorelease_pool.h"
14 #include "base/process_util.h" 15 #include "base/process_util.h"
15 #include "base/scoped_ptr.h" 16 #include "base/scoped_ptr.h"
16 #include "base/scoped_temp_dir.h" 17 #include "base/scoped_temp_dir.h"
17 #include "base/string_number_conversions.h" 18 #include "base/string_number_conversions.h"
18 #include "base/string_util.h" 19 #include "base/string_util.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 const char kSingleProcessTestsFlag[] = "single_process"; 60 const char kSingleProcessTestsFlag[] = "single_process";
60 const char kSingleProcessTestsAndChromeFlag[] = "single-process"; 61 const char kSingleProcessTestsAndChromeFlag[] = "single-process";
61 // The following is kept for historical reasons (so people that are used to 62 // The following is kept for historical reasons (so people that are used to
62 // using it don't get surprised). 63 // using it don't get surprised).
63 const char kChildProcessFlag[] = "child"; 64 const char kChildProcessFlag[] = "child";
64 65
65 const char kHelpFlag[] = "help"; 66 const char kHelpFlag[] = "help";
66 67
67 const char kTestTerminateTimeoutFlag[] = "test-terminate-timeout"; 68 const char kTestTerminateTimeoutFlag[] = "test-terminate-timeout";
68 69
70 // The environment variable name for the total number of test shards.
71 static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
72 // The environment variable name for the test shard index.
73 static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
74
69 // How long we wait for the subprocess to exit (with a success/failure code). 75 // How long we wait for the subprocess to exit (with a success/failure code).
70 // See http://crbug.com/43862 for some discussion of the value. 76 // See http://crbug.com/43862 for some discussion of the value.
71 const int kDefaultTestTimeoutMs = 20000; 77 const int kDefaultTestTimeoutMs = 20000;
72 78
73 // The default output file for XML output. 79 // The default output file for XML output.
74 static const FilePath::CharType kDefaultOutputFile[] = FILE_PATH_LITERAL( 80 static const FilePath::CharType kDefaultOutputFile[] = FILE_PATH_LITERAL(
75 "test_detail.xml"); 81 "test_detail.xml");
76 82
83 // Parses the environment variable var as an Int32. If it is unset, returns
84 // default_val. If it is set, unsets it then converts it to Int32 before
85 // returning it. If unsetting or converting to an Int32 fails, print an
86 // error and exit with failure.
87 int32 Int32FromEnvOrDie(const char* const var, int32 default_val) {
88 scoped_ptr<base::Environment> env(base::Environment::Create());
89 std::string str_val;
90 int32 result;
91 if (!env->GetVar(var, &str_val))
92 return default_val;
93 if (!env->UnSetVar(var)) {
94 LOG(ERROR) << "Invalid environment: we could not unset " << var << ".\n";
95 exit(EXIT_FAILURE);
96 }
97 if (!base::StringToInt(str_val, &result)) {
98 LOG(ERROR) << "Invalid environment: " << var << " is not an integer.\n";
99 exit(EXIT_FAILURE);
100 }
101 return result;
102 }
103
104 // Checks whether sharding is enabled by examining the relevant
105 // environment variable values. If the variables are present,
106 // but inconsistent (i.e., shard_index >= total_shards), prints
107 // an error and exits.
108 bool ShouldShard(int32* total_shards, int32* shard_index) {
109 *total_shards = Int32FromEnvOrDie(kTestTotalShards, -1);
110 *shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
111
112 if (*total_shards == -1 && *shard_index == -1) {
113 return false;
114 } else if (*total_shards == -1 && *shard_index != -1) {
115 LOG(ERROR) << "Invalid environment variables: you have "
116 << kTestShardIndex << " = " << *shard_index
117 << ", but have left " << kTestTotalShards << " unset.\n";
118 exit(EXIT_FAILURE);
119 } else if (*total_shards != -1 && *shard_index == -1) {
120 LOG(ERROR) << "Invalid environment variables: you have "
121 << kTestTotalShards << " = " << *total_shards
122 << ", but have left " << kTestShardIndex << " unset.\n";
123 exit(EXIT_FAILURE);
124 } else if (*shard_index < 0 || *shard_index >= *total_shards) {
125 LOG(ERROR) << "Invalid environment variables: we require 0 <= "
126 << kTestShardIndex << " < " << kTestTotalShards
127 << ", but you have " << kTestShardIndex << "=" << *shard_index
128 << ", " << kTestTotalShards << "=" << *total_shards << ".\n";
129 exit(EXIT_FAILURE);
130 }
131
132 return *total_shards > 1;
133 }
134
135 // Given the total number of shards, the shard index, and the test id, returns
136 // true iff the test should be run on this shard. The test id is some arbitrary
137 // but unique non-negative integer assigned by this launcher to each test
138 // method. Assumes that 0 <= shard_index < total_shards, which is first
139 // verified in ShouldShard().
140 bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
141 return (test_id % total_shards) == shard_index;
142 }
143
77 // A helper class to output results. 144 // A helper class to output results.
78 // Note: as currently XML is the only supported format by gtest, we don't 145 // Note: as currently XML is the only supported format by gtest, we don't
79 // check output format (e.g. "xml:" prefix) here and output an XML file 146 // check output format (e.g. "xml:" prefix) here and output an XML file
80 // unconditionally. 147 // unconditionally.
81 // Note: we don't output per-test-case or total summary info like 148 // Note: we don't output per-test-case or total summary info like
82 // total failed_test_count, disabled_test_count, elapsed_time and so on. 149 // total failed_test_count, disabled_test_count, elapsed_time and so on.
83 // Only each test (testcase element in the XML) will have the correct 150 // Only each test (testcase element in the XML) will have the correct
84 // failed/disabled/elapsed_time information. Each test won't include 151 // failed/disabled/elapsed_time information. Each test won't include
85 // detailed failure messages either. 152 // detailed failure messages either.
86 class ResultsPrinter { 153 class ResultsPrinter {
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 // Split --gtest_filter at '-', if there is one, to separate into 424 // Split --gtest_filter at '-', if there is one, to separate into
358 // positive filter and negative filter portions. 425 // positive filter and negative filter portions.
359 std::string positive_filter = filter; 426 std::string positive_filter = filter;
360 std::string negative_filter = ""; 427 std::string negative_filter = "";
361 size_t dash_pos = filter.find('-'); 428 size_t dash_pos = filter.find('-');
362 if (dash_pos != std::string::npos) { 429 if (dash_pos != std::string::npos) {
363 positive_filter = filter.substr(0, dash_pos); // Everything up to the dash. 430 positive_filter = filter.substr(0, dash_pos); // Everything up to the dash.
364 negative_filter = filter.substr(dash_pos + 1); // Everything after the dash. 431 negative_filter = filter.substr(dash_pos + 1); // Everything after the dash.
365 } 432 }
366 433
434 int num_runnable_tests = 0;
367 int test_run_count = 0; 435 int test_run_count = 0;
368 int ignored_failure_count = 0; 436 int ignored_failure_count = 0;
369 std::vector<std::string> failed_tests; 437 std::vector<std::string> failed_tests;
370 438
439 int32 total_shards;
440 int32 shard_index;
441 bool should_shard = ShouldShard(&total_shards, &shard_index);
442
371 ResultsPrinter printer(*command_line); 443 ResultsPrinter printer(*command_line);
372 for (int i = 0; i < unit_test->total_test_case_count(); ++i) { 444 for (int i = 0; i < unit_test->total_test_case_count(); ++i) {
373 const testing::TestCase* test_case = unit_test->GetTestCase(i); 445 const testing::TestCase* test_case = unit_test->GetTestCase(i);
374 TestCasePrinterHelper helper(printer, test_case->name(), 446 TestCasePrinterHelper helper(printer, test_case->name(),
375 test_case->total_test_count()); 447 test_case->total_test_count());
376 for (int j = 0; j < test_case->total_test_count(); ++j) { 448 for (int j = 0; j < test_case->total_test_count(); ++j) {
377 const testing::TestInfo* test_info = test_case->GetTestInfo(j); 449 const testing::TestInfo* test_info = test_case->GetTestInfo(j);
378 // Skip disabled tests. 450 // Skip disabled tests.
379 if (std::string(test_info->name()).find("DISABLED") == 0 && 451 if (std::string(test_info->name()).find("DISABLED") == 0 &&
380 !command_line->HasSwitch(kGTestRunDisabledTestsFlag)) { 452 !command_line->HasSwitch(kGTestRunDisabledTestsFlag)) {
381 printer.OnTestEnd(test_info->name(), test_case->name(), 453 printer.OnTestEnd(test_info->name(), test_case->name(),
382 false, false, false, 0); 454 false, false, false, 0);
383 continue; 455 continue;
384 } 456 }
385 std::string test_name = test_info->test_case_name(); 457 std::string test_name = test_info->test_case_name();
386 test_name.append("."); 458 test_name.append(".");
387 test_name.append(test_info->name()); 459 test_name.append(test_info->name());
388 // Skip the test that doesn't match the filter string (if given). 460 // Skip the test that doesn't match the filter string (if given).
389 if ((!positive_filter.empty() && 461 if ((!positive_filter.empty() &&
390 !MatchesFilter(test_name, positive_filter)) || 462 !MatchesFilter(test_name, positive_filter)) ||
391 MatchesFilter(test_name, negative_filter)) { 463 MatchesFilter(test_name, negative_filter)) {
392 printer.OnTestEnd(test_info->name(), test_case->name(), 464 printer.OnTestEnd(test_info->name(), test_case->name(),
393 false, false, false, 0); 465 false, false, false, 0);
394 continue; 466 continue;
395 } 467 }
468 // Decide if this test should be run.
469 bool should_run = true;
470 if (should_shard) {
471 should_run = ShouldRunTestOnShard(total_shards, shard_index,
472 num_runnable_tests);
473 }
474 num_runnable_tests += 1;
475 // If sharding is enabled and the test should not be run, skip it.
476 if (!should_run) {
477 continue;
478 }
396 base::Time start_time = base::Time::Now(); 479 base::Time start_time = base::Time::Now();
397 ++test_run_count; 480 ++test_run_count;
398 int exit_code = RunTest(test_name); 481 int exit_code = RunTest(test_name);
399 if (exit_code == 0) { 482 if (exit_code == 0) {
400 // Test passed. 483 // Test passed.
401 printer.OnTestEnd(test_info->name(), test_case->name(), true, false, 484 printer.OnTestEnd(test_info->name(), test_case->name(), true, false,
402 false, 485 false,
403 (base::Time::Now() - start_time).InMillisecondsF()); 486 (base::Time::Now() - start_time).InMillisecondsF());
404 } else { 487 } else {
405 failed_tests.push_back(test_name); 488 failed_tests.push_back(test_name);
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 exit_code = 1; 619 exit_code = 1;
537 break; 620 break;
538 } 621 }
539 622
540 // Special value "-1" means "repeat indefinitely". 623 // Special value "-1" means "repeat indefinitely".
541 if (cycles != -1) 624 if (cycles != -1)
542 cycles--; 625 cycles--;
543 } 626 }
544 return exit_code; 627 return exit_code;
545 } 628 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698