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 |