Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "base/test/launcher/test_launcher.h" | 5 #include "base/test/launcher/test_launcher.h" |
| 6 | 6 |
| 7 #if defined(OS_POSIX) | 7 #if defined(OS_POSIX) |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| 11 #include "base/at_exit.h" | 11 #include "base/at_exit.h" |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/environment.h" | 14 #include "base/environment.h" |
| 15 #include "base/file_util.h" | 15 #include "base/file_util.h" |
| 16 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
| 17 #include "base/format_macros.h" | 17 #include "base/format_macros.h" |
| 18 #include "base/lazy_instance.h" | 18 #include "base/lazy_instance.h" |
| 19 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/memory/scoped_ptr.h" | 20 #include "base/memory/scoped_ptr.h" |
| 21 #include "base/message_loop/message_loop.h" | 21 #include "base/message_loop/message_loop.h" |
| 22 #include "base/process/kill.h" | 22 #include "base/process/kill.h" |
| 23 #include "base/process/launch.h" | 23 #include "base/process/launch.h" |
| 24 #include "base/strings/string_number_conversions.h" | 24 #include "base/strings/string_number_conversions.h" |
| 25 #include "base/strings/string_split.h" | |
| 26 #include "base/strings/string_util.h" | |
| 25 #include "base/strings/stringprintf.h" | 27 #include "base/strings/stringprintf.h" |
| 26 #include "base/strings/utf_string_conversions.h" | 28 #include "base/strings/utf_string_conversions.h" |
| 27 #include "base/test/launcher/test_results_tracker.h" | 29 #include "base/test/launcher/test_results_tracker.h" |
| 28 #include "base/test/sequenced_worker_pool_owner.h" | 30 #include "base/test/sequenced_worker_pool_owner.h" |
| 29 #include "base/test/test_switches.h" | 31 #include "base/test/test_switches.h" |
| 30 #include "base/test/test_timeouts.h" | 32 #include "base/test/test_timeouts.h" |
| 31 #include "base/threading/thread_checker.h" | 33 #include "base/threading/thread_checker.h" |
| 32 #include "base/time/time.h" | 34 #include "base/time/time.h" |
| 33 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
| 34 | 36 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 // Returns true if bot mode has been requested, i.e. defaults optimized | 183 // Returns true if bot mode has been requested, i.e. defaults optimized |
| 182 // for continuous integration bots. This way developers don't have to remember | 184 // for continuous integration bots. This way developers don't have to remember |
| 183 // special command-line flags. | 185 // special command-line flags. |
| 184 bool BotModeEnabled() { | 186 bool BotModeEnabled() { |
| 185 scoped_ptr<Environment> env(Environment::Create()); | 187 scoped_ptr<Environment> env(Environment::Create()); |
| 186 return CommandLine::ForCurrentProcess()->HasSwitch( | 188 return CommandLine::ForCurrentProcess()->HasSwitch( |
| 187 switches::kTestLauncherBotMode) || | 189 switches::kTestLauncherBotMode) || |
| 188 env->HasVar("CHROMIUM_TEST_LAUNCHER_BOT_MODE"); | 190 env->HasVar("CHROMIUM_TEST_LAUNCHER_BOT_MODE"); |
| 189 } | 191 } |
| 190 | 192 |
| 191 // For a basic pattern matching for gtest_filter options. (Copied from | |
| 192 // gtest.cc, see the comment below and http://crbug.com/44497) | |
| 193 bool PatternMatchesString(const char* pattern, const char* str) { | |
| 194 switch (*pattern) { | |
| 195 case '\0': | |
| 196 case ':': // Either ':' or '\0' marks the end of the pattern. | |
| 197 return *str == '\0'; | |
| 198 case '?': // Matches any single character. | |
| 199 return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); | |
| 200 case '*': // Matches any string (possibly empty) of characters. | |
| 201 return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || | |
| 202 PatternMatchesString(pattern + 1, str); | |
| 203 default: // Non-special character. Matches itself. | |
| 204 return *pattern == *str && | |
| 205 PatternMatchesString(pattern + 1, str + 1); | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 // TODO(phajdan.jr): Avoid duplicating gtest code. (http://crbug.com/44497) | |
| 210 // For basic pattern matching for gtest_filter options. (Copied from | |
| 211 // gtest.cc) | |
| 212 bool MatchesFilter(const std::string& name, const std::string& filter) { | |
| 213 const char *cur_pattern = filter.c_str(); | |
| 214 for (;;) { | |
| 215 if (PatternMatchesString(cur_pattern, name.c_str())) { | |
| 216 return true; | |
| 217 } | |
| 218 | |
| 219 // Finds the next pattern in the filter. | |
| 220 cur_pattern = strchr(cur_pattern, ':'); | |
| 221 | |
| 222 // Returns if no more pattern can be found. | |
| 223 if (cur_pattern == NULL) { | |
| 224 return false; | |
| 225 } | |
| 226 | |
| 227 // Skips the pattern separater (the ':' character). | |
| 228 cur_pattern++; | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 void RunCallback( | 193 void RunCallback( |
| 233 const TestLauncher::LaunchChildGTestProcessCallback& callback, | 194 const TestLauncher::LaunchChildGTestProcessCallback& callback, |
| 234 int exit_code, | 195 int exit_code, |
| 235 const TimeDelta& elapsed_time, | 196 const TimeDelta& elapsed_time, |
| 236 bool was_timeout, | 197 bool was_timeout, |
| 237 const std::string& output) { | 198 const std::string& output) { |
| 238 callback.Run(exit_code, elapsed_time, was_timeout, output); | 199 callback.Run(exit_code, elapsed_time, was_timeout, output); |
| 239 } | 200 } |
| 240 | 201 |
| 241 void DoLaunchChildTestProcess( | 202 void DoLaunchChildTestProcess( |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 675 return false; | 636 return false; |
| 676 } | 637 } |
| 677 | 638 |
| 678 parallel_jobs_ = jobs; | 639 parallel_jobs_ = jobs; |
| 679 } | 640 } |
| 680 fprintf(stdout, "Using %" PRIuS " parallel jobs.\n", parallel_jobs_); | 641 fprintf(stdout, "Using %" PRIuS " parallel jobs.\n", parallel_jobs_); |
| 681 fflush(stdout); | 642 fflush(stdout); |
| 682 worker_pool_owner_.reset( | 643 worker_pool_owner_.reset( |
| 683 new SequencedWorkerPoolOwner(parallel_jobs_, "test_launcher")); | 644 new SequencedWorkerPoolOwner(parallel_jobs_, "test_launcher")); |
| 684 | 645 |
| 685 // Split --gtest_filter at '-', if there is one, to separate into | 646 if (command_line->HasSwitch(switches::kTestLauncherFilterFile) && |
| 686 // positive filter and negative filter portions. | 647 command_line->HasSwitch(kGTestFilterFlag)) { |
| 687 std::string filter = command_line->GetSwitchValueASCII(kGTestFilterFlag); | 648 LOG(ERROR) << "Only one of --test-launcher-filter-file and --gtest_filter " |
| 688 positive_test_filter_ = filter; | 649 << "at a time is allowed."; |
| 689 size_t dash_pos = filter.find('-'); | 650 return false; |
| 690 if (dash_pos != std::string::npos) { | 651 } |
| 691 // Everything up to the dash. | |
| 692 positive_test_filter_ = filter.substr(0, dash_pos); | |
| 693 | 652 |
| 694 // Everything after the dash. | 653 if (command_line->HasSwitch(switches::kTestLauncherFilterFile)) { |
| 695 negative_test_filter_ = filter.substr(dash_pos + 1); | 654 std::string filter; |
| 655 if (!ReadFileToString( | |
| 656 command_line->GetSwitchValuePath(switches::kTestLauncherFilterFile), | |
| 657 &filter)) { | |
| 658 LOG(ERROR) << "Failed to read the filter file."; | |
| 659 return false; | |
| 660 } | |
| 661 | |
| 662 std::vector<std::string> filter_lines; | |
| 663 SplitString(filter, '\n', &filter_lines); | |
| 664 for (size_t i = 0; i < filter_lines.size(); i++) { | |
| 665 if (filter_lines[i].empty()) | |
| 666 continue; | |
| 667 | |
| 668 if (filter_lines[i][0] == '-') | |
| 669 negative_test_filter_.push_back(filter_lines[i].substr(1)); | |
| 670 else | |
| 671 positive_test_filter_.push_back(filter_lines[i]); | |
| 672 } | |
| 673 } else { | |
| 674 // Split --gtest_filter at '-', if there is one, to separate into | |
|
sky
2013/12/18 17:19:59
I thought you could you multiple - patterns?
Paweł Hajdan Jr.
2013/12/18 17:50:30
You can. It's --gtest_filter=Test.Positive1:Test.P
sky
2013/12/18 21:48:42
I was thinking more of: Test.Positive1:Test.Positi
| |
| 675 // positive filter and negative filter portions. | |
| 676 std::string filter = command_line->GetSwitchValueASCII(kGTestFilterFlag); | |
| 677 size_t dash_pos = filter.find('-'); | |
| 678 if (dash_pos == std::string::npos) { | |
| 679 SplitString(filter, ':', &positive_test_filter_); | |
| 680 } else { | |
| 681 // Everything up to the dash. | |
| 682 SplitString(filter.substr(0, dash_pos), ':', &positive_test_filter_); | |
| 683 | |
| 684 // Everything after the dash. | |
| 685 SplitString(filter.substr(dash_pos + 1), ':', &negative_test_filter_); | |
| 686 } | |
| 696 } | 687 } |
| 697 | 688 |
| 698 if (!results_tracker_.Init(*command_line)) { | 689 if (!results_tracker_.Init(*command_line)) { |
| 699 LOG(ERROR) << "Failed to initialize test results tracker."; | 690 LOG(ERROR) << "Failed to initialize test results tracker."; |
| 700 return 1; | 691 return 1; |
| 701 } | 692 } |
| 702 | 693 |
| 703 return true; | 694 return true; |
| 704 } | 695 } |
| 705 | 696 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 721 // Skip disabled tests. | 712 // Skip disabled tests. |
| 722 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 713 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 723 if (test_name.find("DISABLED") != std::string::npos && | 714 if (test_name.find("DISABLED") != std::string::npos && |
| 724 !command_line->HasSwitch(kGTestRunDisabledTestsFlag)) { | 715 !command_line->HasSwitch(kGTestRunDisabledTestsFlag)) { |
| 725 continue; | 716 continue; |
| 726 } | 717 } |
| 727 | 718 |
| 728 std::string filtering_test_name = | 719 std::string filtering_test_name = |
| 729 launcher_delegate_->GetTestNameForFiltering(test_case, test_info); | 720 launcher_delegate_->GetTestNameForFiltering(test_case, test_info); |
| 730 | 721 |
| 731 // Skip the test that doesn't match the filter string (if given). | 722 // Skip the test that doesn't match the filter (if given). |
| 732 if ((!positive_test_filter_.empty() && | 723 if (!positive_test_filter_.empty()) { |
| 733 !MatchesFilter(filtering_test_name, positive_test_filter_)) || | 724 bool found = false; |
| 734 MatchesFilter(filtering_test_name, negative_test_filter_)) { | 725 for (size_t k = 0; k < positive_test_filter_.size(); ++k) { |
| 726 if (MatchPattern(filtering_test_name, positive_test_filter_[k])) { | |
| 727 found = true; | |
| 728 break; | |
| 729 } | |
| 730 } | |
| 731 | |
| 732 if (!found) | |
| 733 continue; | |
| 734 } | |
| 735 bool excluded = false; | |
| 736 for (size_t k = 0; k < negative_test_filter_.size(); ++k) { | |
| 737 if (MatchPattern(filtering_test_name, negative_test_filter_[k])) { | |
| 738 excluded = true; | |
| 739 break; | |
| 740 } | |
| 741 } | |
| 742 if (excluded) | |
| 735 continue; | 743 continue; |
| 736 } | |
| 737 | 744 |
| 738 if (!launcher_delegate_->ShouldRunTest(test_case, test_info)) | 745 if (!launcher_delegate_->ShouldRunTest(test_case, test_info)) |
| 739 continue; | 746 continue; |
| 740 | 747 |
| 741 if (num_runnable_tests++ % total_shards_ != shard_index_) | 748 if (num_runnable_tests++ % total_shards_ != shard_index_) |
| 742 continue; | 749 continue; |
| 743 | 750 |
| 744 test_names.push_back(test_name); | 751 test_names.push_back(test_name); |
| 745 } | 752 } |
| 746 } | 753 } |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1004 | 1011 |
| 1005 g_live_processes.Get().erase(process_handle); | 1012 g_live_processes.Get().erase(process_handle); |
| 1006 } | 1013 } |
| 1007 | 1014 |
| 1008 base::CloseProcessHandle(process_handle); | 1015 base::CloseProcessHandle(process_handle); |
| 1009 | 1016 |
| 1010 return exit_code; | 1017 return exit_code; |
| 1011 } | 1018 } |
| 1012 | 1019 |
| 1013 } // namespace base | 1020 } // namespace base |
| OLD | NEW |