133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# Copyright 2012 the V8 project authors. All rights reserved.
233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# Redistribution and use in source and binary forms, with or without
333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# modification, are permitted provided that the following conditions are
433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# met:
533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#
633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#     * Redistributions of source code must retain the above copyright
733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#       notice, this list of conditions and the following disclaimer.
833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#     * Redistributions in binary form must reproduce the above
933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#       copyright notice, this list of conditions and the following
1033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#       disclaimer in the documentation and/or other materials provided
1133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#       with the distribution.
1233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#     * Neither the name of Google Inc. nor the names of its
1333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#       contributors may be used to endorse or promote products derived
1433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#       from this software without specific prior written permission.
1533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#
1633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
2833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
2933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport os
30248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.orgimport shutil
3133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport time
3233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
33aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.orgfrom pool import Pool
3433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgfrom . import commands
35285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.orgfrom . import perfdata
3633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgfrom . import utils
3733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
3833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
3933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgclass Job(object):
4033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  def __init__(self, command, dep_command, test_id, timeout, verbose):
4133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.command = command
4233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.dep_command = dep_command
4333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.id = test_id
4433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.timeout = timeout
4533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.verbose = verbose
4633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
4733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
4833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgdef RunTest(job):
49aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org  start_time = time.time()
50aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org  if job.dep_command is not None:
51aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    dep_output = commands.Execute(job.dep_command, job.verbose, job.timeout)
52aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    # TODO(jkummerow): We approximate the test suite specific function
53aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    # IsFailureOutput() by just checking the exit code here. Currently
54aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    # only cctests define dependencies, for which this simplification is
55aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    # correct.
56aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    if dep_output.exit_code != 0:
57aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org      return (job.id, dep_output, time.time() - start_time)
58aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org  output = commands.Execute(job.command, job.verbose, job.timeout)
59aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org  return (job.id, output, time.time() - start_time)
6033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
6133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgclass Runner(object):
6233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
6333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  def __init__(self, suites, progress_indicator, context):
64248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org    self.datapath = os.path.join("out", "testrunner_data")
65248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org    self.perf_data_manager = perfdata.PerfDataManager(self.datapath)
66285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org    self.perfdata = self.perf_data_manager.GetStore(context.arch, context.mode)
67248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org    self.perf_failures = False
6870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    self.printed_allocations = False
6933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.tests = [ t for s in suites for t in s.tests ]
70e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org    if not context.no_sorting:
71e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org      for t in self.tests:
72e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org        t.duration = self.perfdata.FetchPerfData(t) or 1.0
73e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org      self.tests.sort(key=lambda t: t.duration, reverse=True)
7433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self._CommonInit(len(self.tests), progress_indicator, context)
7533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
7633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  def _CommonInit(self, num_tests, progress_indicator, context):
7733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.indicator = progress_indicator
7833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    progress_indicator.runner = self
7933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.context = context
8033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.succeeded = 0
8133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.total = num_tests
8233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.remaining = num_tests
8333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.failed = []
8433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.crashed = 0
85d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    self.reran_tests = 0
8633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
87248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  def _RunPerfSafe(self, fun):
88248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org    try:
89248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      fun()
90248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org    except Exception, e:
91248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      print("PerfData exception: %s" % e)
92248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      self.perf_failures = True
93248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org
94d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  def _GetJob(self, test):
95d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    command = self.GetCommand(test)
96d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    timeout = self.context.timeout
97d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    if ("--stress-opt" in test.flags or
98d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org        "--stress-opt" in self.context.mode_flags or
99d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org        "--stress-opt" in self.context.extra_flags):
100d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      timeout *= 4
101d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    if test.dependency is not None:
102d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      dep_command = [ c.replace(test.path, test.dependency) for c in command ]
103d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    else:
104d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      dep_command = None
105d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    return Job(command, dep_command, test.id, timeout, self.context.verbose)
106d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
107d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  def _MaybeRerun(self, pool, test):
10812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if test.run <= self.context.rerun_failures_count:
109d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      # Possibly rerun this test if its run count is below the maximum per
11012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      # test. <= as the flag controls reruns not including the first run.
111d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      if test.run == 1:
112d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org        # Count the overall number of reran tests on the first rerun.
113d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org        if self.reran_tests < self.context.rerun_failures_max:
114d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org          self.reran_tests += 1
115d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org        else:
116d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org          # Don't rerun this if the overall number of rerun tests has been
117d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org          # reached.
118d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org          return
119d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      if test.run >= 2 and test.duration > self.context.timeout / 20.0:
120d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org        # Rerun slow tests at most once.
121d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org        return
122d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
123d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      # Rerun this test.
124d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      test.duration = None
125d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      test.output = None
126d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      test.run += 1
127d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      pool.add([self._GetJob(test)])
128d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      self.remaining += 1
129d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
1305366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org  def _ProcessTestNormal(self, test, result, pool):
1315366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    self.indicator.AboutToRun(test)
1325366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    test.output = result[1]
1335366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    test.duration = result[2]
1345366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    has_unexpected_output = test.suite.HasUnexpectedOutput(test)
1355366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    if has_unexpected_output:
1365366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.failed.append(test)
1375366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      if test.output.HasCrashed():
1385366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org        self.crashed += 1
1395366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    else:
1405366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.succeeded += 1
1415366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    self.remaining -= 1
14212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    # For the indicator, everything that happens after the first run is treated
14312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    # as unexpected even if it flakily passes in order to include it in the
14412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    # output.
14512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    self.indicator.HasRun(test, has_unexpected_output or test.run > 1)
1465366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    if has_unexpected_output:
1475366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      # Rerun test failures after the indicator has processed the results.
1485366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self._MaybeRerun(pool, test)
1495366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    # Update the perf database if the test succeeded.
1505366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    return not has_unexpected_output
1515366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org
1525366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org  def _ProcessTestPredictable(self, test, result, pool):
15370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    def HasDifferentAllocations(output1, output2):
15470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      def AllocationStr(stdout):
15570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org        for line in reversed((stdout or "").splitlines()):
15670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org          if line.startswith("### Allocations = "):
15770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org            self.printed_allocations = True
15870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org            return line
15970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org        return ""
16070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      return (AllocationStr(output1.stdout) != AllocationStr(output2.stdout))
16170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
1625366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    # Always pass the test duration for the database update.
1635366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    test.duration = result[2]
1645366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    if test.run == 1 and result[1].HasTimedOut():
1655366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      # If we get a timeout in the first run, we are already in an
1665366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      # unpredictable state. Just report it as a failure and don't rerun.
1675366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.indicator.AboutToRun(test)
1685366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      test.output = result[1]
1695366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.remaining -= 1
1705366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.failed.append(test)
1715366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.indicator.HasRun(test, True)
17270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    if test.run > 1 and HasDifferentAllocations(test.output, result[1]):
17370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      # From the second run on, check for different allocations. If a
17470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      # difference is found, call the indicator twice to report both tests.
17570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      # All runs of each test are counted as one for the statistic.
1765366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.indicator.AboutToRun(test)
1775366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.remaining -= 1
1785366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.failed.append(test)
1795366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.indicator.HasRun(test, True)
1805366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.indicator.AboutToRun(test)
1815366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      test.output = result[1]
1825366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.indicator.HasRun(test, True)
1835366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    elif test.run >= 3:
1845366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      # No difference on the third run -> report a success.
1855366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.indicator.AboutToRun(test)
1865366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.remaining -= 1
1875366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.succeeded += 1
1885366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      test.output = result[1]
1895366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      self.indicator.HasRun(test, False)
1905366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    else:
1915366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      # No difference yet and less than three runs -> add another run and
1925366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      # remember the output for comparison.
1935366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      test.run += 1
1945366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      test.output = result[1]
1955366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      pool.add([self._GetJob(test)])
1965366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    # Always update the perf database.
1975366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org    return True
1985366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org
19933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  def Run(self, jobs):
20033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.indicator.Starting()
20133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self._RunInternal(jobs)
20233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.indicator.Done()
20346a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org    if self.failed or self.remaining:
20489e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org      return 1
20589e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org    return 0
20633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
20733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  def _RunInternal(self, jobs):
208aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    pool = Pool(jobs)
20933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    test_map = {}
210aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    # TODO(machenbach): Instead of filling the queue completely before
211aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    # pool.imap_unordered, make this a generator that already starts testing
212aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    # while the queue is filled.
21333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    queue = []
21433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    queued_exception = None
215e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org    for test in self.tests:
21633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      assert test.id >= 0
21733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      test_map[test.id] = test
21833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      try:
219d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org        queue.append([self._GetJob(test)])
22033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      except Exception, e:
22133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        # If this failed, save the exception and re-raise it later (after
22233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        # all other tests have had a chance to run).
22333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        queued_exception = e
22433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        continue
22533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    try:
226aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org      it = pool.imap_unordered(RunTest, queue)
22733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      for result in it:
228aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org        test = test_map[result[0]]
2295366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org        if self.context.predictable:
2305366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org          update_perf = self._ProcessTestPredictable(test, result, pool)
23133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        else:
2325366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org          update_perf = self._ProcessTestNormal(test, result, pool)
2335366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org        if update_perf:
234248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org          self._RunPerfSafe(lambda: self.perfdata.UpdatePerfData(test))
235aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org    finally:
23633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      pool.terminate()
237248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      self._RunPerfSafe(lambda: self.perf_data_manager.close())
238248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      if self.perf_failures:
239248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        # Nuke perf data in case of failures. This might not work on windows as
240248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        # some files might still be open.
241248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        print "Deleting perf test data due to db corruption."
242248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        shutil.rmtree(self.datapath)
24333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    if queued_exception:
24433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      raise queued_exception
24533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
24670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    # Make sure that any allocations were printed in predictable mode.
24770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    assert not self.context.predictable or self.printed_allocations
24833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
24933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  def GetCommand(self, test):
25033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    d8testflag = []
25133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    shell = test.suite.shell()
25233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    if shell == "d8":
25333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      d8testflag = ["--test"]
25433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    if utils.IsWindows():
25533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      shell += ".exe"
2566bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    cmd = (self.context.command_prefix +
25789e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org           [os.path.abspath(os.path.join(self.context.shell_dir, shell))] +
25833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org           d8testflag +
25904a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org           ["--random-seed=%s" % self.context.random_seed] +
26033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org           test.suite.GetFlagsForTestCase(test, self.context) +
261068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org           self.context.extra_flags)
26233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    return cmd
26333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
26433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
26533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgclass BreakNowException(Exception):
26633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  def __init__(self, value):
26733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    self.value = value
26833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  def __str__(self):
26933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    return repr(self.value)
270