Bug 1583353 - [manifestparser] Support manifests in the 'pathprefix' filter, r=egao

Allows 'paths' passed into the pathprefix filter to be manifests. Any path that
ends with '.ini' is considered a manifest.

Depends on D51899

Differential Revision: https://phabricator.services.mozilla.com/D51900

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrew Halberstadt 2019-11-08 18:58:09 +00:00
Родитель 746c6aaf3a
Коммит a3466c3c3c
4 изменённых файлов: 136 добавлений и 42 удалений

Просмотреть файл

@ -107,6 +107,7 @@ per-file-ignores =
testing/firefox-ui/**/__init__.py: F401
testing/marionette/**/__init__.py: F401
testing/mochitest/tests/python/conftest.py: F811
testing/mozbase/manifestparser/tests/test_filters.py: E731
testing/mozharness/configs/*: E124, E127, E128, E131, E231, E261, E265, E266, E501, W391
# These paths contain Python-2 only syntax which cause errors since flake8

Просмотреть файл

@ -374,7 +374,7 @@ class pathprefix(InstanceFilter):
"""
Removes tests that don't start with any of the given test paths.
:param paths: A list of test paths to filter on
:param paths: A list of test paths (or manifests) to filter on
"""
def __init__(self, paths):
@ -388,12 +388,20 @@ class pathprefix(InstanceFilter):
for tp in self.paths:
tp = os.path.normpath(tp)
path = test['relpath']
if os.path.isabs(tp):
path = test['path']
if tp.endswith('.ini'):
mpath = test['manifest'] if os.path.isabs(tp) else test['manifest_relpath']
if not os.path.normpath(path).startswith(tp):
continue
# only return tests that are in this manifest
if os.path.normpath(mpath) != tp:
continue
else:
# only return tests that start with this path
path = test['relpath']
if os.path.isabs(tp):
path = test['path']
if not os.path.normpath(path).startswith(tp):
continue
# any test path that points to a single file will be run no
# matter what, even if it's disabled

Просмотреть файл

@ -201,8 +201,29 @@ class ManifestParser(object):
test = data
test['name'] = section
def relative_to_root(path):
# Microoptimization, because relpath is quite expensive.
# We know that rootdir is an absolute path or empty. If path
# starts with rootdir, then path is also absolute and the tail
# of the path is the relative path (possibly non-normalized,
# when here is unknown).
# For this to work rootdir needs to be terminated with a path
# separator, so that references to sibling directories with
# a common prefix don't get misscomputed (e.g. /root and
# /rootbeer/file).
# When the rootdir is unknown, the relpath needs to be left
# unchanged. We use an empty string as rootdir in that case,
# which leaves relpath unchanged after slicing.
if path.startswith(rootdir):
return path[len(rootdir):]
else:
return relpath(path, rootdir)
# Will be None if the manifest being read is a file-like object.
test['manifest'] = filename
test['manifest_relpath'] = None
if test['manifest']:
test['manifest_relpath'] = relative_to_root(normalize_path(test['manifest']))
# determine the path
path = test.get('path', section)
@ -217,23 +238,7 @@ class ManifestParser(object):
path = os.path.join(here, path)
if '..' in path:
path = os.path.normpath(path)
# Microoptimization, because relpath is quite expensive.
# We know that rootdir is an absolute path or empty. If path
# starts with rootdir, then path is also absolute and the tail
# of the path is the relative path (possibly non-normalized,
# when here is unknown).
# For this to work rootdir needs to be terminated with a path
# separator, so that references to sibling directories with
# a common prefix don't get misscomputed (e.g. /root and
# /rootbeer/file).
# When the rootdir is unknown, the relpath needs to be left
# unchanged. We use an empty string as rootdir in that case,
# which leaves relpath unchanged after slicing.
if path.startswith(rootdir):
_relpath = path[len(rootdir):]
else:
_relpath = relpath(path, rootdir)
_relpath = relative_to_root(path)
test['path'] = path
test['relpath'] = _relpath
@ -493,7 +498,15 @@ class ManifestParser(object):
print('[%s]' % path, file=fp)
# reserved keywords:
reserved = ['path', 'name', 'here', 'manifest', 'relpath', 'ancestor-manifest']
reserved = [
'path',
'name',
'here',
'manifest',
'manifest_relpath',
'relpath',
'ancestor-manifest'
]
for key in sorted(test.keys()):
if key in reserved:
continue

Просмотреть файл

@ -1,22 +1,24 @@
#!/usr/bin/env python
# flake8: noqa
from __future__ import absolute_import
from __future__ import absolute_import, print_function
from copy import deepcopy
import os
from copy import deepcopy
from pprint import pprint
import mozpack.path as mozpath
import mozunit
import pytest
from manifestparser.filters import (
enabled,
fail_if,
filterlist,
pathprefix,
run_if,
skip_if,
subsuite,
tags,
skip_if,
run_if,
fail_if,
enabled,
filterlist,
)
here = os.path.dirname(os.path.abspath(__file__))
@ -97,17 +99,50 @@ def test_filters_run_in_order():
assert [i for i in fl] == [a, b, c, d, e, f]
@pytest.fixture(scope='module')
def create_tests():
def inner(*paths, **defaults):
tests = []
for path in paths:
if isinstance(path, tuple):
path, kwargs = path
else:
kwargs = {}
path = mozpath.normpath(path)
manifest = kwargs.pop('manifest', defaults.pop('manifest',
mozpath.join(mozpath.dirname(path), 'manifest.ini')))
test = {
'name': mozpath.basename(path),
'path': '/root/' + path,
'relpath': path,
'manifest': '/root/' + manifest,
'manifest_relpath': manifest,
}
test.update(**defaults)
test.update(**kwargs)
tests.append(test)
# dump tests to stdout for easier debugging on failure
print("The 'create_tests' fixture returned:")
pprint(tests, indent=2)
return tests
return inner
@pytest.fixture
def tests():
return (
{"name": "test0"},
{"name": "test1", "skip-if": "foo == 'bar'"},
{"name": "test2", "run-if": "foo == 'bar'"},
{"name": "test3", "fail-if": "foo == 'bar'"},
{"name": "test4", "disabled": "some reason"},
{"name": "test5", "subsuite": "baz"},
{"name": "test6", "subsuite": "baz,foo == 'bar'"},
{"name": "test7", "tags": "foo bar"},
def tests(create_tests):
return create_tests(
"test0",
("test1", {"skip-if": "foo == 'bar'"}),
("test2", {"run-if": "foo == 'bar'"}),
("test3", {"fail-if": "foo == 'bar'"}),
("test4", {"disabled": "some reason"}),
("test5", {"subsuite": "baz"}),
("test6", {"subsuite": "baz,foo == 'bar'"}),
("test7", {"tags": "foo bar"}),
)
@ -193,5 +228,42 @@ def test_tags(tests):
assert ref[7] in tests
def test_pathprefix(create_tests):
tests = create_tests(
'test0',
'subdir/test1',
'subdir/test2',
('subdir/test3', {'manifest': 'manifest.ini'}),
)
def names(items):
return sorted(i['name'] for i in items)
# relative directory
prefix = pathprefix('subdir')
filtered = prefix(tests, {})
assert names(filtered) == ['test1', 'test2', 'test3']
# absolute directory
prefix = pathprefix(['/root/subdir'])
filtered = prefix(tests, {})
assert names(filtered) == ['test1', 'test2', 'test3']
# relative manifest
prefix = pathprefix(['subdir/manifest.ini'])
filtered = prefix(tests, {})
assert names(filtered) == ['test1', 'test2']
# absolute manifest
prefix = pathprefix(['/root/subdir/manifest.ini'])
filtered = prefix(tests, {})
assert names(filtered) == ['test1', 'test2']
# mixed test and manifest
prefix = pathprefix(['subdir/test2', 'manifest.ini'])
filtered = prefix(tests, {})
assert names(filtered) == ['test0', 'test2', 'test3']
if __name__ == '__main__':
mozunit.main()