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

Side by Side Diff: scripts/slave/runtest.py

Issue 10636008: Convert runtest to have a built-in annotator. (Closed) Base URL: http://git.chromium.org/chromium/tools/build.git@master
Patch Set: Fix nits. Created 8 years, 5 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
« no previous file with comments | « scripts/slave/gtest_slave_utils.py ('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 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """A tool to run a chrome test executable, used by the buildbot slaves. 6 """A tool to run a chrome test executable, used by the buildbot slaves.
7 7
8 When this is run, the current directory (cwd) should be the outer build 8 When this is run, the current directory (cwd) should be the outer build
9 directory (e.g., chrome-release/build/). 9 directory (e.g., chrome-release/build/).
10 10
11 For a list of command-line options, call this script with '--help'. 11 For a list of command-line options, call this script with '--help'.
12 """ 12 """
13 13
14 import copy 14 import copy
15 import logging 15 import logging
16 import optparse 16 import optparse
17 import os 17 import os
18 import re
18 import stat 19 import stat
19 import sys 20 import sys
20 import tempfile 21 import tempfile
21 22
22 # sys.path needs to be modified here because python2.6 automatically adds the 23 # sys.path needs to be modified here because python2.6 automatically adds the
23 # system "google" module (/usr/lib/pymodules/python2.6/google) to sys.modules 24 # system "google" module (/usr/lib/pymodules/python2.6/google) to sys.modules
24 # when we import "chromium_config" (I don't know why it does this). This causes 25 # when we import "chromium_config" (I don't know why it does this). This causes
25 # the import of our local "google.*" modules to fail because python seems to 26 # the import of our local "google.*" modules to fail because python seems to
26 # only look for a system "google.*", even if our path is in sys.path before 27 # only look for a system "google.*", even if our path is in sys.path before
27 # importing "google.*". If we modify sys.path here, before importing 28 # importing "google.*". If we modify sys.path here, before importing
28 # "chromium_config", python2.6 properly uses our path to find our "google.*" 29 # "chromium_config", python2.6 properly uses our path to find our "google.*"
29 # (even though it still automatically adds the system "google" module to 30 # (even though it still automatically adds the system "google" module to
30 # sys.modules, and probably should still be using that to resolve "google.*", 31 # sys.modules, and probably should still be using that to resolve "google.*",
31 # which I really don't understand). 32 # which I really don't understand).
32 sys.path.insert(0, os.path.abspath('src/tools/python')) 33 sys.path.insert(0, os.path.abspath('src/tools/python'))
33 34
34 # Because of this dependency on a chromium checkout, we need to disable some 35 # Because of this dependency on a chromium checkout, we need to disable some
35 # pylint checks. 36 # pylint checks.
36 # pylint: disable=E0611 37 # pylint: disable=E0611
37 # pylint: disable=E1101 38 # pylint: disable=E1101
39 from buildbot.status import builder
40
38 from common import chromium_utils 41 from common import chromium_utils
42 from common import gtest_utils
39 from slave import gtest_slave_utils 43 from slave import gtest_slave_utils
40 from slave import slave_utils 44 from slave import slave_utils
41 from slave import xvfb 45 from slave import xvfb
42 import config 46 import config
43 47
44 USAGE = '%s [options] test.exe [test args]' % os.path.basename(sys.argv[0]) 48 USAGE = '%s [options] test.exe [test args]' % os.path.basename(sys.argv[0])
45 49
46 CHROME_SANDBOX_PATH = '/opt/chromium/chrome_sandbox' 50 CHROME_SANDBOX_PATH = '/opt/chromium/chrome_sandbox'
47 51
48 DEST_DIR = 'gtest_results' 52 DEST_DIR = 'gtest_results'
49 53
50 HTTPD_CONF = { 54 HTTPD_CONF = {
51 'linux': 'httpd2_linux.conf', 55 'linux': 'httpd2_linux.conf',
52 'mac': 'httpd2_mac.conf', 56 'mac': 'httpd2_mac.conf',
53 'win': 'httpd.conf' 57 'win': 'httpd.conf'
54 } 58 }
55 59
60
56 def should_enable_sandbox(sandbox_path): 61 def should_enable_sandbox(sandbox_path):
57 """Return a boolean indicating that the current slave is capable of using the 62 """Return a boolean indicating that the current slave is capable of using the
58 sandbox and should enable it. This should return True iff the slave is a 63 sandbox and should enable it. This should return True iff the slave is a
59 Linux host with the sandbox file present and configured correctly.""" 64 Linux host with the sandbox file present and configured correctly."""
60 if not (sys.platform.startswith('linux') and 65 if not (sys.platform.startswith('linux') and
61 os.path.exists(sandbox_path)): 66 os.path.exists(sandbox_path)):
62 return False 67 return False
63 sandbox_stat = os.stat(sandbox_path) 68 sandbox_stat = os.stat(sandbox_path)
64 if ((sandbox_stat.st_mode & stat.S_ISUID) and 69 if ((sandbox_stat.st_mode & stat.S_ISUID) and
65 (sandbox_stat.st_mode & stat.S_IRUSR) and 70 (sandbox_stat.st_mode & stat.S_IRUSR) and
66 (sandbox_stat.st_mode & stat.S_IXUSR) and 71 (sandbox_stat.st_mode & stat.S_IXUSR) and
67 (sandbox_stat.st_uid == 0)): 72 (sandbox_stat.st_uid == 0)):
68 return True 73 return True
69 return False 74 return False
70 75
76
71 def get_temp_count(): 77 def get_temp_count():
72 """Returns the number of files and directories inside the temporary dir.""" 78 """Returns the number of files and directories inside the temporary dir."""
73 return len(os.listdir(tempfile.gettempdir())) 79 return len(os.listdir(tempfile.gettempdir()))
74 80
75 81
76 def _RunGTestCommand(command, results_tracker=None, pipes=None): 82 def _RunGTestCommand(command, results_tracker=None, pipes=None):
77 if results_tracker and pipes: 83 if results_tracker and pipes:
78 # This is not supported by RunCommand. 84 # This is not supported by RunCommand.
79 print 'Invalid test invocation. (results_tracker and pipes)' 85 print 'Invalid test invocation. (results_tracker and pipes)'
80 return 1 86 return 1
81 if results_tracker: 87 if results_tracker:
82 return chromium_utils.RunCommand( 88 return chromium_utils.RunCommand(
83 command, parser_func=results_tracker.OnReceiveLine) 89 command, parser_func=results_tracker.ProcessLine)
84 else: 90 else:
85 return chromium_utils.RunCommand(command, pipes=pipes) 91 return chromium_utils.RunCommand(command, pipes=pipes)
86 92
87 93
88 def _GenerateJSONForTestResults(options, results_tracker): 94 def _GenerateJSONForTestResults(options, results_tracker):
89 """Generate (update) a JSON file from the gtest results XML and 95 """Generate (update) a JSON file from the gtest results XML and
90 upload the file to the archive server. 96 upload the file to the archive server.
91 The archived JSON file will be placed at: 97 The archived JSON file will be placed at:
92 www-dir/DEST_DIR/buildname/testname/results.json 98 www-dir/DEST_DIR/buildname/testname/results.json
93 on the archive server (NOTE: this is to be deprecated). 99 on the archive server (NOTE: this is to be deprecated).
94 Note that it adds slave's WebKit/Tools/Scripts to the PYTHONPATH 100 Note that it adds slave's WebKit/Tools/Scripts to the PYTHONPATH
95 to run the JSON generator. 101 to run the JSON generator.
96 102
97 Args: 103 Args:
98 options: command-line options that are supposed to have build_dir, 104 options: command-line options that are supposed to have build_dir,
99 results_directory, builder_name, build_name and test_output_xml values. 105 results_directory, builder_name, build_name and test_output_xml values.
100 """ 106 """
101 # pylint: disable=W0703 107 # pylint: disable=W0703
102 results_map = None 108 results_map = None
103 try: 109 try:
104 if os.path.exists(options.test_output_xml): 110 if os.path.exists(options.test_output_xml):
105 results_map = gtest_slave_utils.GetResultsMapFromXML( 111 results_map = gtest_slave_utils.GetResultsMapFromXML(
106 options.test_output_xml) 112 options.test_output_xml)
107 else: 113 else:
108 sys.stderr.write('Unable to generate JSON from XML, using log output.') 114 sys.stderr.write('Unable to generate JSON from XML, using log output.')
109 # The file did not get generated. See if we can generate a results map 115 # The file did not get generated. See if we can generate a results map
110 # from the log output. 116 # from the log output.
111 results_map = results_tracker.GetResultsMap() 117 results_map = gtest_slave_utils.GetResultsMap(results_tracker)
112 except Exception, e: 118 except Exception, e:
113 # This error will be caught by the following 'not results_map' statement. 119 # This error will be caught by the following 'not results_map' statement.
114 print 'Error: ', e 120 print 'Error: ', e
115 121
116 if not results_map: 122 if not results_map:
117 print 'No data was available to update the JSON results' 123 print 'No data was available to update the JSON results'
118 return 124 return
119 125
120 build_dir = os.path.abspath(options.build_dir) 126 build_dir = os.path.abspath(options.build_dir)
121 slave_name = slave_utils.SlaveBuildName(build_dir) 127 slave_name = slave_utils.SlaveBuildName(build_dir)
(...skipping 18 matching lines...) Expand all
140 146
141 # Generate results JSON file and upload it to the appspot server. 147 # Generate results JSON file and upload it to the appspot server.
142 gtest_slave_utils.GenerateAndUploadJSONResults( 148 gtest_slave_utils.GenerateAndUploadJSONResults(
143 results_map, generate_json_options) 149 results_map, generate_json_options)
144 150
145 # The code can throw all sorts of exceptions, including 151 # The code can throw all sorts of exceptions, including
146 # slave.gtest.networktransaction.NetworkTimeout so just trap everything. 152 # slave.gtest.networktransaction.NetworkTimeout so just trap everything.
147 except: # pylint: disable=W0702 153 except: # pylint: disable=W0702
148 print 'Unexpected error while generating JSON' 154 print 'Unexpected error while generating JSON'
149 155
156
150 def _BuildParallelCommand(build_dir, test_exe_path, options): 157 def _BuildParallelCommand(build_dir, test_exe_path, options):
151 supervisor_path = os.path.join(build_dir, '..', 'tools', 158 supervisor_path = os.path.join(build_dir, '..', 'tools',
152 'sharding_supervisor', 159 'sharding_supervisor',
153 'sharding_supervisor.py') 160 'sharding_supervisor.py')
154 supervisor_args = ['--no-color'] 161 supervisor_args = ['--no-color']
155 if options.factory_properties.get('retry_failed', True): 162 if options.factory_properties.get('retry_failed', True):
156 supervisor_args.append('--retry-failed') 163 supervisor_args.append('--retry-failed')
157 if options.total_shards and options.shard_index: 164 if options.total_shards and options.shard_index:
158 supervisor_args.extend(['--total-slaves', str(options.total_shards), 165 supervisor_args.extend(['--total-slaves', str(options.total_shards),
159 '--slave-index', str(options.shard_index - 1)]) 166 '--slave-index', str(options.shard_index - 1)])
160 if options.sharding_args: 167 if options.sharding_args:
161 supervisor_args.extend(options.sharding_args.split()) 168 supervisor_args.extend(options.sharding_args.split())
162 command = [sys.executable, supervisor_path] 169 command = [sys.executable, supervisor_path]
163 command.extend(supervisor_args) 170 command.extend(supervisor_args)
164 command.append(test_exe_path) 171 command.append(test_exe_path)
165 return command 172 return command
166 173
174
167 def start_http_server(platform, build_dir, test_exe_path, document_root): 175 def start_http_server(platform, build_dir, test_exe_path, document_root):
168 # pylint: disable=F0401 176 # pylint: disable=F0401
169 import google.httpd_utils 177 import google.httpd_utils
170 import google.platform_utils 178 import google.platform_utils
171 platform_util = google.platform_utils.PlatformUtility(build_dir) 179 platform_util = google.platform_utils.PlatformUtility(build_dir)
172 180
173 # Name the output directory for the exe, without its path or suffix. 181 # Name the output directory for the exe, without its path or suffix.
174 # e.g., chrome-release/httpd_logs/unit_tests/ 182 # e.g., chrome-release/httpd_logs/unit_tests/
175 test_exe_name = os.path.splitext(os.path.basename(test_exe_path))[0] 183 test_exe_name = os.path.splitext(os.path.basename(test_exe_path))[0]
176 output_dir = os.path.join(slave_utils.SlaveBaseDir(build_dir), 184 output_dir = os.path.join(slave_utils.SlaveBaseDir(build_dir),
(...skipping 22 matching lines...) Expand all
199 document_root) 207 document_root)
200 stop_cmd = platform_util.GetStopHttpdCommand() 208 stop_cmd = platform_util.GetStopHttpdCommand()
201 http_server = google.httpd_utils.ApacheHttpd(start_cmd, stop_cmd, [8000]) 209 http_server = google.httpd_utils.ApacheHttpd(start_cmd, stop_cmd, [8000])
202 try: 210 try:
203 http_server.StartServer() 211 http_server.StartServer()
204 except google.httpd_utils.HttpdNotStarted, e: 212 except google.httpd_utils.HttpdNotStarted, e:
205 raise google.httpd_utils.HttpdNotStarted('%s. See log file in %s' % 213 raise google.httpd_utils.HttpdNotStarted('%s. See log file in %s' %
206 (e, output_dir)) 214 (e, output_dir))
207 return http_server 215 return http_server
208 216
217
218 def getText(result, observer, name):
219 """Generate a text summary for the waterfall.
220
221 Updates the waterfall with any unusual test output, with a link to logs of
222 failed test steps.
223 """
224 GTEST_DASHBOARD_BASE = ('http://test-results.appspot.com'
225 '/dashboards/flakiness_dashboard.html')
226
227 # basic_info is an array of lines to display on the waterfall
228 basic_info = [name]
229
230 disabled = observer.DisabledTests()
231 if disabled:
232 basic_info.append('%s disabled' % str(disabled))
233
234 flaky = observer.FlakyTests()
235 if flaky:
236 basic_info.append('%s flaky' % str(flaky))
237
238 failed_test_count = len(observer.FailedTests())
239
240 if failed_test_count == 0:
241 if result is builder.SUCCESS:
242 return basic_info
243 elif result is builder.WARNINGS:
244 return basic_info + ['warnings']
245
246 if observer.RunningTests():
247
248 basic_info += ['did not complete']
249
250 # TODO(xusydoc): see if 'crashed or hung' should be tracked by RunningTests()
251 if failed_test_count:
252 failure_text = ['failed %d' % failed_test_count]
253 if observer.master_name:
254 # Include the link to the flakiness dashboard
255 failure_text.append('<div class="BuildResultInfo">')
256 failure_text.append('<a href="%s#master=%s&testType=%s'
257 '&tests=%s">' % (
258 GTEST_DASHBOARD_BASE, observer.master_name,
259 name,
260 ','.join(observer.FailedTests())))
261 failure_text.append('Flakiness dashboard')
262 failure_text.append('</a>')
263 failure_text.append('</div>')
264 else:
265 failure_text = ['crashed or hung']
266 return basic_info + failure_text
267
268
269 def annotate(test_name, result, results_tracker):
270 """Given a test result and tracker, update the waterfall with test results."""
271 get_text_result = builder.SUCCESS
272
273 for failure in sorted(results_tracker.FailedTests()):
274 testabbr = re.sub(r'[^\w\.\-]', '_', failure.split('.')[-1])
275 for line in results_tracker.FailureDescription(failure):
276 print '@@@STEP_LOG_LINE@%s@%s@@@' % (testabbr, line)
277 print '@@@STEP_LOG_END@%s@@@' % testabbr
278
279 for suppression_hash in sorted(results_tracker.SuppressionHashes()):
280 for line in results_tracker.Suppression(suppression_hash):
281 print '@@@STEP_LOG_LINE@%s@%s@@@' % (testabbr, line)
282 print '@@@STEP_LOG_END@%s@@@' % testabbr
283
284 if results_tracker.ParsingErrors():
285 # Generate a log file containing the list of errors.
286 for line in results_tracker.ParsingErrors():
287 print '@@@STEP_LOG_LINE@%s@%s@@@' % ('log parsing error(s)', line)
288
289 print '@@@STEP_LOG_END@%s@@@' % 'log parsing error(s)'
290 results_tracker.ClearParsingErrors()
291
292 if result is builder.SUCCESS:
293 if (len(results_tracker.ParsingErrors()) or
294 len(results_tracker.FailedTests()) or
295 len(results_tracker.SuppressionHashes())):
296 print '@@@STEP_WARNINGS@@@'
297 get_text_result = builder.WARNING
298 else:
299 print '@@@STEP_FAILURE@@@'
300 get_text_result = builder.FAILURE
301
302 for desc in getText(get_text_result, results_tracker, test_name):
303 print '@@@STEP_TEXT@%s@@@' % desc
304
305
209 def main_mac(options, args): 306 def main_mac(options, args):
210 if len(args) < 1: 307 if len(args) < 1:
211 raise chromium_utils.MissingArgument('Usage: %s' % USAGE) 308 raise chromium_utils.MissingArgument('Usage: %s' % USAGE)
212 309
213 test_exe = args[0] 310 test_exe = args[0]
214 build_dir = os.path.normpath(os.path.abspath(options.build_dir)) 311 build_dir = os.path.normpath(os.path.abspath(options.build_dir))
215 test_exe_path = os.path.join(build_dir, options.target, test_exe) 312 test_exe_path = os.path.join(build_dir, options.target, test_exe)
216 if not os.path.exists(test_exe_path): 313 if not os.path.exists(test_exe_path):
217 pre = 'Unable to find %s\n' % test_exe_path 314 pre = 'Unable to find %s\n' % test_exe_path
218 315
(...skipping 22 matching lines...) Expand all
241 command = _BuildParallelCommand(build_dir, test_exe_path, options) 338 command = _BuildParallelCommand(build_dir, test_exe_path, options)
242 elif options.run_shell_script: 339 elif options.run_shell_script:
243 command = ['bash', test_exe_path] 340 command = ['bash', test_exe_path]
244 elif options.run_python_script: 341 elif options.run_python_script:
245 command = [sys.executable, test_exe] 342 command = [sys.executable, test_exe]
246 else: 343 else:
247 command = [test_exe_path] 344 command = [test_exe_path]
248 command.extend(args[1:]) 345 command.extend(args[1:])
249 346
250 results_tracker = None 347 results_tracker = None
348 if options.generate_json_file or options.annotate:
349 results_tracker = gtest_utils.GTestLogParser()
350
251 if options.generate_json_file: 351 if options.generate_json_file:
252 results_tracker = gtest_slave_utils.GTestUnexpectedDeathTracker()
253
254 if os.path.exists(options.test_output_xml): 352 if os.path.exists(options.test_output_xml):
255 # remove the old XML output file. 353 # remove the old XML output file.
256 os.remove(options.test_output_xml) 354 os.remove(options.test_output_xml)
257 355
258 try: 356 try:
259 http_server = None 357 http_server = None
260 if options.document_root: 358 if options.document_root:
261 http_server = start_http_server('mac', build_dir=build_dir, 359 http_server = start_http_server('mac', build_dir=build_dir,
262 test_exe_path=test_exe_path, 360 test_exe_path=test_exe_path,
263 document_root=options.document_root) 361 document_root=options.document_root)
264 if options.factory_properties.get('asan', False): 362 if options.factory_properties.get('asan', False):
265 symbolize = os.path.abspath(os.path.join('src', 'tools', 'valgrind', 363 symbolize = os.path.abspath(os.path.join('src', 'tools', 'valgrind',
266 'asan', 'asan_symbolize.py')) 364 'asan', 'asan_symbolize.py'))
267 pipes = [[sys.executable, symbolize], ['c++filt']] 365 pipes = [[sys.executable, symbolize], ['c++filt']]
268 result = _RunGTestCommand(command, pipes=pipes) 366 result = _RunGTestCommand(command, pipes=pipes)
269 else: 367 else:
270 result = _RunGTestCommand(command, results_tracker) 368 result = _RunGTestCommand(command, results_tracker)
271 finally: 369 finally:
272 if http_server: 370 if http_server:
273 http_server.StopServer() 371 http_server.StopServer()
274 372
275 if options.generate_json_file: 373 if options.generate_json_file:
276 _GenerateJSONForTestResults(options, results_tracker) 374 _GenerateJSONForTestResults(options, results_tracker)
277 375
376 if options.annotate:
377 annotate(options.test_type, result, results_tracker)
378
278 return result 379 return result
279 380
381
280 def main_linux(options, args): 382 def main_linux(options, args):
281 if len(args) < 1: 383 if len(args) < 1:
282 raise chromium_utils.MissingArgument('Usage: %s' % USAGE) 384 raise chromium_utils.MissingArgument('Usage: %s' % USAGE)
283 385
284 build_dir = os.path.normpath(os.path.abspath(options.build_dir)) 386 build_dir = os.path.normpath(os.path.abspath(options.build_dir))
285 slave_name = slave_utils.SlaveBuildName(build_dir) 387 slave_name = slave_utils.SlaveBuildName(build_dir)
286 # If this is a sub-project build (i.e. there's a 'sconsbuild' in build_dir), 388 # If this is a sub-project build (i.e. there's a 'sconsbuild' in build_dir),
287 # look for the test binaries there, otherwise look for the top-level build 389 # look for the test binaries there, otherwise look for the top-level build
288 # output. 390 # output.
289 # This assumes we never pass a build_dir which might contain build output that 391 # This assumes we never pass a build_dir which might contain build output that
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 command = _BuildParallelCommand(build_dir, test_exe_path, options) 455 command = _BuildParallelCommand(build_dir, test_exe_path, options)
354 elif options.run_shell_script: 456 elif options.run_shell_script:
355 command = ['bash', test_exe_path] 457 command = ['bash', test_exe_path]
356 elif options.run_python_script: 458 elif options.run_python_script:
357 command = [sys.executable, test_exe] 459 command = [sys.executable, test_exe]
358 else: 460 else:
359 command = [test_exe_path] 461 command = [test_exe_path]
360 command.extend(args[1:]) 462 command.extend(args[1:])
361 463
362 results_tracker = None 464 results_tracker = None
465 if options.generate_json_file or options.annotate:
466 results_tracker = gtest_utils.GTestLogParser()
467
363 if options.generate_json_file: 468 if options.generate_json_file:
364 results_tracker = gtest_slave_utils.GTestUnexpectedDeathTracker()
365
366 if os.path.exists(options.test_output_xml): 469 if os.path.exists(options.test_output_xml):
367 # remove the old XML output file. 470 # remove the old XML output file.
368 os.remove(options.test_output_xml) 471 os.remove(options.test_output_xml)
369 472
370 try: 473 try:
371 http_server = None 474 http_server = None
372 if options.document_root: 475 if options.document_root:
373 http_server = start_http_server('linux', build_dir=build_dir, 476 http_server = start_http_server('linux', build_dir=build_dir,
374 test_exe_path=test_exe_path, 477 test_exe_path=test_exe_path,
375 document_root=options.document_root) 478 document_root=options.document_root)
(...skipping 11 matching lines...) Expand all
387 result = _RunGTestCommand(command, results_tracker) 490 result = _RunGTestCommand(command, results_tracker)
388 finally: 491 finally:
389 if http_server: 492 if http_server:
390 http_server.StopServer() 493 http_server.StopServer()
391 if options.xvfb: 494 if options.xvfb:
392 xvfb.StopVirtualX(slave_name) 495 xvfb.StopVirtualX(slave_name)
393 496
394 if options.generate_json_file: 497 if options.generate_json_file:
395 _GenerateJSONForTestResults(options, results_tracker) 498 _GenerateJSONForTestResults(options, results_tracker)
396 499
500 if options.annotate:
501 annotate(options.test_type, result, results_tracker)
502
397 return result 503 return result
398 504
505
399 def main_win(options, args): 506 def main_win(options, args):
400 """Using the target build configuration, run the executable given in the 507 """Using the target build configuration, run the executable given in the
401 first non-option argument, passing any following arguments to that 508 first non-option argument, passing any following arguments to that
402 executable. 509 executable.
403 """ 510 """
404 if len(args) < 1: 511 if len(args) < 1:
405 raise chromium_utils.MissingArgument('Usage: %s' % USAGE) 512 raise chromium_utils.MissingArgument('Usage: %s' % USAGE)
406 513
407 test_exe = args[0] 514 test_exe = args[0]
408 build_dir = os.path.abspath(options.build_dir) 515 build_dir = os.path.abspath(options.build_dir)
(...skipping 14 matching lines...) Expand all
423 command = [sys.executable, test_exe] 530 command = [sys.executable, test_exe]
424 else: 531 else:
425 command = [test_exe_path] 532 command = [test_exe_path]
426 command.extend(args[1:]) 533 command.extend(args[1:])
427 534
428 # Nuke anything that appears to be stale chrome items in the temporary 535 # Nuke anything that appears to be stale chrome items in the temporary
429 # directory from previous test runs (i.e.- from crashes or unittest leaks). 536 # directory from previous test runs (i.e.- from crashes or unittest leaks).
430 slave_utils.RemoveChromeTemporaryFiles() 537 slave_utils.RemoveChromeTemporaryFiles()
431 538
432 results_tracker = None 539 results_tracker = None
540 if options.generate_json_file or options.annotate:
541 results_tracker = gtest_utils.GTestLogParser()
542
433 if options.generate_json_file: 543 if options.generate_json_file:
434 results_tracker = gtest_slave_utils.GTestUnexpectedDeathTracker()
435
436 if os.path.exists(options.test_output_xml): 544 if os.path.exists(options.test_output_xml):
437 # remove the old XML output file. 545 # remove the old XML output file.
438 os.remove(options.test_output_xml) 546 os.remove(options.test_output_xml)
439 547
440 try: 548 try:
441 http_server = None 549 http_server = None
442 if options.document_root: 550 if options.document_root:
443 http_server = start_http_server('win', build_dir=build_dir, 551 http_server = start_http_server('win', build_dir=build_dir,
444 test_exe_path=test_exe_path, 552 test_exe_path=test_exe_path,
445 document_root=options.document_root) 553 document_root=options.document_root)
446 result = _RunGTestCommand(command, results_tracker) 554 result = _RunGTestCommand(command, results_tracker)
447 finally: 555 finally:
448 if http_server: 556 if http_server:
449 http_server.StopServer() 557 http_server.StopServer()
450 558
451 if options.enable_pageheap: 559 if options.enable_pageheap:
452 slave_utils.SetPageHeap(build_dir, 'chrome.exe', False) 560 slave_utils.SetPageHeap(build_dir, 'chrome.exe', False)
453 561
454 if options.generate_json_file: 562 if options.generate_json_file:
455 _GenerateJSONForTestResults(options, results_tracker) 563 _GenerateJSONForTestResults(options, results_tracker)
456 564
565 if options.annotate:
566 annotate(options.test_type, result, results_tracker)
567
457 return result 568 return result
458 569
459 570
460 def main(): 571 def main():
461 import platform 572 import platform
462 573
463 xvfb_path = os.path.join(os.path.dirname(sys.argv[0]), '..', '..', 574 xvfb_path = os.path.join(os.path.dirname(sys.argv[0]), '..', '..',
464 'third_party', 'xvfb', platform.architecture()[0]) 575 'third_party', 'xvfb', platform.architecture()[0])
465 576
466 # Initialize logging. 577 # Initialize logging.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 help="The name of the builder running this script.") 655 help="The name of the builder running this script.")
545 option_parser.add_option("", "--build-number", default=None, 656 option_parser.add_option("", "--build-number", default=None,
546 help=("The build number of the builder running" 657 help=("The build number of the builder running"
547 "this script.")) 658 "this script."))
548 option_parser.add_option("", "--test-type", default='', 659 option_parser.add_option("", "--test-type", default='',
549 help="The test name that identifies the test, " 660 help="The test name that identifies the test, "
550 "e.g. 'unit-tests'") 661 "e.g. 'unit-tests'")
551 option_parser.add_option("", "--test-results-server", default='', 662 option_parser.add_option("", "--test-results-server", default='',
552 help="The test results server to upload the " 663 help="The test results server to upload the "
553 "results.") 664 "results.")
665 option_parser.add_option('', '--annotate', action='store_true',
666 dest = 'annotate', default=False,
667 help='Annotate output when run as a buildstep.')
554 chromium_utils.AddPropertiesOptions(option_parser) 668 chromium_utils.AddPropertiesOptions(option_parser)
555 options, args = option_parser.parse_args() 669 options, args = option_parser.parse_args()
556 670
557 if options.run_shell_script and options.run_python_script: 671 if options.run_shell_script and options.run_python_script:
558 sys.stderr.write('Use either --run-shell-script OR --run-python-script, ' 672 sys.stderr.write('Use either --run-shell-script OR --run-python-script, '
559 'not both.') 673 'not both.')
560 return 1 674 return 1
561 675
562 # Print out builder name for log_parser 676 # Print out builder name for log_parser
563 print '[Running on builder: "%s"]' % options.builder_name 677 print '[Running on builder: "%s"]' % options.builder_name
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 '%d new files were left in %s: Fix the tests to clean up themselves.' 712 '%d new files were left in %s: Fix the tests to clean up themselves.'
599 ) % ((new_temp_files - temp_files), tempfile.gettempdir()) 713 ) % ((new_temp_files - temp_files), tempfile.gettempdir())
600 # TODO(maruel): Make it an error soon. Not yet since I want to iron out all 714 # TODO(maruel): Make it an error soon. Not yet since I want to iron out all
601 # the remaining cases before. 715 # the remaining cases before.
602 #result = 1 716 #result = 1
603 return result 717 return result
604 718
605 719
606 if '__main__' == __name__: 720 if '__main__' == __name__:
607 sys.exit(main()) 721 sys.exit(main())
OLDNEW
« no previous file with comments | « scripts/slave/gtest_slave_utils.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698