Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(773)

Side by Side Diff: content/public/test/test_launcher.cc

Issue 17379024: GTTF: Extract a function to launch child gtest process. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: bugfix Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/test/test_launcher.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « base/test/test_launcher.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698