OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/public/test/test_launcher.h" | 5 #include "content/public/test/test_launcher.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 // add a new binary that must be compiled on all builds. | 56 // add a new binary that must be compiled on all builds. |
57 const char kManualTestPrefix[] = "MANUAL_"; | 57 const char kManualTestPrefix[] = "MANUAL_"; |
58 | 58 |
59 TestLauncherDelegate* g_launcher_delegate; | 59 TestLauncherDelegate* g_launcher_delegate; |
60 } | 60 } |
61 | 61 |
62 namespace { | 62 namespace { |
63 | 63 |
64 int DoRunTestInternal(const testing::TestCase* test_case, | 64 int DoRunTestInternal(const testing::TestCase* test_case, |
65 const std::string& test_name, | 65 const std::string& test_name, |
66 CommandLine* command_line, | 66 const CommandLine& command_line, |
67 base::TimeDelta default_timeout, | 67 base::TimeDelta default_timeout, |
68 bool* was_timeout) { | 68 bool* was_timeout) { |
69 if (test_case) { | 69 if (test_case) { |
70 std::string pre_test_name = test_name; | 70 std::string pre_test_name = test_name; |
71 std::string replace_string = std::string(".") + kPreTestPrefix; | 71 std::string replace_string = std::string(".") + kPreTestPrefix; |
72 ReplaceFirstSubstringAfterOffset(&pre_test_name, 0, ".", replace_string); | 72 ReplaceFirstSubstringAfterOffset(&pre_test_name, 0, ".", replace_string); |
73 for (int i = 0; i < test_case->total_test_count(); ++i) { | 73 for (int i = 0; i < test_case->total_test_count(); ++i) { |
74 const testing::TestInfo* test_info = test_case->GetTestInfo(i); | 74 const testing::TestInfo* test_info = test_case->GetTestInfo(i); |
75 std::string cur_test_name = test_info->test_case_name(); | 75 std::string cur_test_name = test_info->test_case_name(); |
76 cur_test_name.append("."); | 76 cur_test_name.append("."); |
77 cur_test_name.append(test_info->name()); | 77 cur_test_name.append(test_info->name()); |
78 if (cur_test_name == pre_test_name) { | 78 if (cur_test_name == pre_test_name) { |
79 int exit_code = DoRunTestInternal(test_case, | 79 int exit_code = DoRunTestInternal(test_case, |
80 pre_test_name, | 80 pre_test_name, |
81 command_line, | 81 command_line, |
82 default_timeout, | 82 default_timeout, |
83 was_timeout); | 83 was_timeout); |
84 if (exit_code != 0) | 84 if (exit_code != 0) |
85 return exit_code; | 85 return exit_code; |
86 } | 86 } |
87 } | 87 } |
88 } | 88 } |
89 | 89 |
90 CommandLine new_cmd_line(*command_line); | 90 CommandLine new_cmd_line(command_line); |
91 | 91 |
92 // Always enable disabled tests. This method is not called with disabled | 92 // Always enable disabled tests. This method is not called with disabled |
93 // tests unless this flag was specified to the browser test executable. | 93 // tests unless this flag was specified to the browser test executable. |
94 new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests"); | 94 new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests"); |
95 new_cmd_line.AppendSwitchASCII("gtest_filter", test_name); | 95 new_cmd_line.AppendSwitchASCII("gtest_filter", test_name); |
96 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); | 96 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); |
97 | 97 |
98 const char* browser_wrapper = getenv("BROWSER_WRAPPER"); | 98 int exit_code = base::LaunchChildGTestProcess(new_cmd_line, |
99 if (browser_wrapper) { | 99 default_timeout, |
100 #if defined(OS_WIN) | 100 was_timeout); |
101 new_cmd_line.PrependWrapper(ASCIIToWide(browser_wrapper)); | 101 if (*was_timeout) { |
102 #elif defined(OS_POSIX) | |
103 new_cmd_line.PrependWrapper(browser_wrapper); | |
104 #endif | |
105 VLOG(1) << "BROWSER_WRAPPER was set, prefixing command_line with " | |
106 << browser_wrapper; | |
107 } | |
108 | |
109 base::ProcessHandle process_handle; | |
110 base::LaunchOptions options; | |
111 | |
112 #if defined(OS_POSIX) | |
113 // On POSIX, we launch the test in a new process group with pgid equal to | |
114 // its pid. Any child processes that the test may create will inherit the | |
115 // same pgid. This way, if the test is abruptly terminated, we can clean up | |
116 // any orphaned child processes it may have left behind. | |
117 options.new_process_group = true; | |
118 #endif | |
119 | |
120 if (!base::LaunchProcess(new_cmd_line, options, &process_handle)) | |
121 return -1; | |
122 | |
123 int exit_code = 0; | |
124 if (!base::WaitForExitCodeWithTimeout(process_handle, | |
125 &exit_code, | |
126 default_timeout)) { | |
127 LOG(ERROR) << "Test timeout (" << default_timeout.InMilliseconds() | 102 LOG(ERROR) << "Test timeout (" << default_timeout.InMilliseconds() |
128 << " ms) exceeded for " << test_name; | 103 << " ms) exceeded for " << test_name; |
129 | |
130 if (was_timeout) | |
131 *was_timeout = true; | |
132 exit_code = -1; // Set a non-zero exit code to signal a failure. | |
133 | |
134 // Ensure that the process terminates. | |
135 base::KillProcess(process_handle, -1, true); | |
136 } | 104 } |
137 | 105 |
138 #if defined(OS_POSIX) | |
139 if (exit_code != 0) { | |
140 // On POSIX, in case the test does not exit cleanly, either due to a crash | |
141 // or due to it timing out, we need to clean up any child processes that | |
142 // it might have created. On Windows, child processes are automatically | |
143 // cleaned up using JobObjects. | |
144 base::KillProcessGroup(process_handle); | |
145 } | |
146 #endif | |
147 | |
148 base::CloseProcessHandle(process_handle); | |
149 | |
150 return exit_code; | 106 return exit_code; |
151 } | 107 } |
152 | 108 |
153 // Runs test specified by |test_name| in a child process, | 109 // Runs test specified by |test_name| in a child process, |
154 // and returns the exit code. | 110 // and returns the exit code. |
155 int DoRunTest(TestLauncherDelegate* launcher_delegate, | 111 int DoRunTest(TestLauncherDelegate* launcher_delegate, |
156 const testing::TestCase* test_case, | 112 const testing::TestCase* test_case, |
157 const std::string& test_name, | 113 const std::string& test_name, |
158 base::TimeDelta default_timeout, | 114 base::TimeDelta default_timeout, |
159 bool* was_timeout) { | 115 bool* was_timeout) { |
160 if (was_timeout) | 116 if (was_timeout) |
161 *was_timeout = false; | 117 *was_timeout = false; |
162 | 118 |
163 #if defined(OS_MACOSX) | 119 #if defined(OS_MACOSX) |
164 // Some of the below method calls will leak objects if there is no | 120 // Some of the below method calls will leak objects if there is no |
165 // autorelease pool in place. | 121 // autorelease pool in place. |
166 base::mac::ScopedNSAutoreleasePool pool; | 122 base::mac::ScopedNSAutoreleasePool pool; |
167 #endif | 123 #endif |
168 | 124 |
169 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | |
170 CommandLine new_cmd_line(cmd_line->GetProgram()); | |
171 CommandLine::SwitchMap switches = cmd_line->GetSwitches(); | |
172 | |
173 // Strip out gtest_output flag because otherwise we would overwrite results | |
174 // of the previous test. We will generate the final output file later | |
175 // in RunTests(). | |
176 switches.erase(base::kGTestOutputFlag); | |
177 | |
178 // Strip out gtest_repeat flag because we can only run one test in the child | |
179 // process (restarting the browser in the same process is illegal after it | |
180 // has been shut down and will actually crash). | |
181 switches.erase(base::kGTestRepeatFlag); | |
182 | |
183 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); | |
184 iter != switches.end(); ++iter) { | |
185 new_cmd_line.AppendSwitchNative((*iter).first, (*iter).second); | |
186 } | |
187 | |
188 base::ScopedTempDir temp_dir; | 125 base::ScopedTempDir temp_dir; |
189 // Create a new data dir and pass it to the child. | 126 // Create a new data dir and pass it to the child. |
190 if (!temp_dir.CreateUniqueTempDir() || !temp_dir.IsValid()) { | 127 if (!temp_dir.CreateUniqueTempDir() || !temp_dir.IsValid()) { |
191 LOG(ERROR) << "Error creating temp data directory"; | 128 LOG(ERROR) << "Error creating temp data directory"; |
192 return -1; | 129 return -1; |
193 } | 130 } |
194 | 131 |
| 132 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); |
| 133 |
| 134 const char* browser_wrapper = getenv("BROWSER_WRAPPER"); |
| 135 if (browser_wrapper) { |
| 136 #if defined(OS_WIN) |
| 137 new_cmd_line.PrependWrapper(ASCIIToWide(browser_wrapper)); |
| 138 #elif defined(OS_POSIX) |
| 139 new_cmd_line.PrependWrapper(browser_wrapper); |
| 140 #endif |
| 141 VLOG(1) << "BROWSER_WRAPPER was set, prefixing command_line with " |
| 142 << browser_wrapper; |
| 143 } |
| 144 |
195 if (!launcher_delegate->AdjustChildProcessCommandLine(&new_cmd_line, | 145 if (!launcher_delegate->AdjustChildProcessCommandLine(&new_cmd_line, |
196 temp_dir.path())) { | 146 temp_dir.path())) { |
197 return -1; | 147 return -1; |
198 } | 148 } |
199 | 149 |
200 return DoRunTestInternal( | 150 return DoRunTestInternal( |
201 test_case, test_name, &new_cmd_line, default_timeout, was_timeout); | 151 test_case, test_name, new_cmd_line, default_timeout, was_timeout); |
202 } | 152 } |
203 | 153 |
204 void PrintUsage() { | 154 void PrintUsage() { |
205 fprintf(stdout, | 155 fprintf(stdout, |
206 "Runs tests using the gtest framework, each test being run in its own\n" | 156 "Runs tests using the gtest framework, each test being run in its own\n" |
207 "process. Any gtest flags can be specified.\n" | 157 "process. Any gtest flags can be specified.\n" |
208 " --single_process\n" | 158 " --single_process\n" |
209 " Runs the tests and the launcher in the same process. Useful for \n" | 159 " Runs the tests and the launcher in the same process. Useful for \n" |
210 " debugging a specific test in a debugger.\n" | 160 " debugging a specific test in a debugger.\n" |
211 " --single-process\n" | 161 " --single-process\n" |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 | 352 |
403 WrapperTestLauncherDelegate delegate(launcher_delegate); | 353 WrapperTestLauncherDelegate delegate(launcher_delegate); |
404 return base::LaunchTests(&delegate, argc, argv); | 354 return base::LaunchTests(&delegate, argc, argv); |
405 } | 355 } |
406 | 356 |
407 TestLauncherDelegate* GetCurrentTestLauncherDelegate() { | 357 TestLauncherDelegate* GetCurrentTestLauncherDelegate() { |
408 return g_launcher_delegate; | 358 return g_launcher_delegate; |
409 } | 359 } |
410 | 360 |
411 } // namespace content | 361 } // namespace content |
OLD | NEW |