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