Skip to content

Commit

Permalink
Merge pull request tc39#497 from tschneidereit/master
Browse files Browse the repository at this point in the history
Enable parallel test execution in console runner
  • Loading branch information
rwaldron committed Feb 8, 2016
2 parents 26aeed1 + 7ae29d4 commit 5cb97c2
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 15 deletions.
9 changes: 5 additions & 4 deletions CONSOLE-RUNNER.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Name | Action
-----|-------
-h, --help | displays a brief help message
--command=COMMAND | **required** command which invokes javascript engine to be tested
-j, --workers-count | Number of tests to run in parallel (defaults to number of cores - 1)
--tests=TESTS | path to the test suite; default is current directory
--cat | don't execute tests, just print code that would be run
--summary | generate a summary at end of execution
Expand All @@ -49,9 +50,9 @@ Name | Action
--unmarked_default=MODE | mode to use for tests that are not marked **onlyStrict** or **noStrict** ; MODE can be `strict` or `non_strict` or `both`
--logname=LOGNAME | write output to file (in addition to stdout)
--junitname=JUNITNAME | write test results to file in JUnit XML format
--loglevel=LOGLEVEL | set log level, primarily useful for debugging `test262.py`
--loglevel=LOGLEVEL | set log level, primarily useful for debugging `test262.py`
--print-handle=FUNC | enable async test logging via javascript function e.g., `console.log`

### Usage Notes

Non-option arguments are used as filters to match test names. If no filters are found, the whole test suite is run.
Expand All @@ -66,7 +67,7 @@ The COMMAND argument can be a quoted string. This is useful when testing ECMASc

```
$ test262.py --command="node --harmony" es6
```
```

#### Async Tests

Expand All @@ -81,7 +82,7 @@ JavaScriptCore<sup>2</sup> | jsc | print

***Notes:***
1. As of 2014-Jul-23, SpiderMonkey does not support Promise in the `js` executable ([see bug 911216](https://bugzilla.mozilla.org/show_bug.cgi?id=911216) )
2. As of 2014-Jul-23, JavaScriptCore does not support Promise in the `jsc` executable
2. As of 2014-Jul-23, JavaScriptCore does not support Promise in the `jsc` executable


### Troubleshooting
Expand Down
84 changes: 73 additions & 11 deletions tools/packaging/test262.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import sys
import tempfile
import time
import threading
import xml.dom.minidom
import datetime
import shutil
Expand Down Expand Up @@ -54,6 +55,8 @@ def ReportError(s):
def BuildOptions():
result = optparse.OptionParser()
result.add_option("--command", default=None, help="The command-line to run")
result.add_option("-j", "--workers-count", type=int, default=max(1, GetCPUCount() - 1),
help="Number of tests to run in parallel (default %default)")
result.add_option("--tests", default=path.abspath('.'),
help="Path to the tests")
result.add_option("--cat", default=False, action="store_true",
Expand Down Expand Up @@ -92,6 +95,35 @@ def IsWindows():
p = platform.system()
return (p == 'Windows') or (p == 'Microsoft')

def GetCPUCount():
"""
Guess at a reasonable parallelism count to set as the default for the
current machine and run.
"""
# Python 2.6+
try:
import multiprocessing
return multiprocessing.cpu_count()
except (ImportError, NotImplementedError):
pass

# POSIX
try:
res = int(os.sysconf('SC_NPROCESSORS_ONLN'))
if res > 0:
return res
except (AttributeError, ValueError):
pass

# Windows
try:
res = int(os.environ['NUMBER_OF_PROCESSORS'])
if res > 0:
return res
except (KeyError, ValueError):
pass

return 1

class TempFile(object):

Expand Down Expand Up @@ -526,7 +558,7 @@ def PrintFailureOutput(self, progress, logfile):
print
result.ReportOutcome(False)

def Run(self, command_template, tests, print_summary, full_summary, logname, junitfile):
def Run(self, command_template, tests, print_summary, full_summary, logname, junitfile, workers_count):
if not "{{path}}" in command_template:
command_template += " {{path}}"
cases = self.EnumerateTests(tests)
Expand All @@ -551,16 +583,41 @@ def Run(self, command_template, tests, print_summary, full_summary, logname, jun
SkipCaseElement.append(SkipElement)
TestSuiteElement.append(SkipCaseElement)

if workers_count > 1:
pool_sem = threading.Semaphore(workers_count)
log_lock = threading.Lock()
else:
log_lock = None

for case in cases:
result = case.Run(command_template)
if junitfile:
TestCaseElement = result.XmlAssemble(result)
TestSuiteElement.append(TestCaseElement)
if case == cases[len(cases)-1]:
xmlj.ElementTree(TestSuitesElement).write(junitfile, "UTF-8")
if logname:
self.WriteLog(result)
progress.HasRun(result)
def exec_case():
result = case.Run(command_template)

try:
if workers_count > 1:
log_lock.acquire()

if junitfile:
TestCaseElement = result.XmlAssemble(result)
TestSuiteElement.append(TestCaseElement)
if case == cases[len(cases)-1]:
xmlj.ElementTree(TestSuitesElement).write(junitfile, "UTF-8")
if logname:
self.WriteLog(result)
finally:
if workers_count > 1:
log_lock.release()

progress.HasRun(result)
if workers_count == 1:
exec_case()
else:
pool_sem.acquire()
threading.Thread(target=exec_case).start()
pool_sem.release()

if workers_count > 1:
log_lock.acquire()

if print_summary:
self.PrintSummary(progress, logname)
Expand All @@ -570,6 +627,10 @@ def Run(self, command_template, tests, print_summary, full_summary, logname, jun
print
print "Use --full-summary to see output from failed tests"
print

if workers_count > 1:
log_lock.release()

return progress.failed

def WriteLog(self, result):
Expand Down Expand Up @@ -634,7 +695,8 @@ def Main():
options.summary or options.full_summary,
options.full_summary,
options.logname,
options.junitname)
options.junitname,
options.workers_count)
return code

if __name__ == '__main__':
Expand Down

0 comments on commit 5cb97c2

Please sign in to comment.