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

Side by Side Diff: presubmit_support.py

Issue 99453003: Print test duration in verbose mode. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 7 years 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 | « presubmit_canned_checks.py ('k') | tests/presubmit_unittest.py » ('j') | 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 """Enables directory-specific presubmit checks to run at upload and/or commit. 6 """Enables directory-specific presubmit checks to run at upload and/or commit.
7 """ 7 """
8 8
9 __version__ = '1.7.0' 9 __version__ = '1.7.0'
10 10
11 # TODO(joi) Add caching where appropriate/needed. The API is designed to allow 11 # TODO(joi) Add caching where appropriate/needed. The API is designed to allow
12 # caching (between all different invocations of presubmit scripts for a given 12 # caching (between all different invocations of presubmit scripts for a given
13 # change). We should add it as our presubmit scripts start feeling slow. 13 # change). We should add it as our presubmit scripts start feeling slow.
14 14
15 import cpplint 15 import cpplint
16 import cPickle # Exposed through the API. 16 import cPickle # Exposed through the API.
17 import cStringIO # Exposed through the API. 17 import cStringIO # Exposed through the API.
18 import collections
19 import contextlib 18 import contextlib
20 import fnmatch 19 import fnmatch
21 import glob 20 import glob
22 import inspect 21 import inspect
23 import json # Exposed through the API. 22 import json # Exposed through the API.
24 import logging 23 import logging
25 import marshal # Exposed through the API. 24 import marshal # Exposed through the API.
26 import multiprocessing 25 import multiprocessing
27 import optparse 26 import optparse
28 import os # Somewhat exposed through the API. 27 import os # Somewhat exposed through the API.
(...skipping 20 matching lines...) Expand all
49 48
50 49
51 # Ask for feedback only once in program lifetime. 50 # Ask for feedback only once in program lifetime.
52 _ASKED_FOR_FEEDBACK = False 51 _ASKED_FOR_FEEDBACK = False
53 52
54 53
55 class PresubmitFailure(Exception): 54 class PresubmitFailure(Exception):
56 pass 55 pass
57 56
58 57
59 CommandData = collections.namedtuple('CommandData', 58 class CommandData(object):
60 ['name', 'cmd', 'kwargs', 'message']) 59 def __init__(self, name, cmd, kwargs, message):
60 self.name = name
61 self.cmd = cmd
62 self.kwargs = kwargs
63 self.message = message
64 self.info = None
65
61 66
62 def normpath(path): 67 def normpath(path):
63 '''Version of os.path.normpath that also changes backward slashes to 68 '''Version of os.path.normpath that also changes backward slashes to
64 forward slashes when not running on Windows. 69 forward slashes when not running on Windows.
65 ''' 70 '''
66 # This is safe to always do because the Windows version of os.path.normpath 71 # This is safe to always do because the Windows version of os.path.normpath
67 # will replace forward slashes with backward slashes. 72 # will replace forward slashes with backward slashes.
68 path = path.replace(os.sep, '/') 73 path = path.replace(os.sep, '/')
69 return os.path.normpath(path) 74 return os.path.normpath(path)
70 75
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 file_item = file_item.AbsoluteLocalPath() 466 file_item = file_item.AbsoluteLocalPath()
462 if not file_item.startswith(self.change.RepositoryRoot()): 467 if not file_item.startswith(self.change.RepositoryRoot()):
463 raise IOError('Access outside the repository root is denied.') 468 raise IOError('Access outside the repository root is denied.')
464 return gclient_utils.FileRead(file_item, mode) 469 return gclient_utils.FileRead(file_item, mode)
465 470
466 @property 471 @property
467 def tbr(self): 472 def tbr(self):
468 """Returns if a change is TBR'ed.""" 473 """Returns if a change is TBR'ed."""
469 return 'TBR' in self.change.tags 474 return 'TBR' in self.change.tags
470 475
471 @staticmethod 476 def RunTests(self, tests_mix, parallel=True):
472 def RunTests(tests_mix, parallel=True):
473 tests = [] 477 tests = []
474 msgs = [] 478 msgs = []
475 for t in tests_mix: 479 for t in tests_mix:
476 if isinstance(t, OutputApi.PresubmitResult): 480 if isinstance(t, OutputApi.PresubmitResult):
477 msgs.append(t) 481 msgs.append(t)
478 else: 482 else:
479 assert issubclass(t.message, _PresubmitResult) 483 assert issubclass(t.message, _PresubmitResult)
480 tests.append(t) 484 tests.append(t)
485 if self.verbose:
486 t.info = _PresubmitNotifyResult
481 if len(tests) > 1 and parallel: 487 if len(tests) > 1 and parallel:
482 pool = multiprocessing.Pool() 488 pool = multiprocessing.Pool()
483 # async recipe works around multiprocessing bug handling Ctrl-C 489 # async recipe works around multiprocessing bug handling Ctrl-C
484 msgs.extend(pool.map_async(CallCommand, tests).get(99999)) 490 msgs.extend(pool.map_async(CallCommand, tests).get(99999))
485 pool.close() 491 pool.close()
486 pool.join() 492 pool.join()
487 else: 493 else:
488 msgs.extend(map(CallCommand, tests)) 494 msgs.extend(map(CallCommand, tests))
489 return [m for m in msgs if m] 495 return [m for m in msgs if m]
490 496
(...skipping 854 matching lines...) Expand 10 before | Expand all | Expand 10 after
1345 for method_name in method_names: 1351 for method_name in method_names:
1346 if not hasattr(presubmit_canned_checks, method_name): 1352 if not hasattr(presubmit_canned_checks, method_name):
1347 raise NonexistantCannedCheckFilter(method_name) 1353 raise NonexistantCannedCheckFilter(method_name)
1348 filtered[method_name] = getattr(presubmit_canned_checks, method_name) 1354 filtered[method_name] = getattr(presubmit_canned_checks, method_name)
1349 setattr(presubmit_canned_checks, method_name, lambda *_a, **_kw: []) 1355 setattr(presubmit_canned_checks, method_name, lambda *_a, **_kw: [])
1350 yield 1356 yield
1351 finally: 1357 finally:
1352 for name, method in filtered.iteritems(): 1358 for name, method in filtered.iteritems():
1353 setattr(presubmit_canned_checks, name, method) 1359 setattr(presubmit_canned_checks, name, method)
1354 1360
1361
1355 def CallCommand(cmd_data): 1362 def CallCommand(cmd_data):
1356 # multiprocessing needs a top level function with a single argument. 1363 """Runs an external program, potentially from a child process created by the
1364 multiprocessing module.
1365
1366 multiprocessing needs a top level function with a single argument.
1367 """
1357 cmd_data.kwargs['stdout'] = subprocess.PIPE 1368 cmd_data.kwargs['stdout'] = subprocess.PIPE
1358 cmd_data.kwargs['stderr'] = subprocess.STDOUT 1369 cmd_data.kwargs['stderr'] = subprocess.STDOUT
1359 try: 1370 try:
1371 start = time.time()
1360 (out, _), code = subprocess.communicate(cmd_data.cmd, **cmd_data.kwargs) 1372 (out, _), code = subprocess.communicate(cmd_data.cmd, **cmd_data.kwargs)
1361 if code != 0: 1373 duration = time.time() - start
1362 return cmd_data.message('%s failed\n%s' % (cmd_data.name, out))
1363 except OSError as e: 1374 except OSError as e:
1375 duration = time.time() - start
iannucci 2013/12/02 19:36:38 finally?
M-A Ruel 2013/12/02 21:23:24 You cannot do try/finally/except in python, only t
1364 return cmd_data.message( 1376 return cmd_data.message(
1365 '%s exec failure\n %s' % (cmd_data.name, e)) 1377 '%s exec failure (%4.2fs)\n %s' % (cmd_data.name, duration, e))
1378 if code != 0:
1379 return cmd_data.message(
1380 '%s (%4.2fs) failed\n%s' % (cmd_data.name, duration, out))
1381 if cmd_data.info:
1382 return cmd_data.info('%s (%4.2fs)' % (cmd_data.name, duration))
1366 1383
1367 1384
1368 def Main(argv): 1385 def Main(argv):
1369 parser = optparse.OptionParser(usage="%prog [options] <files...>", 1386 parser = optparse.OptionParser(usage="%prog [options] <files...>",
1370 version="%prog " + str(__version__)) 1387 version="%prog " + str(__version__))
1371 parser.add_option("-c", "--commit", action="store_true", default=False, 1388 parser.add_option("-c", "--commit", action="store_true", default=False,
1372 help="Use commit instead of upload checks") 1389 help="Use commit instead of upload checks")
1373 parser.add_option("-u", "--upload", action="store_false", dest='commit', 1390 parser.add_option("-u", "--upload", action="store_false", dest='commit',
1374 help="Use upload instead of commit checks") 1391 help="Use upload instead of commit checks")
1375 parser.add_option("-r", "--recursive", action="store_true", 1392 parser.add_option("-r", "--recursive", action="store_true",
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1446 except PresubmitFailure, e: 1463 except PresubmitFailure, e:
1447 print >> sys.stderr, e 1464 print >> sys.stderr, e
1448 print >> sys.stderr, 'Maybe your depot_tools is out of date?' 1465 print >> sys.stderr, 'Maybe your depot_tools is out of date?'
1449 print >> sys.stderr, 'If all fails, contact maruel@' 1466 print >> sys.stderr, 'If all fails, contact maruel@'
1450 return 2 1467 return 2
1451 1468
1452 1469
1453 if __name__ == '__main__': 1470 if __name__ == '__main__':
1454 fix_encoding.fix_encoding() 1471 fix_encoding.fix_encoding()
1455 sys.exit(Main(None)) 1472 sys.exit(Main(None))
OLDNEW
« no previous file with comments | « presubmit_canned_checks.py ('k') | tests/presubmit_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698