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

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 test shard index.
71 static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
72 // The environment variable name for the total number of test shards.
73 static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
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,
84 // returns default_val. If it is not an Int32, prints an error
Paweł Hajdan Jr. 2011/01/14 09:32:45 This comment is lying. We print error and abort wh
chase 2011/01/14 23:39:35 Done.
85 // and aborts.
86 int32 Int32FromEnvOrDie(const char* const var, int32 default_val) {
87 scoped_ptr<base::Environment> env(base::Environment::Create());
88 std::string str_val;
89 int32 result;
90 if (!env->GetVar(var, &str_val))
91 return default_val;
92 if (!env->UnSetVar(var)) {
93 LOG(ERROR) << "Invalid environment: we could not unset " << var << ".\n";
94 exit(EXIT_FAILURE);
95 }
96 if (!base::StringToInt(str_val, &result))
97 return default_val;
98 return result;
99 }
100
101 // Checks whether sharding is enabled by examining the relevant
102 // environment variable values. If the variables are present,
103 // but inconsistent (i.e., shard_index >= total_shards), prints
104 // an error and exits.
105 bool ShouldShard(int32* total_shards, int32* shard_index) {
106 *total_shards = Int32FromEnvOrDie(kTestTotalShards, -1);
107 *shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
108
109 if (*total_shards == -1 && *shard_index == -1) {
110 return false;
111 } else if (*total_shards == -1 && *shard_index != -1) {
112 LOG(ERROR) << "Invalid environment variables: you have "
113 << kTestShardIndex << " = " << *shard_index
114 << ", but have left " << kTestTotalShards << " unset.\n";
115 exit(EXIT_FAILURE);
116 } else if (*total_shards != -1 && *shard_index == -1) {
117 LOG(ERROR) << "Invalid environment variables: you have "
118 << kTestTotalShards << " = " << *total_shards
119 << ", but have left " << kTestShardIndex << " unset.\n";
120 exit(EXIT_FAILURE);
121 } else if (*shard_index < 0 || *shard_index >= *total_shards) {
122 LOG(ERROR) << "Invalid environment variables: we require 0 <= "
123 << kTestShardIndex << " < " << kTestTotalShards
124 << ", but you have " << kTestShardIndex << "=" << *shard_index
125 << ", " << kTestTotalShards << "=" << *total_shards << ".\n";
126 exit(EXIT_FAILURE);
127 }
128
129 return *total_shards > 1;
130 }
131
132 // Given the total number of shards, the shard index, and the test id,
133 // returns true iff the test should be run on this shard. The test id is
134 // some arbitrary but unique non-negative integer assigned to each test
Paweł Hajdan Jr. 2011/01/14 09:32:45 nit: "assigned" -> "assigned by this launcher", to
chase 2011/01/14 23:39:35 Done.
135 // method. Assumes that 0 <= shard_index < total_shards.
Paweł Hajdan Jr. 2011/01/14 09:32:45 nit: Can we check that assumption?
chase 2011/01/14 23:39:35 This assumption is verified in ShouldShard(). I u
136 bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
137 return (test_id % total_shards) == shard_index;
138 }
139
77 // A helper class to output results. 140 // A helper class to output results.
78 // Note: as currently XML is the only supported format by gtest, we don't 141 // 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 142 // check output format (e.g. "xml:" prefix) here and output an XML file
80 // unconditionally. 143 // unconditionally.
81 // Note: we don't output per-test-case or total summary info like 144 // 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. 145 // 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 146 // Only each test (testcase element in the XML) will have the correct
84 // failed/disabled/elapsed_time information. Each test won't include 147 // failed/disabled/elapsed_time information. Each test won't include
85 // detailed failure messages either. 148 // detailed failure messages either.
86 class ResultsPrinter { 149 class ResultsPrinter {
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 // positive filter and negative filter portions. 421 // positive filter and negative filter portions.
359 std::string positive_filter = filter; 422 std::string positive_filter = filter;
360 std::string negative_filter = ""; 423 std::string negative_filter = "";
361 size_t dash_pos = filter.find('-'); 424 size_t dash_pos = filter.find('-');
362 if (dash_pos != std::string::npos) { 425 if (dash_pos != std::string::npos) {
363 positive_filter = filter.substr(0, dash_pos); // Everything up to the dash. 426 positive_filter = filter.substr(0, dash_pos); // Everything up to the dash.
364 negative_filter = filter.substr(dash_pos + 1); // Everything after the dash. 427 negative_filter = filter.substr(dash_pos + 1); // Everything after the dash.
365 } 428 }
366 429
367 int test_run_count = 0; 430 int test_run_count = 0;
431 int num_runnable_tests = 0;
368 int ignored_failure_count = 0; 432 int ignored_failure_count = 0;
369 std::vector<std::string> failed_tests; 433 std::vector<std::string> failed_tests;
370 434
435 int32 total_shards;
436 int32 shard_index;
437 bool should_shard = ShouldShard(&total_shards, &shard_index);
438 bool should_run;
Paweł Hajdan Jr. 2011/01/14 09:32:45 nit: Why is |should_run| declared here, so far fro
chase 2011/01/14 23:39:35 Moved below.
439
371 ResultsPrinter printer(*command_line); 440 ResultsPrinter printer(*command_line);
372 for (int i = 0; i < unit_test->total_test_case_count(); ++i) { 441 for (int i = 0; i < unit_test->total_test_case_count(); ++i) {
373 const testing::TestCase* test_case = unit_test->GetTestCase(i); 442 const testing::TestCase* test_case = unit_test->GetTestCase(i);
374 TestCasePrinterHelper helper(printer, test_case->name(), 443 TestCasePrinterHelper helper(printer, test_case->name(),
375 test_case->total_test_count()); 444 test_case->total_test_count());
376 for (int j = 0; j < test_case->total_test_count(); ++j) { 445 for (int j = 0; j < test_case->total_test_count(); ++j) {
377 const testing::TestInfo* test_info = test_case->GetTestInfo(j); 446 const testing::TestInfo* test_info = test_case->GetTestInfo(j);
378 // Skip disabled tests. 447 // Skip disabled tests.
379 if (std::string(test_info->name()).find("DISABLED") == 0 && 448 if (std::string(test_info->name()).find("DISABLED") == 0 &&
380 !command_line->HasSwitch(kGTestRunDisabledTestsFlag)) { 449 !command_line->HasSwitch(kGTestRunDisabledTestsFlag)) {
381 printer.OnTestEnd(test_info->name(), test_case->name(), 450 printer.OnTestEnd(test_info->name(), test_case->name(),
382 false, false, false, 0); 451 false, false, false, 0);
383 continue; 452 continue;
384 } 453 }
385 std::string test_name = test_info->test_case_name(); 454 std::string test_name = test_info->test_case_name();
386 test_name.append("."); 455 test_name.append(".");
387 test_name.append(test_info->name()); 456 test_name.append(test_info->name());
388 // Skip the test that doesn't match the filter string (if given). 457 // Skip the test that doesn't match the filter string (if given).
389 if ((!positive_filter.empty() && 458 if ((!positive_filter.empty() &&
390 !MatchesFilter(test_name, positive_filter)) || 459 !MatchesFilter(test_name, positive_filter)) ||
391 MatchesFilter(test_name, negative_filter)) { 460 MatchesFilter(test_name, negative_filter)) {
392 printer.OnTestEnd(test_info->name(), test_case->name(), 461 printer.OnTestEnd(test_info->name(), test_case->name(),
393 false, false, false, 0); 462 false, false, false, 0);
394 continue; 463 continue;
395 } 464 }
465 // Decide if this test should be run.
466 should_run = true;
Paweł Hajdan Jr. 2011/01/14 09:32:45 nit: It should be possible to declare bool should_
chase 2011/01/14 23:39:35 Declared here.
467 if (should_shard) {
468 should_run = ShouldRunTestOnShard(total_shards, shard_index,
469 num_runnable_tests);
470 }
471 num_runnable_tests += 1;
472 // If sharding is enabled and the test should not be run, skip it.
473 if (should_shard && !should_run) {
Paweł Hajdan Jr. 2011/01/14 09:32:45 nit: Is should_shard needed in the condition? If
chase 2011/01/14 23:39:35 Done.
474 continue;
475 }
396 base::Time start_time = base::Time::Now(); 476 base::Time start_time = base::Time::Now();
397 ++test_run_count; 477 ++test_run_count;
398 int exit_code = RunTest(test_name); 478 int exit_code = RunTest(test_name);
399 if (exit_code == 0) { 479 if (exit_code == 0) {
400 // Test passed. 480 // Test passed.
401 printer.OnTestEnd(test_info->name(), test_case->name(), true, false, 481 printer.OnTestEnd(test_info->name(), test_case->name(), true, false,
402 false, 482 false,
403 (base::Time::Now() - start_time).InMillisecondsF()); 483 (base::Time::Now() - start_time).InMillisecondsF());
404 } else { 484 } else {
405 failed_tests.push_back(test_name); 485 failed_tests.push_back(test_name);
406 486
407 bool ignore_failure = false; 487 bool ignore_failure = false;
408 488
409 // -1 exit code means a crash or hang. Never ignore those failures, 489 // -1 exit code means a crash or hang. Never ignore those failures,
410 // they are serious and should always be visible. 490 // they are serious and should always be visible.
411 if (exit_code != -1) 491 if (exit_code != -1)
412 ignore_failure = base::TestSuite::ShouldIgnoreFailure(*test_info); 492 ignore_failure = base::TestSuite::ShouldIgnoreFailure(*test_info);
413 493
414 printer.OnTestEnd(test_info->name(), test_case->name(), true, true, 494 printer.OnTestEnd(test_info->name(), test_case->name(), true, true,
415 ignore_failure, 495 ignore_failure,
416 (base::Time::Now() - start_time).InMillisecondsF()); 496 (base::Time::Now() - start_time).InMillisecondsF());
417 if (ignore_failure) 497 if (ignore_failure)
418 ++ignored_failure_count; 498 ++ignored_failure_count;
419 } 499 }
420 } 500 }
421 } 501 }
422 502
423 printf("%d test%s run\n", test_run_count, test_run_count > 1 ? "s" : ""); 503 printf("%d test%s run\n", test_run_count, test_run_count == 1 ? "" : "s");
Paweł Hajdan Jr. 2011/01/14 09:32:45 nit: Why? This change seems unrelated, I'd prefer
chase 2011/01/14 23:39:35 Removed.
424 printf("%d test%s failed (%d ignored)\n", 504 printf("%d test%s failed (%d ignored)\n",
425 static_cast<int>(failed_tests.size()), 505 static_cast<int>(failed_tests.size()),
426 failed_tests.size() > 1 ? "s" : "", ignored_failure_count); 506 failed_tests.size() == 1 ? "" : "s", ignored_failure_count);
Paweł Hajdan Jr. 2011/01/14 09:32:45 nit: Why? This change seems unrelated, I'd prefer
chase 2011/01/14 23:39:35 Removed.
427 if (failed_tests.size() - ignored_failure_count == 0) 507 if (failed_tests.size() - ignored_failure_count == 0)
428 return true; 508 return true;
429 509
430 printf("Failing tests:\n"); 510 printf("Failing tests:\n");
431 for (std::vector<std::string>::const_iterator iter = failed_tests.begin(); 511 for (std::vector<std::string>::const_iterator iter = failed_tests.begin();
432 iter != failed_tests.end(); ++iter) { 512 iter != failed_tests.end(); ++iter) {
433 printf("%s\n", iter->c_str()); 513 printf("%s\n", iter->c_str());
434 } 514 }
435 515
436 return false; 516 return false;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 exit_code = 1; 616 exit_code = 1;
537 break; 617 break;
538 } 618 }
539 619
540 // Special value "-1" means "repeat indefinitely". 620 // Special value "-1" means "repeat indefinitely".
541 if (cycles != -1) 621 if (cycles != -1)
542 cycles--; 622 cycles--;
543 } 623 }
544 return exit_code; 624 return exit_code;
545 } 625 }
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