Recursively find all tests in a git repo.
This method is necessary to allow good code organization (i.e., unittests live
adjacent to the source files they test) in the new infra.git repository.
R=maruel@chromium.org
Review URL: https://codereview.chromium.org/281013002
git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@270564 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/presubmit_canned_checks.py b/presubmit_canned_checks.py
index bd3c361..56031b2 100644
--- a/presubmit_canned_checks.py
+++ b/presubmit_canned_checks.py
@@ -562,6 +562,36 @@
return results
+def GetUnitTestsRecursively(input_api, output_api, directory,
+ whitelist, blacklist):
+ """Gets all files in the directory tree (git repo) that match the whitelist.
+
+ Restricts itself to only find files within the Change's source repo, not
+ dependencies.
+ """
+ def check(filename):
+ return (any(input_api.re.match(f, filename) for f in whitelist) and
+ not any(input_api.re.match(f, filename) for f in blacklist))
+
+ tests = []
+
+ to_run = found = 0
+ for filepath in input_api.change.AllFiles(directory):
+ found += 1
+ if check(filepath):
+ to_run += 1
+ tests.append(filepath)
+ input_api.logging.debug('Found %d files, running %d' % (found, to_run))
+ if not to_run:
+ return [
+ output_api.PresubmitPromptWarning(
+ 'Out of %d files, found none that matched w=%r, b=%r in directory %s'
+ % (found, whitelist, blacklist, directory))
+ ]
+
+ return GetUnitTests(input_api, output_api, tests)
+
+
def GetPythonUnitTests(input_api, output_api, unit_tests):
"""Run the unit tests out of process, capture the output and use the result
code to determine success.
@@ -744,7 +774,7 @@
if True:
return [GetPylintCmd(files)]
else:
- return map(GetPylintCmd, files)
+ return map(lambda x: GetPylintCmd([x]), files)
def RunPylint(input_api, *args, **kwargs):
diff --git a/presubmit_support.py b/presubmit_support.py
index 111db58..e929e31 100755
--- a/presubmit_support.py
+++ b/presubmit_support.py
@@ -869,6 +869,10 @@
raise AttributeError(self, attr)
return self.tags.get(attr)
+ def AllFiles(self, root=None):
+ """List all files under source control in the repo."""
+ raise NotImplementedError()
+
def AffectedFiles(self, include_dirs=False, include_deletes=True,
file_filter=None):
"""Returns a list of AffectedFile instances for all files in the change.
@@ -965,11 +969,23 @@
return [os.path.join(self.RepositoryRoot(), f[1])
for f in changelists[self.Name()]]
+ def AllFiles(self, root=None):
+ """List all files under source control in the repo."""
+ root = root or self.RepositoryRoot()
+ return subprocess.check_output(
+ ['svn', 'ls', '-R', '.'], cwd=root).splitlines()
+
class GitChange(Change):
_AFFECTED_FILES = GitAffectedFile
scm = 'git'
+ def AllFiles(self, root=None):
+ """List all files under source control in the repo."""
+ root = root or self.RepositoryRoot()
+ return subprocess.check_output(
+ ['git', 'ls-files', '--', '.'], cwd=root).splitlines()
+
def ListRelevantPresubmitFiles(files, root):
"""Finds all presubmit files that apply to a given set of source files.
diff --git a/tests/presubmit_unittest.py b/tests/presubmit_unittest.py
index 2f973bd..23304f0 100755
--- a/tests/presubmit_unittest.py
+++ b/tests/presubmit_unittest.py
@@ -1773,7 +1773,7 @@
class ChangeUnittest(PresubmitTestsBase):
def testMembersChanged(self):
members = [
- 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles',
+ 'AbsoluteLocalPaths', 'AffectedFiles', 'AffectedTextFiles', 'AllFiles',
'DescriptionText', 'FullDescriptionText', 'LocalPaths', 'Name',
'RepositoryRoot', 'RightHandSideLines', 'ServerPaths',
'SetDescriptionText', 'TAG_LINE_RE',
@@ -1885,7 +1885,7 @@
'RunPythonUnitTests', 'RunPylint',
'RunUnitTests', 'RunUnitTestsInDirectory',
'GetPythonUnitTests', 'GetPylint',
- 'GetUnitTests', 'GetUnitTestsInDirectory',
+ 'GetUnitTests', 'GetUnitTestsInDirectory', 'GetUnitTestsRecursively',
]
# If this test fails, you should add the relevant test.
self.compareMembers(presubmit_canned_checks, members)