mirror of
https://chromium.googlesource.com/chromium/tools/depot_tools.git
synced 2026-01-11 10:41:31 +00:00
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:
3
testing_support/.style.yapf
Normal file
3
testing_support/.style.yapf
Normal file
@@ -0,0 +1,3 @@
|
||||
[style]
|
||||
based_on_style = pep8
|
||||
column_limit = 80
|
||||
@@ -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)
|
||||
|
||||
@@ -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']:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -17,7 +17,6 @@ import unittest
|
||||
|
||||
import gclient_utils
|
||||
|
||||
|
||||
DEFAULT_BRANCH = 'main'
|
||||
|
||||
|
||||
@@ -64,7 +63,7 @@ class OrderedSet(collections.MutableSet):
|
||||
|
||||
def __repr__(self):
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__,)
|
||||
return '%s()' % (self.__class__.__name__, )
|
||||
return '%s(%r)' % (self.__class__.__name__, list(self))
|
||||
|
||||
def __reversed__(self):
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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] +
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user