testing_support: switch to 4 space indent

Reformat this dir by itself to help merging with conflicts with other CLs.

Reformatted using:
parallel ./yapf -i -- testing_support/*.py
~/chromiumos/chromite/contrib/reflow_overlong_comments testing_support/*.py

The files that still had strings that were too long were manually
reformatted.
testing_support/coverage_utils.py
testing_support/fake_repos.py
testing_support/git_test_utils.py
testing_support/presubmit_canned_checks_test_mocks.py

Change-Id: I4726a4bbd279a70bcf65d0987fcff0ff9a231386
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/4842593
Reviewed-by: Josip Sokcevic <sokcevic@chromium.org>
Commit-Queue: Josip Sokcevic <sokcevic@chromium.org>
Auto-Submit: Mike Frysinger <vapier@chromium.org>
This commit is contained in:
Mike Frysinger
2023-09-05 20:14:34 +00:00
committed by LUCI CQ
parent 691128f836
commit f38dc929a8
10 changed files with 1396 additions and 1310 deletions

View File

@@ -0,0 +1,3 @@
[style]
based_on_style = pep8
column_limit = 80

View File

@@ -10,12 +10,13 @@ import sys
import textwrap
import unittest
ROOT_PATH = os.path.abspath(os.path.join(
os.path.dirname(os.path.dirname(__file__))))
ROOT_PATH = os.path.abspath(
os.path.join(os.path.dirname(os.path.dirname(__file__))))
def native_error(msg, version):
print(textwrap.dedent("""\
print(
textwrap.dedent("""\
ERROR: Native python-coverage (version: %s) is required to be
installed on your PYTHONPATH to run this test. Recommendation:
sudo apt-get install pip
@@ -23,7 +24,10 @@ def native_error(msg, version):
%s""") % (version, msg))
sys.exit(1)
def covered_main(includes, require_native=None, required_percentage=100.0,
def covered_main(includes,
require_native=None,
required_percentage=100.0,
disable_coverage=True):
"""Equivalent of unittest.main(), except that it gathers coverage data, and
asserts if the test is not at 100% coverage.
@@ -46,20 +50,22 @@ def covered_main(includes, require_native=None, required_percentage=100.0,
if require_native is not None:
got_ver = coverage.__version__
if not getattr(coverage.collector, 'CTracer', None):
native_error((
"Native python-coverage module required.\n"
"Pure-python implementation (version: %s) found: %s"
) % (got_ver, coverage), require_native)
native_error(
("Native python-coverage module required.\n"
"Pure-python implementation (version: %s) found: %s") %
(got_ver, coverage), require_native)
if got_ver < distutils.version.LooseVersion(require_native):
native_error("Wrong version (%s) found: %s" % (got_ver, coverage),
native_error(
"Wrong version (%s) found: %s" % (got_ver, coverage),
require_native)
except ImportError:
if require_native is None:
sys.path.insert(0, os.path.join(ROOT_PATH, 'third_party'))
import coverage
else:
print("ERROR: python-coverage (%s) is required to be installed on your "
"PYTHONPATH to run this test." % require_native)
print(
"ERROR: python-coverage (%s) is required to be installed on "
"your PYTHONPATH to run this test." % require_native)
sys.exit(1)
COVERAGE = coverage.coverage(include=includes)

View File

@@ -101,7 +101,8 @@ def expand_package_name_cmd(package_name):
for v in [ARCH_VAR, OS_VAR, PLATFORM_VAR]:
var = "${%s}" % v
if package_name.endswith(var):
package_name = package_name.replace(var, "%s-expanded-test-only" % v)
package_name = package_name.replace(var,
"%s-expanded-test-only" % v)
return package_name
@@ -136,7 +137,8 @@ def describe_cmd(package_name):
args, _ = parser.parse_known_args()
json_template = Template(DESCRIBE_JSON_TEMPLATE).substitute(
package=package_name)
cli_out = Template(DESCRIBE_STDOUT_TEMPLATE).substitute(package=package_name)
cli_out = Template(DESCRIBE_STDOUT_TEMPLATE).substitute(
package=package_name)
json_out = json.loads(json_template)
found = False
for tag in json_out['result']['tags']:

View File

@@ -3,7 +3,6 @@
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Generate fake repositories for testing."""
from __future__ import print_function
@@ -71,9 +70,10 @@ def dict_diff(dict1, dict2):
def commit_git(repo):
"""Commits the changes and returns the new hash."""
subprocess2.check_call(['git', 'add', '-A', '-f'], cwd=repo)
subprocess2.check_call(['git', 'commit', '-q', '--message', 'foo'], cwd=repo)
rev = subprocess2.check_output(
['git', 'show-ref', '--head', 'HEAD'], cwd=repo).split(b' ', 1)[0]
subprocess2.check_call(['git', 'commit', '-q', '--message', 'foo'],
cwd=repo)
rev = subprocess2.check_output(['git', 'show-ref', '--head', 'HEAD'],
cwd=repo).split(b' ', 1)[0]
rev = rev.decode('utf-8')
logging.debug('At revision %s' % rev)
return rev
@@ -164,10 +164,13 @@ class FakeReposBase(object):
except (OSError, subprocess2.CalledProcessError):
return False
for repo in ['repo_%d' % r for r in range(1, self.NB_GIT_REPOS + 1)]:
# TODO(crbug.com/114712) use git.init -b and remove 'checkout' once git is
# upgraded to 2.28 on all builders.
subprocess2.check_call(['git', 'init', '-q', join(self.git_base, repo)])
subprocess2.check_call(['git', 'checkout', '-q', '-b', DEFAULT_BRANCH],
# TODO(crbug.com/114712) use git.init -b and remove 'checkout' once
# git is upgraded to 2.28 on all builders.
subprocess2.check_call(
['git', 'init', '-q',
join(self.git_base, repo)])
subprocess2.check_call(
['git', 'checkout', '-q', '-b', DEFAULT_BRANCH],
cwd=join(self.git_base, repo))
self.git_hashes[repo] = [(None, None)]
self.populateGit()
@@ -175,15 +178,15 @@ class FakeReposBase(object):
return True
def _git_rev_parse(self, path):
return subprocess2.check_output(
['git', 'rev-parse', 'HEAD'], cwd=path).strip()
return subprocess2.check_output(['git', 'rev-parse', 'HEAD'],
cwd=path).strip()
def _commit_git(self, repo, tree, base=None):
repo_root = join(self.git_base, repo)
if base:
base_commit = self.git_hashes[repo][base][0]
subprocess2.check_call(
['git', 'checkout', base_commit], cwd=repo_root)
subprocess2.check_call(['git', 'checkout', base_commit],
cwd=repo_root)
self._genTree(repo_root, tree)
commit_hash = commit_git(repo_root)
base = base or -1
@@ -203,8 +206,9 @@ class FakeReposBase(object):
def _fast_import_git(self, repo, data):
repo_root = join(self.git_base, repo)
logging.debug('%s: fast-import %s', repo, data)
subprocess2.check_call(
['git', 'fast-import', '--quiet'], cwd=repo_root, stdin=data.encode())
subprocess2.check_call(['git', 'fast-import', '--quiet'],
cwd=repo_root,
stdin=data.encode())
def populateGit(self):
raise NotImplementedError()
@@ -277,17 +281,20 @@ deps_os = {
'git_base': self.git_base,
# See self.__init__() for the format. Grab's the hash of the
# first commit in repo_2. Only keep the first 7 character
# because of: TODO(maruel): http://crosbug.com/3591 We need to
# strip the hash.. duh.
# because of: TODO(maruel): http://crosbug.com/3591 We need
# to strip the hash.. duh.
'hash3': self.git_hashes['repo_3'][1][0][:7]
},
'origin': 'git/repo_1@1\n',
'foo bar': 'some file with a space',
})
self._commit_git('repo_2', {
'origin': 'git/repo_2@1\n',
'DEPS': """
self._commit_git(
'repo_2', {
'origin':
'git/repo_2@1\n',
'DEPS':
"""
vars = {
'repo2_false_var': 'False',
}
@@ -313,7 +320,9 @@ deps = {
'origin': 'git/repo_4@2\n',
})
self._commit_git('repo_1', {
self._commit_git(
'repo_1',
{
'DEPS': """
deps = {
'src/repo2': %(git_base)r + 'repo_2@%(hash)s',
@@ -340,16 +349,18 @@ hooks = [
]
""" % {
'git_base': self.git_base,
# See self.__init__() for the format. Grab's the hash of the first
# commit in repo_2. Only keep the first 7 character because of:
# TODO(maruel): http://crosbug.com/3591 We need to strip the hash.. duh.
# See self.__init__() for the format. Grab's the hash of the
# first commit in repo_2. Only keep the first 7 character
# because of: TODO(maruel): http://crosbug.com/3591 We need
# to strip the hash.. duh.
'hash': self.git_hashes['repo_2'][1][0][:7]
},
'origin': 'git/repo_1@2\n',
})
self._commit_git('repo_5', {'origin': 'git/repo_5@1\n'})
self._commit_git('repo_5', {
self._commit_git(
'repo_5', {
'DEPS': """
deps = {
'src/repo1': %(git_base)r + 'repo_1@%(hash1)s',
@@ -371,7 +382,8 @@ pre_deps_hooks = [
},
'origin': 'git/repo_5@2\n',
})
self._commit_git('repo_5', {
self._commit_git(
'repo_5', {
'DEPS': """
deps = {
'src/repo1': %(git_base)r + 'repo_1@%(hash1)s',
@@ -397,7 +409,8 @@ pre_deps_hooks = [
'origin': 'git/repo_5@3\n',
})
self._commit_git('repo_6', {
self._commit_git(
'repo_6', {
'DEPS': """
vars = {
'DummyVariable': 'repo',
@@ -498,7 +511,8 @@ recursedeps = [
'origin': 'git/repo_6@1\n',
})
self._commit_git('repo_7', {
self._commit_git(
'repo_7', {
'DEPS': """
vars = {
'true_var': 'True',
@@ -519,7 +533,8 @@ hooks = [
'origin': 'git/repo_7@1\n',
})
self._commit_git('repo_8', {
self._commit_git(
'repo_8', {
'DEPS': """
deps_os ={
'mac': {
@@ -532,7 +547,8 @@ deps_os ={
'origin': 'git/repo_8@1\n',
})
self._commit_git('repo_9', {
self._commit_git(
'repo_9', {
'DEPS': """
vars = {
'str_var': 'xyz',
@@ -563,7 +579,8 @@ recursedeps = [
'origin': 'git/repo_9@1\n',
})
self._commit_git('repo_10', {
self._commit_git(
'repo_10', {
'DEPS': """
gclient_gn_args_from = 'src/repo9'
deps = {
@@ -589,7 +606,8 @@ recursedeps = [
'origin': 'git/repo_10@1\n',
})
self._commit_git('repo_11', {
self._commit_git(
'repo_11', {
'DEPS': """
deps = {
'src/repo12': '/repo_12',
@@ -601,7 +619,8 @@ deps = {
'origin': 'git/repo_12@1\n',
})
self._fast_import_git('repo_12', """blob
self._fast_import_git(
'repo_12', """blob
mark :1
data 6
Hello
@@ -622,7 +641,8 @@ M 100644 :1 a
M 100644 :2 b
""")
self._commit_git('repo_13', {
self._commit_git(
'repo_13', {
'DEPS': """
deps = {
'src/repo12': '/repo_12',
@@ -630,7 +650,8 @@ deps = {
'origin': 'git/repo_13@1\n',
})
self._commit_git('repo_13', {
self._commit_git(
'repo_13', {
'DEPS': """
deps = {
'src/repo12': '/repo_12@refs/changes/1212',
@@ -639,7 +660,8 @@ deps = {
})
# src/repo12 is now a CIPD dependency.
self._commit_git('repo_13', {
self._commit_git(
'repo_13', {
'DEPS': """
deps = {
'src/repo12': {
@@ -660,8 +682,10 @@ hooks = [{
'origin': 'git/repo_13@3\n'
})
self._commit_git('repo_14', {
'DEPS': textwrap.dedent("""\
self._commit_git(
'repo_14', {
'DEPS':
textwrap.dedent("""\
vars = {}
deps = {
'src/cipd_dep': {
@@ -696,34 +720,44 @@ hooks = [{
'dep_type': 'cipd',
},
}"""),
'origin': 'git/repo_14@2\n'
'origin':
'git/repo_14@2\n'
})
# A repo with a hook to be recursed in, without use_relative_paths
self._commit_git('repo_15', {
'DEPS': textwrap.dedent("""\
self._commit_git(
'repo_15', {
'DEPS':
textwrap.dedent("""\
hooks = [{
"name": "absolute_cwd",
"pattern": ".",
"action": ["python3", "-c", "pass"]
}]"""),
'origin': 'git/repo_15@2\n'
'origin':
'git/repo_15@2\n'
})
# A repo with a hook to be recursed in, with use_relative_paths
self._commit_git('repo_16', {
'DEPS': textwrap.dedent("""\
self._commit_git(
'repo_16', {
'DEPS':
textwrap.dedent("""\
use_relative_paths=True
hooks = [{
"name": "relative_cwd",
"pattern": ".",
"action": ["python3", "relative.py"]
}]"""),
'relative.py': 'pass',
'origin': 'git/repo_16@2\n'
'relative.py':
'pass',
'origin':
'git/repo_16@2\n'
})
# A repo with a gclient_gn_args_file and use_relative_paths
self._commit_git('repo_17', {
'DEPS': textwrap.dedent("""\
self._commit_git(
'repo_17', {
'DEPS':
textwrap.dedent("""\
use_relative_paths=True
vars = {
'toto': 'tata',
@@ -732,7 +766,8 @@ hooks = [{
gclient_gn_args = [
'toto',
]"""),
'origin': 'git/repo_17@2\n'
'origin':
'git/repo_17@2\n'
})
self._commit_git(
@@ -847,29 +882,40 @@ class FakeRepoSkiaDEPS(FakeReposBase):
def populateGit(self):
# Skia repo.
self._commit_git('repo_1', {
self._commit_git(
'repo_1', {
'skia_base_file': 'root-level file.',
'gyp/gyp_file': 'file in the gyp directory',
'include/include_file': 'file in the include directory',
'src/src_file': 'file in the src directory',
})
self._commit_git('repo_3', { # skia/gyp
self._commit_git(
'repo_3',
{ # skia/gyp
'gyp_file': 'file in the gyp directory',
})
self._commit_git('repo_4', { # skia/include
'include_file': 'file in the include directory',
})
self._commit_git('repo_5', { # skia/src
self._commit_git(
'repo_5',
{ # skia/src
'src_file': 'file in the src directory',
})
# Chrome repo.
self._commit_git('repo_2', {
'DEPS': self.DEPS_git_pre % {'git_base': self.git_base},
self._commit_git(
'repo_2', {
'DEPS': self.DEPS_git_pre % {
'git_base': self.git_base
},
'myfile': 'src/trunk/src@1'
})
self._commit_git('repo_2', {
'DEPS': self.DEPS_post % {'git_base': self.git_base},
self._commit_git(
'repo_2', {
'DEPS': self.DEPS_post % {
'git_base': self.git_base
},
'myfile': 'src/trunk/src@2'
})
@@ -883,25 +929,33 @@ class FakeRepoBlinkDEPS(FakeReposBase):
def populateGit(self):
# Blink repo.
self._commit_git('repo_2', {
self._commit_git(
'repo_2', {
'OWNERS': 'OWNERS-pre',
'Source/exists_always': '_ignored_',
'Source/exists_before_but_not_after': '_ignored_',
})
# Chrome repo.
self._commit_git('repo_1', {
'DEPS': self.DEPS_pre % {'git_base': self.git_base},
self._commit_git(
'repo_1', {
'DEPS': self.DEPS_pre % {
'git_base': self.git_base
},
'myfile': 'myfile@1',
'.gitignore': '/third_party/WebKit',
})
self._commit_git('repo_1', {
'DEPS': self.DEPS_post % {'git_base': self.git_base},
self._commit_git(
'repo_1', {
'DEPS': self.DEPS_post % {
'git_base': self.git_base
},
'myfile': 'myfile@2',
'.gitignore': '',
'third_party/WebKit/OWNERS': 'OWNERS-post',
'third_party/WebKit/Source/exists_always': '_ignored_',
'third_party/WebKit/Source/exists_after_but_not_before': '_ignored',
'third_party/WebKit/Source/exists_after_but_not_before':
'_ignored',
})
def populateSvn(self):
@@ -975,12 +1029,12 @@ class FakeReposTestBase(trial_dir.TestCase):
def setUp(self):
super(FakeReposTestBase, self).setUp()
if not self.FAKE_REPOS_CLASS in self.CACHED_FAKE_REPOS:
self.CACHED_FAKE_REPOS[self.FAKE_REPOS_CLASS] = self.FAKE_REPOS_CLASS()
self.CACHED_FAKE_REPOS[
self.FAKE_REPOS_CLASS] = self.FAKE_REPOS_CLASS()
self.FAKE_REPOS = self.CACHED_FAKE_REPOS[self.FAKE_REPOS_CLASS]
# No need to call self.FAKE_REPOS.setUp(), it will be called by the child
# class.
# Do not define tearDown(), since super's version does the right thing and
# self.FAKE_REPOS is kept across tests.
# No need to call self.FAKE_REPOS.setUp(), it will be called by the
# child class. Do not define tearDown(), since super's version does the
# right thing and self.FAKE_REPOS is kept across tests.
@property
def git_base(self):
@@ -1015,8 +1069,8 @@ class FakeReposTestBase(trial_dir.TestCase):
self.assertEqual(tree, actual)
def mangle_git_tree(self, *args):
"""Creates a 'virtual directory snapshot' to compare with the actual result
on disk."""
"""Creates a 'virtual directory snapshot' to compare with the actual
result on disk."""
result = {}
for item, new_root in args:
repo, rev = item.split('@', 1)
@@ -1044,7 +1098,8 @@ def main(argv):
print('Using %s' % fake.root_dir)
try:
fake.set_up_git()
print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.')
print(
'Fake setup, press enter to quit or Ctrl-C to keep the checkouts.')
sys.stdin.readline()
except KeyboardInterrupt:
trial_dir.TrialDir.SHOULD_LEAK.leak = True

View File

@@ -20,7 +20,6 @@ class MockFileSystem(object):
file contents. A file content value of None indicates that the file should
not exist (IOError will be raised if it is opened;
reading from a missing key raises a KeyError, not an IOError."""
def __init__(self, files=None):
self.files = files or {}
self.written_files = {}
@@ -97,7 +96,8 @@ class MockFileSystem(object):
return self.files[path]
def relpath(self, path, base):
# This implementation is wrong in many ways; assert to check them for now.
# This implementation is wrong in many ways; assert to check them for
# now.
if not base.endswith(self.sep):
base += self.sep
assert path.startswith(base)

View File

@@ -17,7 +17,6 @@ import unittest
import gclient_utils
DEFAULT_BRANCH = 'main'
@@ -143,8 +142,7 @@ class GitRepoSchema(object):
"""
COMMIT = collections.namedtuple('COMMIT', 'name parents is_branch is_root')
def __init__(self, repo_schema='',
content_fn=lambda v: {v: {'data': v}}):
def __init__(self, repo_schema='', content_fn=lambda v: {v: {'data': v}}):
"""Builds a new GitRepoSchema.
Args:
@@ -176,9 +174,9 @@ class GitRepoSchema(object):
assert empty_keys, 'Cycle detected! %s' % par_map
for k in sorted(empty_keys):
yield self.COMMIT(k, self.par_map[k],
not any(k in v for v in self.par_map.values()),
is_root)
yield self.COMMIT(
k, self.par_map[k],
not any(k in v for v in self.par_map.values()), is_root)
del par_map[k]
for v in par_map.values():
v.difference_update(empty_keys)
@@ -289,7 +287,8 @@ class GitRepo(object):
Args:
schema - An instance of GitRepoSchema
"""
self.repo_path = os.path.realpath(tempfile.mkdtemp(dir=self.BASE_TEMP_DIR))
self.repo_path = os.path.realpath(
tempfile.mkdtemp(dir=self.BASE_TEMP_DIR))
self.commit_map = {}
self._date = datetime.datetime(1970, 1, 1, tzinfo=UTC)
@@ -320,7 +319,8 @@ class GitRepo(object):
parents = list(commit.parents)
self.git('checkout', '--detach', '-q', self[parents[0]])
if len(parents) > 1:
self.git('merge', '--no-commit', '-q', *[self[x] for x in parents[1:]])
self.git('merge', '--no-commit', '-q',
*[self[x] for x in parents[1:]])
else:
self.git('checkout', '--orphan', 'root_%s' % commit.name)
self.git('rm', '-rf', '.')
@@ -354,10 +354,12 @@ class GitRepo(object):
rslt = self.git('commit', '--allow-empty', '-m', commit.name, env=env)
assert rslt.retcode == 0, 'Failed to commit %s' % str(commit)
self.commit_map[commit.name] = self.git('rev-parse', 'HEAD').stdout.strip()
self.commit_map[commit.name] = self.git('rev-parse',
'HEAD').stdout.strip()
self.git('tag', 'tag_%s' % commit.name, self[commit.name])
if commit.is_branch:
self.git('branch', '-f', 'branch_%s' % commit.name, self[commit.name])
self.git('branch', '-f', 'branch_%s' % commit.name,
self[commit.name])
def get_git_commit_env(self, commit_data=None):
commit_data = commit_data or {}
@@ -384,8 +386,7 @@ class GitRepo(object):
try:
with open(os.devnull, 'wb') as devnull:
shell = sys.platform == 'win32'
output = subprocess.check_output(
('git', ) + args,
output = subprocess.check_output(('git', ) + args,
shell=shell,
cwd=self.repo_path,
stderr=devnull,
@@ -412,8 +413,8 @@ class GitRepo(object):
self.repo_path = None
def run(self, fn, *args, **kwargs):
"""Run a python function with the given args and kwargs with the cwd set to
the git repo."""
"""Run a python function with the given args and kwargs with the cwd
set to the git repo."""
assert self.repo_path is not None
curdir = os.getcwd()
try:
@@ -423,8 +424,8 @@ class GitRepo(object):
os.chdir(curdir)
def capture_stdio(self, fn, *args, **kwargs):
"""Run a python function with the given args and kwargs with the cwd set to
the git repo.
"""Run a python function with the given args and kwargs with the cwd set
to the git repo.
Returns the (stdout, stderr) of whatever ran, instead of the what |fn|
returned.
@@ -452,7 +453,8 @@ class GitRepo(object):
def to_schema(self):
lines = self.git('rev-list', '--parents', '--reverse', '--topo-order',
'--format=%s', *self.to_schema_refs).stdout.splitlines()
'--format=%s',
*self.to_schema_refs).stdout.splitlines()
hash_to_msg = {}
ret = GitRepoSchema()
current = None
@@ -543,5 +545,6 @@ class GitRepoReadWriteTestBase(GitRepoSchemaTestBase):
super(GitRepoReadWriteTestBase, self).tearDown()
def assertSchema(self, schema_string):
self.assertEqual(GitRepoSchema(schema_string).simple_graph(),
self.assertEqual(
GitRepoSchema(schema_string).simple_graph(),
self.repo.to_schema().simple_graph())

View File

@@ -15,7 +15,9 @@ from presubmit_canned_checks import _ReportErrorFileAndLine
class MockCannedChecks(object):
def _FindNewViolationsOfRule(self, callable_rule, input_api,
def _FindNewViolationsOfRule(self,
callable_rule,
input_api,
source_file_filter=None,
error_formatter=_ReportErrorFileAndLine):
"""Find all newly introduced violations of a per-line rule (a callable).
@@ -35,17 +37,19 @@ class MockCannedChecks(object):
errors = []
for f in input_api.AffectedFiles(include_deletes=False,
file_filter=source_file_filter):
# For speed, we do two passes, checking first the full file. Shelling out
# to the SCM to determine the changed region can be quite expensive on
# Win32. Assuming that most files will be kept problem-free, we can
# skip the SCM operations most of the time.
# For speed, we do two passes, checking first the full file.
# Shelling out to the SCM to determine the changed region can be
# quite expensive on Win32. Assuming that most files will be kept
# problem-free, we can skip the SCM operations most of the time.
extension = str(f.LocalPath()).rsplit('.', 1)[-1]
if all(callable_rule(extension, line) for line in f.NewContents()):
continue # No violation found in full text: can skip considering diff.
# No violation found in full text: can skip considering diff.
continue
for line_num, line in f.ChangedContents():
if not callable_rule(extension, line):
errors.append(error_formatter(f.LocalPath(), line_num, line))
errors.append(error_formatter(f.LocalPath(), line_num,
line))
return errors
@@ -91,13 +95,17 @@ class MockInputApi(object):
def AffectedSourceFiles(self, file_filter=None):
return self.AffectedFiles(file_filter=file_filter)
def FilterSourceFile(self, file, # pylint: disable=redefined-builtin
files_to_check=(), files_to_skip=()):
def FilterSourceFile(
self,
file, # pylint: disable=redefined-builtin
files_to_check=(),
files_to_skip=()):
local_path = file.LocalPath()
found_in_files_to_check = not files_to_check
if files_to_check:
if isinstance(files_to_check, str):
raise TypeError('files_to_check should be an iterable of strings')
raise TypeError(
'files_to_check should be an iterable of strings')
for pattern in files_to_check:
compiled_pattern = re.compile(pattern)
if compiled_pattern.search(local_path):
@@ -105,7 +113,8 @@ class MockInputApi(object):
break
if files_to_skip:
if isinstance(files_to_skip, str):
raise TypeError('files_to_skip should be an iterable of strings')
raise TypeError(
'files_to_skip should be an iterable of strings')
for pattern in files_to_skip:
compiled_pattern = re.compile(pattern)
if compiled_pattern.search(local_path):
@@ -134,7 +143,6 @@ class MockOutputApi(object):
An instance of this class can be passed to presubmit unittests for outputing
various types of results.
"""
class PresubmitResult(object):
def __init__(self, message, items=None, long_text=''):
self.message = message
@@ -146,22 +154,26 @@ class MockOutputApi(object):
class PresubmitError(PresubmitResult):
def __init__(self, message, items=None, long_text=''):
MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
MockOutputApi.PresubmitResult.__init__(self, message, items,
long_text)
self.type = 'error'
class PresubmitPromptWarning(PresubmitResult):
def __init__(self, message, items=None, long_text=''):
MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
MockOutputApi.PresubmitResult.__init__(self, message, items,
long_text)
self.type = 'warning'
class PresubmitNotifyResult(PresubmitResult):
def __init__(self, message, items=None, long_text=''):
MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
MockOutputApi.PresubmitResult.__init__(self, message, items,
long_text)
self.type = 'notify'
class PresubmitPromptOrNotify(PresubmitResult):
def __init__(self, message, items=None, long_text=''):
MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
MockOutputApi.PresubmitResult.__init__(self, message, items,
long_text)
self.type = 'promptOrNotify'
def __init__(self):
@@ -177,18 +189,21 @@ class MockFile(object):
This class can be used to form the mock list of changed files in
MockInputApi for presubmit unittests.
"""
def __init__(self, local_path, new_contents, old_contents=None, action='A',
def __init__(self,
local_path,
new_contents,
old_contents=None,
action='A',
scm_diff=None):
self._local_path = local_path
self._new_contents = new_contents
self._changed_contents = [(i + 1, l) for i, l in enumerate(new_contents)]
self._changed_contents = [(i + 1, l)
for i, l in enumerate(new_contents)]
self._action = action
if scm_diff:
self._scm_diff = scm_diff
else:
self._scm_diff = (
"--- /dev/null\n+++ %s\n@@ -0,0 +1,%d @@\n" %
self._scm_diff = ("--- /dev/null\n+++ %s\n@@ -0,0 +1,%d @@\n" %
(local_path, len(new_contents)))
for l in new_contents:
self._scm_diff += "+%s\n" % l
@@ -216,19 +231,19 @@ class MockFile(object):
return self._old_contents
def rfind(self, p):
"""os.path.basename is called on MockFile so we need an rfind method."""
"""os.path.basename is used on MockFile so we need an rfind method."""
return self._local_path.rfind(p)
def __getitem__(self, i):
"""os.path.basename is called on MockFile so we need a get method."""
"""os.path.basename is used on MockFile so we need a get method."""
return self._local_path[i]
def __len__(self):
"""os.path.basename is called on MockFile so we need a len method."""
"""os.path.basename is used on MockFile so we need a len method."""
return len(self._local_path)
def replace(self, altsep, sep):
"""os.path.basename is called on MockFile so we need a replace method."""
"""os.path.basename is used on MockFile so we need a replace method."""
return self._local_path.replace(altsep, sep)
@@ -243,7 +258,6 @@ class MockChange(object):
This class can be used in presubmit unittests to mock the query of the
current change.
"""
def __init__(self, changed_files, description=''):
self._changed_files = changed_files
self.footers = defaultdict(list)
@@ -252,7 +266,9 @@ class MockChange(object):
def LocalPaths(self):
return self._changed_files
def AffectedFiles(self, include_dirs=False, include_deletes=True,
def AffectedFiles(self,
include_dirs=False,
include_deletes=True,
file_filter=None):
return self._changed_files

View File

@@ -2,7 +2,6 @@
# Copyright (c) 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Script used to test subprocess2."""
import optparse
@@ -10,7 +9,6 @@ import os
import sys
import time
if sys.platform == 'win32':
# Annoying, make sure the output is not translated on Windows.
# pylint: disable=no-member,import-error
@@ -19,16 +17,17 @@ if sys.platform == 'win32':
msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
parser = optparse.OptionParser()
parser.add_option(
'--fail',
parser.add_option('--fail',
dest='return_value',
action='store_const',
default=0,
const=64)
parser.add_option(
'--crlf', action='store_const', const='\r\n', dest='eol', default='\n')
parser.add_option(
'--cr', action='store_const', const='\r', dest='eol')
parser.add_option('--crlf',
action='store_const',
const='\r\n',
dest='eol',
default='\n')
parser.add_option('--cr', action='store_const', const='\r', dest='eol')
parser.add_option('--stdout', action='store_true')
parser.add_option('--stderr', action='store_true')
parser.add_option('--read', action='store_true')
@@ -36,6 +35,7 @@ options, args = parser.parse_args()
if args:
parser.error('Internal error')
def do(string):
if options.stdout:
sys.stdout.buffer.write(string.upper().encode('utf-8'))

View File

@@ -1,7 +1,6 @@
# Copyright (c) 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Simplify unit tests based on pymox."""
from __future__ import print_function
@@ -22,8 +21,10 @@ class TestCaseUtils(object):
## Some utilities for generating arbitrary arguments.
def String(self, max_length):
return ''.join([self._RANDOM_CHOICE(self._STRING_LETTERS)
for _ in range(self._RANDOM_RANDINT(1, max_length))])
return ''.join([
self._RANDOM_CHOICE(self._STRING_LETTERS)
for _ in range(self._RANDOM_RANDINT(1, max_length))
])
def Strings(self, max_arg_count, max_arg_length):
return [self.String(max_arg_length) for _ in range(max_arg_count)]
@@ -36,18 +37,17 @@ class TestCaseUtils(object):
return self._OS_SEP.join(self.Strings(max_elt_count, max_elt_length))
def Dir(self, max_elt_count=4, max_elt_length=8):
return (self._RANDOM_CHOICE((self._OS_SEP, '')) +
self._DirElts(max_elt_count, max_elt_length))
return (self._RANDOM_CHOICE(
(self._OS_SEP, '')) + self._DirElts(max_elt_count, max_elt_length))
def RootDir(self, max_elt_count=4, max_elt_length=8):
return self._OS_SEP + self._DirElts(max_elt_count, max_elt_length)
def compareMembers(self, obj, members):
"""If you add a member, be sure to add the relevant test!"""
# Skip over members starting with '_' since they are usually not meant to
# be for public use.
actual_members = [x for x in sorted(dir(obj))
if not x.startswith('_')]
# Skip over members starting with '_' since they are usually not meant
# to be for public use.
actual_members = [x for x in sorted(dir(obj)) if not x.startswith('_')]
expected_members = sorted(members)
if actual_members != expected_members:
diff = ([i for i in actual_members if i not in expected_members] +

View File

@@ -40,7 +40,8 @@ class TrialDir(object):
# You can override self.TRIAL_ROOT.
if not self.TRIAL_ROOT:
# Was not yet initialized.
TrialDir.TRIAL_ROOT = os.path.realpath(tempfile.mkdtemp(prefix='trial'))
TrialDir.TRIAL_ROOT = os.path.realpath(
tempfile.mkdtemp(prefix='trial'))
atexit.register(self._clean)
self.root_dir = os.path.join(TrialDir.TRIAL_ROOT, self.subdir)
gclient_utils.rmtree(self.root_dir)