summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorFedor Indutny <fedor@indutny.com>2014-12-17 20:34:21 +0700
committerFedor Indutny <fedor@indutny.com>2014-12-17 20:45:37 +0700
commitb7d247856e318a830eff7e2d12495008c1c80ae3 (patch)
tree78a7bf71876adbd7abc67504e9dc550229867826 /tools
parent0e19476595729c850f07befea93e864822cd8459 (diff)
downloadandroid-node-v8-b7d247856e318a830eff7e2d12495008c1c80ae3.tar.gz
android-node-v8-b7d247856e318a830eff7e2d12495008c1c80ae3.tar.bz2
android-node-v8-b7d247856e318a830eff7e2d12495008c1c80ae3.zip
test: run tests in parallel, common improvements
* Allow running tests in mixed parallel/sequential modes * Add -J flag for running tests on all available CPUs * Support TEST_THREAD_ID in test/common.js and use it for tmpDir and PORT * make: use -J flag Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> PR-URL: https://github.com/iojs/io.js/pull/172 Fix: iojs/io.js#139
Diffstat (limited to 'tools')
-rwxr-xr-xtools/test.py50
1 files changed, 39 insertions, 11 deletions
diff --git a/tools/test.py b/tools/test.py
index cb60fbda1e..7241f162d7 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -40,6 +40,7 @@ import tempfile
import time
import threading
import utils
+import multiprocessing
from os.path import join, dirname, abspath, basename, isdir, exists
from datetime import datetime
@@ -58,9 +59,13 @@ class ProgressIndicator(object):
def __init__(self, cases, flaky_tests_mode):
self.cases = cases
self.flaky_tests_mode = flaky_tests_mode
- self.queue = Queue(len(cases))
+ self.parallel_queue = Queue(len(cases))
+ self.sequential_queue = Queue(len(cases))
for case in cases:
- self.queue.put_nowait(case)
+ if case.parallel:
+ self.parallel_queue.put_nowait(case)
+ else:
+ self.sequential_queue.put_nowait(case)
self.succeeded = 0
self.remaining = len(cases)
self.total = len(cases)
@@ -87,11 +92,11 @@ class ProgressIndicator(object):
# That way -j1 avoids threading altogether which is a nice fallback
# in case of threading problems.
for i in xrange(tasks - 1):
- thread = threading.Thread(target=self.RunSingle, args=[])
+ thread = threading.Thread(target=self.RunSingle, args=[True, i + 1])
threads.append(thread)
thread.start()
try:
- self.RunSingle()
+ self.RunSingle(False, 0)
# Wait for the remaining threads
for thread in threads:
# Use a timeout so that signals (ctrl-c) will be processed.
@@ -105,13 +110,19 @@ class ProgressIndicator(object):
self.Done()
return not self.failed
- def RunSingle(self):
+ def RunSingle(self, parallel, thread_id):
while not self.terminate:
try:
- test = self.queue.get_nowait()
+ test = self.parallel_queue.get_nowait()
except Empty:
- return
+ if parallel:
+ return
+ try:
+ test = self.sequential_queue.get_nowait()
+ except Empty:
+ return
case = test.case
+ case.thread_id = thread_id
self.lock.acquire()
self.AboutToRun(case)
self.lock.release()
@@ -381,6 +392,8 @@ class TestCase(object):
self.duration = None
self.arch = arch
self.mode = mode
+ self.parallel = False
+ self.thread_id = 0
def IsNegative(self):
return False
@@ -399,11 +412,12 @@ class TestCase(object):
def GetSource(self):
return "(no source available)"
- def RunCommand(self, command):
+ def RunCommand(self, command, env):
full_command = self.context.processor(command)
output = Execute(full_command,
self.context,
- self.context.GetTimeout(self.mode))
+ self.context.GetTimeout(self.mode),
+ env)
self.Cleanup()
return TestOutput(self,
full_command,
@@ -420,7 +434,9 @@ class TestCase(object):
self.BeforeRun()
try:
- result = self.RunCommand(self.GetCommand())
+ result = self.RunCommand(self.GetCommand(), {
+ "TEST_THREAD_ID": "%d" % self.thread_id
+ })
finally:
# Tests can leave the tty in non-blocking mode. If the test runner
# tries to print to stdout/stderr after that and the tty buffer is
@@ -559,15 +575,22 @@ def CheckedUnlink(name):
PrintError("os.unlink() " + str(e))
-def Execute(args, context, timeout=None):
+def Execute(args, context, timeout=None, env={}):
(fd_out, outname) = tempfile.mkstemp()
(fd_err, errname) = tempfile.mkstemp()
+
+ # Extend environment
+ env_copy = os.environ.copy()
+ for key, value in env.iteritems():
+ env_copy[key] = value
+
(process, exit_code, timed_out) = RunProcess(
context,
timeout,
args = args,
stdout = fd_out,
stderr = fd_err,
+ env = env_copy
)
os.close(fd_out)
os.close(fd_err)
@@ -1068,6 +1091,7 @@ class ClassifiedTest(object):
def __init__(self, case, outcomes):
self.case = case
self.outcomes = outcomes
+ self.parallel = self.case.parallel
class Configuration(object):
@@ -1224,6 +1248,8 @@ def BuildOptions():
default=False, action="store_true")
result.add_option("-j", help="The number of parallel tasks to run",
default=1, type="int")
+ result.add_option("-J", help="Run tasks in parallel on all cores",
+ default=False, action="store_true")
result.add_option("--time", help="Print timing information after running",
default=False, action="store_true")
result.add_option("--suppress-dialogs", help="Suppress Windows dialogs for crashing tests",
@@ -1245,6 +1271,8 @@ def ProcessOptions(options):
VERBOSE = options.verbose
options.arch = options.arch.split(',')
options.mode = options.mode.split(',')
+ if options.J:
+ options.j = multiprocessing.cpu_count()
def CheckTestMode(name, option):
if not option in ["run", "skip", "dontcare"]:
print "Unknown %s mode %s" % (name, option)