Index: tools/telemetry/telemetry/test_runner.py |
diff --git a/tools/telemetry/telemetry/test_runner.py b/tools/telemetry/telemetry/test_runner.py |
index adb95a83618e1b1d2ff968df9211b297fda26d68..ec6213258ca9d32bf598e14ad97d2932788b94bb 100644 |
--- a/tools/telemetry/telemetry/test_runner.py |
+++ b/tools/telemetry/telemetry/test_runner.py |
@@ -10,9 +10,11 @@ actually running the test is in Test and PageRunner.""" |
import copy |
import inspect |
import json |
+import math |
import optparse |
import os |
import sys |
+import traceback |
from telemetry import test |
from telemetry.core import browser_options |
@@ -20,6 +22,71 @@ from telemetry.core import discover |
from telemetry.core import util |
+def PrintFormattedException(exception_class, exception, tb): |
+ """Prints an Exception in a more useful format than the default. |
+ |
+ TODO(tonyg): Consider further enhancements. For instance: |
+ - Report stacks to maintainers like depot_tools does. |
+ - Add a debug flag to automatically start pdb upon exception. |
+ """ |
+ def _GetFinalFrame(frame): |
+ final_frame = None |
+ while frame is not None: |
+ final_frame = frame |
+ frame = frame.tb_next |
+ return final_frame |
+ |
+ def _AbbreviateMiddle(target, middle, length): |
+ assert length >= 0, 'Must provide positive length' |
+ assert len(middle) <= length, 'middle must not be greater than length' |
+ if len(target) <= length: |
+ return target |
+ half_length = (length - len(middle)) / 2. |
+ return '%s%s%s' % (target[:int(math.floor(half_length))], |
+ middle, |
+ target[-int(math.ceil(half_length)):]) |
+ |
+ base_dir = os.path.abspath(util.GetChromiumSrcDir()) |
+ formatted_exception = traceback.format_exception( |
+ exception_class, exception, tb) |
+ extracted_tb = traceback.extract_tb(tb) |
+ traceback_header = formatted_exception[0].strip() |
+ exception = formatted_exception[-1].strip() |
+ local_variables = _GetFinalFrame(tb).tb_frame.f_locals |
+ |
+ # Format the traceback. |
+ print >> sys.stderr |
+ print >> sys.stderr, traceback_header |
+ for filename, line, function, text in extracted_tb: |
+ filename = os.path.abspath(filename).lstrip(base_dir) |
+ print >> sys.stderr, ' %s at %s:%d' % (function, filename, line) |
+ print >> sys.stderr, ' %s' % text |
+ |
+ # Format the locals. |
+ if local_variables: |
+ print >> sys.stderr |
+ print >> sys.stderr, 'Locals:' |
+ longest_variable = max([len(v) for v in local_variables.keys()]) |
+ for variable, value in sorted(local_variables.iteritems()): |
+ if variable == 'self': |
+ continue |
+ value = repr(value) |
+ possibly_truncated_value = _AbbreviateMiddle(value, ' ... ', 128) |
+ truncation_indication = '' |
+ if len(possibly_truncated_value) != len(value): |
+ truncation_indication = ' (truncated)' |
+ print >> sys.stderr, ' %s: %s%s' % (variable.ljust(longest_variable + 1), |
+ possibly_truncated_value, |
+ truncation_indication) |
+ |
+ # Format the exception. |
+ print >> sys.stderr |
+ print >> sys.stderr, exception |
+ |
+ |
+sys.excepthook = PrintFormattedException |
+ |
+ |
class Command(object): |
usage = '' |