1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Redistribution and use in source and binary forms, with or without
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# modification, are permitted provided that the following conditions are
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# met:
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#     * Redistributions of source code must retain the above copyright
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       notice, this list of conditions and the following disclaimer.
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#     * Redistributions in binary form must reproduce the above
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       copyright notice, this list of conditions and the following
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       disclaimer in the documentation and/or other materials provided
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       with the distribution.
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#     * Neither the name of Google Inc. nor the names of its
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       contributors may be used to endorse or promote products derived
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#       from this software without specific prior written permission.
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfrom functools import wraps
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport json
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport os
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport sys
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport time
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfrom . import execution
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfrom . import junit_output
37bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochfrom . import statusfile
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochABS_PATH_PREFIX = os.getcwd() + os.sep
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ProgressIndicator(object):
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def __init__(self):
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.runner = None
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  def SetRunner(self, runner):
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    self.runner = runner
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def Starting(self):
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pass
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def Done(self):
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pass
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def HasRun(self, test, has_unexpected_output):
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    pass
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  def Heartbeat(self):
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pass
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def PrintFailureHeader(self, test):
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if test.suite.IsNegativeTest(test):
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      negative_marker = '[negative] '
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    else:
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      negative_marker = ''
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print "=== %(label)s %(negative)s===" % {
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'label': test.GetLabel(),
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'negative': negative_marker
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  def _EscapeCommand(self, test):
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    command = execution.GetCommand(test, self.runner.context)
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parts = []
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for part in command:
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if ' ' in part:
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        # Escape spaces.  We may need to escape more characters for this
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        # to work properly.
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        parts.append('"%s"' % part)
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      else:
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        parts.append(part)
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return " ".join(parts)
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass IndicatorNotifier(object):
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  """Holds a list of progress indicators and notifies them all on events."""
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  def __init__(self):
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    self.indicators = []
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  def Register(self, indicator):
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    self.indicators.append(indicator)
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch# Forge all generic event-dispatching methods in IndicatorNotifier, which are
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch# part of the ProgressIndicator interface.
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochfor func_name in ProgressIndicator.__dict__:
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  func = getattr(ProgressIndicator, func_name)
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if callable(func) and not func.__name__.startswith('_'):
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    def wrap_functor(f):
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      @wraps(f)
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      def functor(self, *args, **kwargs):
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        """Generic event dispatcher."""
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        for indicator in self.indicators:
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          getattr(indicator, f.__name__)(*args, **kwargs)
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return functor
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    setattr(IndicatorNotifier, func_name, wrap_functor(func))
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SimpleProgressIndicator(ProgressIndicator):
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  """Abstract base class for {Verbose,Dots}ProgressIndicator"""
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def Starting(self):
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print 'Running %i tests' % self.runner.total
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def Done(self):
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for failed in self.runner.failed:
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      self.PrintFailureHeader(failed)
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if failed.output.stderr:
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print "--- stderr ---"
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print failed.output.stderr.strip()
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if failed.output.stdout:
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print "--- stdout ---"
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print failed.output.stdout.strip()
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      print "Command: %s" % self._EscapeCommand(failed)
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if failed.output.HasCrashed():
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print "exit code: %d" % failed.output.exit_code
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print "--- CRASHED ---"
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if failed.output.HasTimedOut():
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print "--- TIMEOUT ---"
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if len(self.runner.failed) == 0:
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print "==="
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print "=== All tests succeeded"
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print "==="
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    else:
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print "==="
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print "=== %i tests failed" % len(self.runner.failed)
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if self.runner.crashed > 0:
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print "=== %i tests CRASHED" % self.runner.crashed
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      print "==="
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass VerboseProgressIndicator(SimpleProgressIndicator):
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def HasRun(self, test, has_unexpected_output):
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if has_unexpected_output:
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if test.output.HasCrashed():
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        outcome = 'CRASH'
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      else:
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        outcome = 'FAIL'
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    else:
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      outcome = 'pass'
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print 'Done running %s: %s' % (test.GetLabel(), outcome)
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sys.stdout.flush()
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  def Heartbeat(self):
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    print 'Still working...'
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    sys.stdout.flush()
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass DotsProgressIndicator(SimpleProgressIndicator):
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def HasRun(self, test, has_unexpected_output):
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    total = self.runner.succeeded + len(self.runner.failed)
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (total > 1) and (total % 50 == 1):
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sys.stdout.write('\n')
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if has_unexpected_output:
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if test.output.HasCrashed():
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sys.stdout.write('C')
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sys.stdout.flush()
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      elif test.output.HasTimedOut():
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sys.stdout.write('T')
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sys.stdout.flush()
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      else:
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sys.stdout.write('F')
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sys.stdout.flush()
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    else:
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sys.stdout.write('.')
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sys.stdout.flush()
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CompactProgressIndicator(ProgressIndicator):
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  """Abstract base class for {Color,Monochrome}ProgressIndicator"""
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def __init__(self, templates):
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    super(CompactProgressIndicator, self).__init__()
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.templates = templates
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.last_status_length = 0
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.start_time = time.time()
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def Done(self):
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.PrintProgress('Done')
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print ""  # Line break.
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def HasRun(self, test, has_unexpected_output):
198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    self.PrintProgress(test.GetLabel())
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if has_unexpected_output:
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      self.ClearLine(self.last_status_length)
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      self.PrintFailureHeader(test)
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stdout = test.output.stdout.strip()
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if len(stdout):
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print self.templates['stdout'] % stdout
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stderr = test.output.stderr.strip()
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if len(stderr):
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print self.templates['stderr'] % stderr
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      print "Command: %s" % self._EscapeCommand(test)
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if test.output.HasCrashed():
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print "exit code: %d" % test.output.exit_code
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print "--- CRASHED ---"
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if test.output.HasTimedOut():
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        print "--- TIMEOUT ---"
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def Truncate(self, string, length):
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if length and (len(string) > (length - 3)):
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return string[:(length - 3)] + "..."
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    else:
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return string
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def PrintProgress(self, name):
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.ClearLine(self.last_status_length)
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    elapsed = time.time() - self.start_time
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    progress = 0 if not self.runner.total else (
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ((self.runner.total - self.runner.remaining) * 100) //
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          self.runner.total)
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    status = self.templates['status_line'] % {
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'passed': self.runner.succeeded,
229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      'progress': progress,
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'failed': len(self.runner.failed),
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'test': name,
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'mins': int(elapsed) / 60,
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'secs': int(elapsed) % 60
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    status = self.Truncate(status, 78)
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.last_status_length = len(status)
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print status,
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sys.stdout.flush()
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ColorProgressIndicator(CompactProgressIndicator):
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def __init__(self):
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    templates = {
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'status_line': ("[%(mins)02i:%(secs)02i|"
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      "\033[34m%%%(progress) 4d\033[0m|"
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "\033[32m+%(passed) 4d\033[0m|"
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "\033[31m-%(failed) 4d\033[0m]: %(test)s"),
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'stdout': "\033[1m%s\033[0m",
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'stderr': "\033[31m%s\033[0m",
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    super(ColorProgressIndicator, self).__init__(templates)
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def ClearLine(self, last_line_length):
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print "\033[1K\r",
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MonochromeProgressIndicator(CompactProgressIndicator):
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def __init__(self):
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    templates = {
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      'status_line': ("[%(mins)02i:%(secs)02i|%%%(progress) 4d|"
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "+%(passed) 4d|-%(failed) 4d]: %(test)s"),
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'stdout': '%s',
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      'stderr': '%s',
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    super(MonochromeProgressIndicator, self).__init__(templates)
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def ClearLine(self, last_line_length):
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    print ("\r" + (" " * last_line_length) + "\r"),
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass JUnitTestProgressIndicator(ProgressIndicator):
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  def __init__(self, junitout, junittestsuite):
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.outputter = junit_output.JUnitTestOutput(junittestsuite)
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if junitout:
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      self.outfile = open(junitout, "w")
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    else:
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      self.outfile = sys.stdout
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def Done(self):
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.outputter.FinishAndWrite(self.outfile)
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if self.outfile != sys.stdout:
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      self.outfile.close()
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def HasRun(self, test, has_unexpected_output):
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    fail_text = ""
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if has_unexpected_output:
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stdout = test.output.stdout.strip()
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if len(stdout):
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        fail_text += "stdout:\n%s\n" % stdout
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stderr = test.output.stderr.strip()
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if len(stderr):
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        fail_text += "stderr:\n%s\n" % stderr
296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      fail_text += "Command: %s" % self._EscapeCommand(test)
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if test.output.HasCrashed():
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        fail_text += "exit code: %d\n--- CRASHED ---" % test.output.exit_code
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if test.output.HasTimedOut():
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        fail_text += "--- TIMEOUT ---"
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.outputter.HasRunTest(
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        [test.GetLabel()] + self.runner.context.mode_flags + test.flags,
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        test.duration,
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        fail_text)
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass JsonTestProgressIndicator(ProgressIndicator):
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  def __init__(self, json_test_results, arch, mode, random_seed):
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.json_test_results = json_test_results
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.arch = arch
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.mode = mode
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    self.random_seed = random_seed
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.results = []
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    self.tests = []
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def Done(self):
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    complete_results = []
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if os.path.exists(self.json_test_results):
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      with open(self.json_test_results, "r") as f:
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        # Buildbot might start out with an empty file.
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        complete_results = json.loads(f.read() or "[]")
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
324bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    duration_mean = None
325bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if self.tests:
326bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      # Get duration mean.
327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      duration_mean = (
328bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          sum(t.duration for t in self.tests) / float(len(self.tests)))
329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    # Sort tests by duration.
331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    timed_tests = [t for t in self.tests if t.duration is not None]
332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    timed_tests.sort(lambda a, b: cmp(b.duration, a.duration))
333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    slowest_tests = [
334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      {
335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "name": test.GetLabel(),
336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "flags": test.flags,
337014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "command": self._EscapeCommand(test).replace(ABS_PATH_PREFIX, ""),
338014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "duration": test.duration,
339bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        "marked_slow": statusfile.IsSlow(test.outcomes),
340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } for test in timed_tests[:20]
341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ]
342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    complete_results.append({
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "arch": self.arch,
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "mode": self.mode,
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "results": self.results,
347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      "slowest_tests": slowest_tests,
348bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      "duration_mean": duration_mean,
349bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      "test_total": len(self.tests),
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    })
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    with open(self.json_test_results, "w") as f:
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      f.write(json.dumps(complete_results))
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  def HasRun(self, test, has_unexpected_output):
356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    # Buffer all tests for sorting the durations in the end.
357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    self.tests.append(test)
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if not has_unexpected_output:
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      # Omit tests that run as expected. Passing tests of reruns after failures
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      # will have unexpected_output to be reported here has well.
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    self.results.append({
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "name": test.GetLabel(),
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "flags": test.flags,
366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      "command": self._EscapeCommand(test).replace(ABS_PATH_PREFIX, ""),
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "run": test.run,
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "stdout": test.output.stdout,
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "stderr": test.output.stderr,
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "exit_code": test.output.exit_code,
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "result": test.suite.GetOutcome(test),
372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      "expected": list(test.outcomes or ["PASS"]),
373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      "duration": test.duration,
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      # TODO(machenbach): This stores only the global random seed from the
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      # context and not possible overrides when using random-seed stress.
377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      "random_seed": self.random_seed,
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      "target_name": test.suite.shell(),
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      "variant": test.variant,
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    })
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochPROGRESS_INDICATORS = {
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  'verbose': VerboseProgressIndicator,
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  'dots': DotsProgressIndicator,
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  'color': ColorProgressIndicator,
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  'mono': MonochromeProgressIndicator
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
389