Bug 1213314: expand try alias support and implement aliases; r=ahal

This adds a lot of functionality to the `flags.aliases` field in the try
comment parser, and implements all of the aliases currently supported by
Buildbot's try_parser.py.

The situation changes slightly because of the way chunks are handled; it's no
longer possible to specify chunks using an alias with no leading `-`.  This
change should not cause undue hardship.

--HG--
extra : commitid : IQWTKQ7YxCB
extra : rebase_source : 5b8bdf7182117da75686fd58d18e778899a85194
This commit is contained in:
Dustin J. Mitchell 2015-10-22 17:46:39 -04:00
parent f686f5b310
commit 3f0b0fbbf7
3 changed files with 125 additions and 17 deletions

View File

@ -96,17 +96,52 @@ def normalize_test_list(aliases, all_tests, job_list):
if 'platforms' in all_entry:
entry['platforms'] = list(all_entry['platforms'])
results.append(entry)
return parse_test_chunks(aliases, results)
return parse_test_chunks(aliases, all_tests, results)
else:
return parse_test_chunks(aliases, tests)
return parse_test_chunks(aliases, all_tests, tests)
def parse_test_chunks(aliases, tests):
def handle_alias(test, aliases, all_tests):
'''
Expand a test if its name refers to an alias, returning a list of test
dictionaries cloned from the first (to maintain any metadata).
:param dict test: the test to expand
:param dict aliases: Dict of alias name -> real name.
:param list all_tests: test flags from job_flags.yml structure.
'''
if test['test'] not in aliases:
return [test]
alias = aliases[test['test']]
def mktest(name):
newtest = copy.deepcopy(test)
newtest['test'] = name
return newtest
def exprmatch(alias):
if not alias.startswith('/') or not alias.endswith('/'):
return [alias]
regexp = re.compile('^' + alias[1:-1] + '$')
return [t for t in all_tests if regexp.match(t)]
if isinstance(alias, str):
return [mktest(t) for t in exprmatch(alias)]
elif isinstance(alias, list):
names = sum([exprmatch(a) for a in alias], [])
return [mktest(t) for t in set(names)]
else:
return [test]
def parse_test_chunks(aliases, all_tests, tests):
'''
Test flags may include parameters to narrow down the number of chunks in a
given push. We don't model 1 chunk = 1 job in taskcluster so we must check
each test flag to see if it is actually specifying a chunk.
:param dict aliases: Dict of alias name -> real name.
:param list all_tests: test flags from job_flags.yml structure.
:param list tests: Result from normalize_test_list
:returns: List of jobs
'''
@ -116,24 +151,22 @@ def parse_test_chunks(aliases, tests):
matches = TEST_CHUNK_SUFFIX.match(test['test'])
if not matches:
if test['test'] in aliases:
test['test'] = aliases[test['test']]
results.append(test)
results.extend(handle_alias(test, aliases, all_tests))
continue
name = matches.group(1)
chunk = int(matches.group(2))
test['test'] = name
if name in aliases:
name = aliases[name]
if name in seen_chunks:
seen_chunks[name].add(chunk)
else:
seen_chunks[name] = set([chunk])
test['test'] = name
test['only_chunks'] = seen_chunks[name]
results.append(test)
for test in handle_alias(test, aliases, all_tests):
name = test['test']
if name in seen_chunks:
seen_chunks[name].add(chunk)
else:
seen_chunks[name] = set([chunk])
test['test'] = name
test['only_chunks'] = seen_chunks[name]
results.append(test)
return results;

View File

@ -3,7 +3,49 @@
# "all" is specified.
flags:
aliases:
mochitests: mochitest
# Aliases specify shorthands that can be used in try syntax. An alias can
# specify a simple replacement:
# fb: foobar -- replaces fb with foobar
#
# or an expansion into several test suites (which cannot themselves be
# aliases):
# footests:
# - foo
# - bar
# - bing
#
# or a pattern or patterns (identified by leading and trailing /) that
# will be matched against the available flags
# dt: /devtools.*/
# footests:
# - browser-foo
# - /foo.*/ -- selects all defined flags starting with "foo"
#
# Note that alias expansion is performed in the absence of any chunk
# prefixes. For example, the first example above would replace "foo-7"
# with "foobar-7". Note that a few aliases allowed chunks to be specified
# without a leading `-`, for example 'mochitest-dt1'. That's no longer
# supported.
mochitest: /mochitest.*/
mochitests: /mochitest.*/
jittest: /jittest.*/
jittests: /jittest.*/
mochitest-debug: /mochitest-debug-.*/
mochitest-o: /.*mochitest-o.*/
mochitest-a11y: /.*mochitest-o.*/
xpcshell: /xpcshell.*/
robocop: /robocop.*/
mochitest-dt: /mochitest-devtools-chrome.*/
mochitest-gl: /mochitest-gl.*/
mochitest-bc: /mochitest-browser-chrome.*/
mochitest-browser: /mochitest-browser-chrome.*/
reftest: /(plain-)?reftest.*/
reftests: /(plain-)?reftest.*/
web-platform-test: /web-platform-tests.*/
web-platform-tests: /web-platform-tests.*/
e10s: /.*e10s.*/
gaia-js-integration: /.*gaia-js-integration.*/
gaia-ui-test: /.*gaia-ui-test.*/
builds:
- emulator

View File

@ -49,6 +49,39 @@ class TestCommitParser(unittest.TestCase):
[{ 'test': 'alpha', "only_chunks": set([1, 3]) }]
)
def test_normalize_test_list_with_alias_pattern(self):
self.assertEqual(
normalize_test_list({ "a": '/.*oo.*/' },
['woot', 'foo', 'bar'],
'a, b, c'),
[{ 'test': t } for t in ['woot', 'foo', 'b', 'c']]
)
def test_normalize_test_list_with_alias_pattern_anchored(self):
self.assertEqual(
normalize_test_list({ "a": '/.*oo/' },
['woot', 'foo', 'bar'],
'a, b, c'),
[{ 'test': t } for t in ['foo', 'b', 'c']]
)
def test_normalize_test_list_with_alias_pattern_list(self):
self.assertEqual( sorted(
normalize_test_list({ "a": ['/.*oo/', 'bar', '/bi.*/'] },
['woot', 'foo', 'bar', 'bing', 'baz'],
'a, b')),
sorted([{ 'test': t } for t in ['foo', 'bar', 'bing', 'b']])
)
def test_normalize_test_list_with_alias_pattern_list_chunks(self):
self.assertEqual( sorted(
normalize_test_list({ "a": ['/.*oo/', 'bar', '/bi.*/'] },
['woot', 'foo', 'bar', 'bing', 'baz'],
'a-1, a-4, b')),
sorted([{'test': 'b'}] + [
{ 'test': t, 'only_chunks': set([1, 4])} for t in ['foo', 'bar', 'bing']])
)
def test_invalid_commit(self):
'''
Disallow invalid commit messages from being parsed...