OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |