Reviewers: Mads Ager,
Description:
Enable sharding of individual testsuites in tools/test.py
This patch enables two new flags for the tools/test.py script;
--shard-count - giving the ability to split the tests to be run
into shard-count chunks.
--shard-run - giving the ability to specify which of the shards to actually
run.
Example
tools/test.py -j15 --shard-count=2 --shard-run=1 mozilla
would split the mozilla tests into two chunks and run the tests in the first
chunk
Running:
tools/test.py -j15 --shard-count=2 --shard-run=1 mozilla
tools/test.py -j15 --shard-count=2 --shard-run=2 mozilla
is equivalent (in terms of test coverage) of just running:
tools/test.py -j15 mozilla
In addition, tests are now sorted before they are returned from the
test specific ListTests methods (sputnik and mozilla tests where
already sorted before they where returned).
This change is needed to split a single test suite over two slaves on
the waterfall.
Please review this at http://codereview.chromium.org/6127003/
SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/
Affected files:
M test/cctest/testcfg.py
M test/es5conform/testcfg.py
M test/message/testcfg.py
M test/mjsunit/testcfg.py
M tools/test.py
Index: test/cctest/testcfg.py
===================================================================
--- test/cctest/testcfg.py (revision 6231)
+++ test/cctest/testcfg.py (working copy)
@@ -92,6 +92,7 @@
dependency = relative_path[0] + '/' + dependency
if self.Contains(path, full_path):
result.append(CcTestCase(full_path, executable, mode, raw_test,
dependency, self.context))
+ result.sort()
return result
def GetTestStatus(self, sections, defs):
Index: test/es5conform/testcfg.py
===================================================================
--- test/es5conform/testcfg.py (revision 6231)
+++ test/es5conform/testcfg.py (working copy)
@@ -82,8 +82,10 @@
for root, dirs, files in os.walk(current_root):
for dotted in [x for x in dirs if x.startswith('.')]:
dirs.remove(dotted)
+ dirs.sort()
root_path = root[len(self.root):].split(os.path.sep)
root_path = current_path + [x for x in root_path if x]
+ files.sort()
for file in files:
if file.endswith('.js'):
full_path = root_path + [file[:-3]]
Index: test/message/testcfg.py
===================================================================
--- test/message/testcfg.py (revision 6231)
+++ test/message/testcfg.py (working copy)
@@ -107,6 +107,9 @@
mjsunit = [current_path + [t] for t in self.Ls(self.root)]
regress = [current_path + ['regress', t] for t in
self.Ls(join(self.root, 'regress'))]
bugs = [current_path + ['bugs', t] for t in
self.Ls(join(self.root, 'bugs'))]
+ mjsunit.sort()
+ regress.sort()
+ bugs.sort()
all_tests = mjsunit + regress + bugs
result = []
for test in all_tests:
Index: test/mjsunit/testcfg.py
===================================================================
--- test/mjsunit/testcfg.py (revision 6231)
+++ test/mjsunit/testcfg.py (working copy)
@@ -111,6 +111,12 @@
third_party = [current_path + ['third_party', t] for t in
self.Ls(join(self.root, 'third_party'))]
tools = [current_path + ['tools', t] for t in
self.Ls(join(self.root, 'tools'))]
compiler = [current_path + ['compiler', t] for t in
self.Ls(join(self.root, 'compiler'))]
+ mjsunit.sort()
+ regress.sort()
+ bugs.sort()
+ third_party.sort()
+ tools.sort()
+ compiler.sort()
all_tests = mjsunit + regress + bugs + third_party + tools + compiler
result = []
for test in all_tests:
Index: tools/test.py
===================================================================
--- tools/test.py (revision 6231)
+++ tools/test.py (working copy)
@@ -1181,6 +1181,10 @@
result.add_option("--crankshaft",
help="Run with the --crankshaft flag",
default=False, action="store_true")
+ result.add_option("--shard-count", help="Split testsuites into this
number of shards",
+ default=1, type="int")
+ result.add_option("--shard-run", help="Run this shard from the split up
tests.",
+ default=1, type="int")
result.add_option("--noprof", help="Disable profiling support",
default=False)
return result
@@ -1302,6 +1306,20 @@
millis = round(d * 1000) % 1000
return time.strftime("%M:%S.", time.gmtime(d)) + ("%03i" % millis)
+def ShardTests(tests, options):
+ if options.shard_count < 2:
+ return tests
+ if options.shard_run < 1 or options.shard_run > options.shard_count:
+ print "shard-run not a valid number, should be in [1:shard-count]"
+ print "defaulting back to running all tests"
+ return tests
+ count = 0;
+ shard = []
+ for test in tests:
+ if count % options.shard_count == options.shard_run - 1:
+ shard.append(test);
+ count += 1
+ return shard
def Main():
parser = BuildOptions()
@@ -1380,12 +1398,13 @@
}
test_list = root.ListTests([], path, context, mode)
unclassified_tests += test_list
+
(cases, unused_rules, all_outcomes) =
config.ClassifyTests(test_list, env)
if globally_unused_rules is None:
globally_unused_rules = set(unused_rules)
else:
globally_unused_rules =
globally_unused_rules.intersection(unused_rules)
- all_cases += cases
+ all_cases += ShardTests(cases, options)
all_unused.append(unused_rules)
if options.cat:
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev