From b4ea8c7f5e5dd5428557d519b721f134a5a0c9f9 Mon Sep 17 00:00:00 2001 From: "ricow@chromium.org" Date: Mon, 10 Jan 2011 13:54:42 +0000 Subject: [PATCH] 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. Review URL: http://codereview.chromium.org/6127003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6248 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- test/cctest/testcfg.py | 1 + test/es5conform/testcfg.py | 2 ++ test/message/testcfg.py | 3 +++ test/mjsunit/testcfg.py | 6 ++++++ tools/test.py | 22 +++++++++++++++++++++- 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/test/cctest/testcfg.py b/test/cctest/testcfg.py index 485f2cf..b15342e 100644 --- a/test/cctest/testcfg.py +++ b/test/cctest/testcfg.py @@ -92,6 +92,7 @@ class CcTestConfiguration(test.TestConfiguration): 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): diff --git a/test/es5conform/testcfg.py b/test/es5conform/testcfg.py index 43d6104..e3a60cc 100644 --- a/test/es5conform/testcfg.py +++ b/test/es5conform/testcfg.py @@ -82,8 +82,10 @@ class ES5ConformTestConfiguration(test.TestConfiguration): 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]] diff --git a/test/message/testcfg.py b/test/message/testcfg.py index 7dae047..21a0428 100644 --- a/test/message/testcfg.py +++ b/test/message/testcfg.py @@ -107,6 +107,9 @@ class MessageTestConfiguration(test.TestConfiguration): 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: diff --git a/test/mjsunit/testcfg.py b/test/mjsunit/testcfg.py index d8fe24d..5cb46bc 100644 --- a/test/mjsunit/testcfg.py +++ b/test/mjsunit/testcfg.py @@ -111,6 +111,12 @@ class MjsunitTestConfiguration(test.TestConfiguration): 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: diff --git a/tools/test.py b/tools/test.py index 7348c62..939ca0c 100755 --- a/tools/test.py +++ b/tools/test.py @@ -1181,6 +1181,12 @@ def BuildOptions(): 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 +1308,20 @@ def FormatTime(d): 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() @@ -1385,7 +1405,7 @@ def Main(): 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: -- 2.7.4