diff --git a/gclient_scm.py b/gclient_scm.py index 6bd056678..d599bfef3 100644 --- a/gclient_scm.py +++ b/gclient_scm.py @@ -448,7 +448,7 @@ class GitWrapper(SCMWrapper): target_rev, patch_rev, base_rev)) self.Print('Current dir is %r' % self.checkout_path) self.Print('git returned non-zero exit status %s:\n%s' % ( - e.returncode, e.stderr)) + e.returncode, e.stderr.decode('utf-8'))) # Print the current status so that developers know what changes caused # the patch failure, since git cherry-pick doesn't show that # information. @@ -553,7 +553,7 @@ class GitWrapper(SCMWrapper): files = self._Capture( ['-c', 'core.quotePath=false', 'ls-files']).splitlines() file_list.extend( - [os.path.join(self.checkout_path, f.decode()) for f in files]) + [os.path.join(self.checkout_path, f) for f in files]) if mirror: self._Capture( ['remote', 'set-url', '--push', 'origin', mirror.url]) @@ -761,7 +761,8 @@ class GitWrapper(SCMWrapper): merge_output = self._Capture(merge_args) except subprocess2.CalledProcessError as e: rebase_files = [] - if re.match('fatal: Not possible to fast-forward, aborting.', e.stderr): + if re.match(b'fatal: Not possible to fast-forward, aborting.', + e.stderr): if not printed_path: self.Print('_____ %s at %s' % (self.relpath, revision), timestamp=False) @@ -791,19 +792,19 @@ class GitWrapper(SCMWrapper): return else: self.Print('Input not recognized') - elif re.match("error: Your local changes to '.*' would be " - "overwritten by merge. Aborting.\nPlease, commit your " - "changes or stash them before you can merge.\n", + elif re.match(b"error: Your local changes to '.*' would be " + b"overwritten by merge. Aborting.\nPlease, commit your " + b"changes or stash them before you can merge.\n", e.stderr): if not printed_path: self.Print('_____ %s at %s' % (self.relpath, revision), timestamp=False) printed_path = True - raise gclient_utils.Error(e.stderr) + raise gclient_utils.Error(e.stderr.decode('utf-8')) else: # Some other problem happened with the merge logging.error("Error during fast-forward merge in %s!" % self.relpath) - self.Print(e.stderr) + self.Print(e.stderr.decode('utf-8')) raise else: # Fast-forward merge was successful @@ -1117,8 +1118,8 @@ class GitWrapper(SCMWrapper): try: rebase_output = scm.GIT.Capture(rebase_cmd, cwd=self.checkout_path) except subprocess2.CalledProcessError as e: - if (re.match(r'cannot rebase: you have unstaged changes', e.stderr) or - re.match(r'cannot rebase: your index contains uncommitted changes', + if (re.match(br'cannot rebase: you have unstaged changes', e.stderr) or + re.match(br'cannot rebase: your index contains uncommitted changes', e.stderr)): while True: rebase_action = self._AskForData( @@ -1136,18 +1137,19 @@ class GitWrapper(SCMWrapper): "cd %s && git " % self.checkout_path + "%s" % ' '.join(rebase_cmd)) elif re.match(r'show|s', rebase_action, re.I): - self.Print('%s' % e.stderr.strip()) + self.Print('%s' % e.stderr.decode('utf-8').strip()) continue else: gclient_utils.Error("Input not recognized") continue - elif re.search(r'^CONFLICT', e.stdout, re.M): + elif re.search(br'^CONFLICT', e.stdout, re.M): raise gclient_utils.Error("Conflict while rebasing this branch.\n" "Fix the conflict and run gclient again.\n" "See 'man git-rebase' for details.\n") else: - self.Print(e.stdout.strip()) - self.Print('Rebase produced error output:\n%s' % e.stderr.strip()) + self.Print(e.stdout.decode('utf-8').strip()) + self.Print('Rebase produced error output:\n%s' % + e.stderr.decode('utf-8').strip()) raise gclient_utils.Error("Unrecognized error, please merge or rebase " "manually.\ncd %s && git " % self.checkout_path @@ -1177,7 +1179,7 @@ class GitWrapper(SCMWrapper): try: self._Capture(['rev-list', '-n', '1', 'HEAD']) except subprocess2.CalledProcessError as e: - if ('fatal: bad object HEAD' in e.stderr + if (b'fatal: bad object HEAD' in e.stderr and self.cache_dir and self.cache_dir in url): self.Print(( 'Likely due to DEPS change with git cache_dir, ' diff --git a/testing_support/fake_repos.py b/testing_support/fake_repos.py index 60fff5693..a7f44e001 100755 --- a/testing_support/fake_repos.py +++ b/testing_support/fake_repos.py @@ -980,7 +980,7 @@ class FakeReposTestBase(trial_dir.TestCase): def gitrevparse(self, repo): """Returns the actual revision for a given repo.""" - return self.FAKE_REPOS._git_rev_parse(repo) + return self.FAKE_REPOS._git_rev_parse(repo).decode('utf-8') def main(argv): diff --git a/testing_support/super_mox.py b/testing_support/super_mox.py index 14f363a2c..efe03f30d 100644 --- a/testing_support/super_mox.py +++ b/testing_support/super_mox.py @@ -79,9 +79,6 @@ class TestCaseUtils(object): self.args = self.Args() self.relpath = self.String(200) - def tearDown(self): - pass - class StdoutCheck(object): def setUp(self): @@ -130,7 +127,6 @@ class SuperMoxTestBase(TestCaseUtils, StdoutCheck, mox.MoxTestBase): def tearDown(self): StdoutCheck.tearDown(self) - TestCaseUtils.tearDown(self) mox.MoxTestBase.tearDown(self) def MockList(self, parent, items_to_mock): diff --git a/tests/gclient_scm_test.py b/tests/gclient_scm_test.py index bfb7be748..a9aad58b2 100755 --- a/tests/gclient_scm_test.py +++ b/tests/gclient_scm_test.py @@ -19,10 +19,15 @@ import sys import tempfile import unittest +if sys.version_info.major == 2: + from cStringIO import StringIO +else: + from io import StringIO + sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from third_party import mock from testing_support import fake_repos -from testing_support.super_mox import mox, StdoutCheck, SuperMoxTestBase from testing_support.super_mox import TestCaseUtils import gclient_scm @@ -38,73 +43,37 @@ join = gclient_scm.os.path.join TIMESTAMP_RE = re.compile('\[[0-9]{1,2}:[0-9]{2}:[0-9]{2}\] (.*)', re.DOTALL) def strip_timestamps(value): lines = value.splitlines(True) - for i in xrange(len(lines)): + for i in range(len(lines)): m = TIMESTAMP_RE.match(lines[i]) if m: lines[i] = m.group(1) return ''.join(lines) -class GCBaseTestCase(object): - def assertRaisesError(self, msg, fn, *args, **kwargs): - """Like unittest's assertRaises() but checks for Gclient.Error.""" - try: - fn(*args, **kwargs) - except gclient_scm.gclient_utils.Error as e: - self.assertEquals(e.args[0], msg) - else: - self.fail('%s not raised' % msg) - - -class BaseTestCase(GCBaseTestCase, SuperMoxTestBase): - def setUp(self): - SuperMoxTestBase.setUp(self) - self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'CheckCallAndFilter') - self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'FileRead') - self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'FileWrite') - self.mox.StubOutWithMock(gclient_scm.gclient_utils, 'rmtree') - self.mox.StubOutWithMock(subprocess2, 'communicate') - self.mox.StubOutWithMock(subprocess2, 'Popen') - self._scm_wrapper = gclient_scm.GitWrapper - self._original_GitBinaryExists = gclient_scm.GitWrapper.BinaryExists - gclient_scm.GitWrapper.BinaryExists = staticmethod(lambda : True) - # Absolute path of the fake checkout directory. - self.base_path = join(self.root_dir, self.relpath) - - def tearDown(self): - SuperMoxTestBase.tearDown(self) - gclient_scm.GitWrapper.BinaryExists = self._original_GitBinaryExists - - -class BasicTests(SuperMoxTestBase): - def setUp(self): - SuperMoxTestBase.setUp(self) - - def testGetFirstRemoteUrl(self): +class BasicTests(unittest.TestCase): + @mock.patch('gclient_scm.scm.GIT.Capture') + def testGetFirstRemoteUrl(self, mockCapture): REMOTE_STRINGS = [('remote.origin.url E:\\foo\\bar', 'E:\\foo\\bar'), ('remote.origin.url /b/foo/bar', '/b/foo/bar'), ('remote.origin.url https://foo/bar', 'https://foo/bar'), ('remote.origin.url E:\\Fo Bar\\bax', 'E:\\Fo Bar\\bax'), ('remote.origin.url git://what/"do', 'git://what/"do')] FAKE_PATH = '/fake/path' - self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'Capture') - for question, _ in REMOTE_STRINGS: - gclient_scm.scm.GIT.Capture( - ['config', '--local', '--get-regexp', r'remote.*.url'], - cwd=FAKE_PATH).AndReturn(question) - - self.mox.ReplayAll() + mockCapture.side_effect = [question for question, _ in REMOTE_STRINGS] for _, answer in REMOTE_STRINGS: - self.assertEquals(gclient_scm.SCMWrapper._get_first_remote_url(FAKE_PATH), - answer) + self.assertEqual( + gclient_scm.SCMWrapper._get_first_remote_url(FAKE_PATH), answer) - def tearDown(self): - SuperMoxTestBase.tearDown(self) + expected_calls = [ + mock.call(['config', '--local', '--get-regexp', r'remote.*.url'], + cwd=FAKE_PATH) + for _ in REMOTE_STRINGS + ] + self.assertEqual(mockCapture.mock_calls, expected_calls) -class BaseGitWrapperTestCase(GCBaseTestCase, StdoutCheck, TestCaseUtils, - unittest.TestCase): +class BaseGitWrapperTestCase(unittest.TestCase, TestCaseUtils): """This class doesn't use pymox.""" class OptionsObject(object): def __init__(self, verbose=False, revision=None): @@ -193,7 +162,7 @@ from :3 value = sys.stdout.getvalue() sys.stdout.close() # pylint: disable=no-member - self.assertEquals(expected, strip_timestamps(value)) + self.assertEqual(expected, strip_timestamps(value)) @staticmethod def CreateGitRepo(git_import, path): @@ -205,7 +174,7 @@ from :3 # git is not available, skip this test. return False Popen(['git', 'fast-import', '--quiet'], stdin=PIPE, stdout=PIPE, - stderr=STDOUT, cwd=path).communicate(input=git_import) + stderr=STDOUT, cwd=path).communicate(input=git_import.encode()) Popen(['git', 'checkout', '-q'], stdout=PIPE, stderr=STDOUT, cwd=path).communicate() Popen(['git', 'remote', 'add', '-f', 'origin', '.'], stdout=PIPE, @@ -224,13 +193,13 @@ from :3 def _GetAskForDataCallback(self, expected_prompt, return_value): def AskForData(prompt, options): - self.assertEquals(prompt, expected_prompt) + self.assertEqual(prompt, expected_prompt) return return_value return AskForData def setUp(self): - TestCaseUtils.setUp(self) unittest.TestCase.setUp(self) + TestCaseUtils.setUp(self) self.url = 'git://foo' # The .git suffix allows gclient_scm to recognize the dir as a git repo # when cloning it locally @@ -238,19 +207,12 @@ from :3 self.relpath = '.' self.base_path = join(self.root_dir, self.relpath) self.enabled = self.CreateGitRepo(self.sample_git_import, self.base_path) - StdoutCheck.setUp(self) self._original_GitBinaryExists = gclient_scm.GitWrapper.BinaryExists - gclient_scm.GitWrapper.BinaryExists = staticmethod(lambda : True) - - def tearDown(self): - try: - rmtree(self.root_dir) - StdoutCheck.tearDown(self) - TestCaseUtils.tearDown(self) - unittest.TestCase.tearDown(self) - finally: - # TODO(maruel): Use auto_stub.TestCase. - gclient_scm.GitWrapper.BinaryExists = self._original_GitBinaryExists + mock.patch('gclient_scm.GitWrapper.BinaryExists', + staticmethod(lambda : True)).start() + mock.patch('sys.stdout', StringIO()).start() + self.addCleanup(mock.patch.stopall) + self.addCleanup(lambda: rmtree(self.root_dir)) class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): @@ -267,10 +229,10 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): gclient_scm.os.remove(file_path) file_list = [] scm.revert(options, self.args, file_list) - self.assertEquals(file_list, [file_path]) + self.assertEqual(file_list, [file_path]) file_list = [] scm.diff(options, self.args, file_list) - self.assertEquals(file_list, []) + self.assertEqual(file_list, []) sys.stdout.close() def testRevertNone(self): @@ -283,9 +245,9 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): scm.update(options, None, file_list) file_list = [] scm.revert(options, self.args, file_list) - self.assertEquals(file_list, []) - self.assertEquals(scm.revinfo(options, self.args, None), - 'a7142dc9f0009350b96a11f372b6ea658592aa95') + self.assertEqual(file_list, []) + self.assertEqual(scm.revinfo(options, self.args, None), + 'a7142dc9f0009350b96a11f372b6ea658592aa95') sys.stdout.close() def testRevertModified(self): @@ -297,14 +259,15 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): file_list = [] scm.update(options, None, file_list) file_path = join(self.base_path, 'a') - open(file_path, 'a').writelines('touched\n') + with open(file_path, 'a') as f: + f.writelines('touched\n') file_list = [] scm.revert(options, self.args, file_list) - self.assertEquals(file_list, [file_path]) + self.assertEqual(file_list, [file_path]) file_list = [] scm.diff(options, self.args, file_list) - self.assertEquals(file_list, []) - self.assertEquals(scm.revinfo(options, self.args, None), + self.assertEqual(file_list, []) + self.assertEqual(scm.revinfo(options, self.args, None), 'a7142dc9f0009350b96a11f372b6ea658592aa95') sys.stdout.close() @@ -317,19 +280,18 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): file_list = [] scm.update(options, None, file_list) file_path = join(self.base_path, 'c') - f = open(file_path, 'w') - f.writelines('new\n') - f.close() + with open(file_path, 'w') as f: + f.writelines('new\n') Popen(['git', 'add', 'c'], stdout=PIPE, stderr=STDOUT, cwd=self.base_path).communicate() file_list = [] scm.revert(options, self.args, file_list) - self.assertEquals(file_list, [file_path]) + self.assertEqual(file_list, [file_path]) file_list = [] scm.diff(options, self.args, file_list) - self.assertEquals(file_list, []) - self.assertEquals(scm.revinfo(options, self.args, None), - 'a7142dc9f0009350b96a11f372b6ea658592aa95') + self.assertEqual(file_list, []) + self.assertEqual(scm.revinfo(options, self.args, None), + 'a7142dc9f0009350b96a11f372b6ea658592aa95') sys.stdout.close() def testStatusNew(self): @@ -337,12 +299,13 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): return options = self.Options() file_path = join(self.base_path, 'a') - open(file_path, 'a').writelines('touched\n') + with open(file_path, 'a') as f: + f.writelines('touched\n') scm = gclient_scm.GitWrapper(self.url, self.root_dir, self.relpath) file_list = [] scm.status(options, self.args, file_list) - self.assertEquals(file_list, [file_path]) + self.assertEqual(file_list, [file_path]) self.checkstdout( ('\n________ running \'git -c core.quotePath=false diff --name-status ' '069c602044c5388d2d15c3f875b057c852003458\' in \'%s\'\n\nM\ta\n') % @@ -355,14 +318,15 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): expected_file_list = [] for f in ['a', 'b']: file_path = join(self.base_path, f) - open(file_path, 'a').writelines('touched\n') + with open(file_path, 'a') as f: + f.writelines('touched\n') expected_file_list.extend([file_path]) scm = gclient_scm.GitWrapper(self.url, self.root_dir, self.relpath) file_list = [] scm.status(options, self.args, file_list) expected_file_list = [join(self.base_path, x) for x in ['a', 'b']] - self.assertEquals(sorted(file_list), expected_file_list) + self.assertEqual(sorted(file_list), expected_file_list) self.checkstdout( ('\n________ running \'git -c core.quotePath=false diff --name-status ' '069c602044c5388d2d15c3f875b057c852003458\' in \'%s\'\n\nM\ta\nM\tb\n') @@ -377,8 +341,8 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): self.relpath) file_list = [] scm.update(options, (), file_list) - self.assertEquals(file_list, expected_file_list) - self.assertEquals(scm.revinfo(options, (), None), + self.assertEqual(file_list, expected_file_list) + self.assertEqual(scm.revinfo(options, (), None), 'a7142dc9f0009350b96a11f372b6ea658592aa95') sys.stdout.close() @@ -393,15 +357,15 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): rev = scm.revinfo(options, (), None) file_list = [] scm.update(options, (), file_list) - self.assertEquals(file_list, [join(self.base_path, x) - for x in ['a', 'b', 'c']]) + self.assertEqual(file_list, [join(self.base_path, x) + for x in ['a', 'b', 'c']]) # The actual commit that is created is unstable, so we verify its tree and # parents instead. - self.assertEquals(scm._Capture(['rev-parse', 'HEAD:']), - 'd2e35c10ac24d6c621e14a1fcadceb533155627d') - self.assertEquals(scm._Capture(['rev-parse', 'HEAD^1']), rev) - self.assertEquals(scm._Capture(['rev-parse', 'HEAD^2']), - scm._Capture(['rev-parse', 'origin/master'])) + self.assertEqual(scm._Capture(['rev-parse', 'HEAD:']), + 'd2e35c10ac24d6c621e14a1fcadceb533155627d') + self.assertEqual(scm._Capture(['rev-parse', 'HEAD^1']), rev) + self.assertEqual(scm._Capture(['rev-parse', 'HEAD^2']), + scm._Capture(['rev-parse', 'origin/master'])) sys.stdout.close() def testUpdateRebase(self): @@ -417,14 +381,14 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): 'Cannot fast-forward merge, attempt to rebase? ' '(y)es / (q)uit / (s)kip : ', 'y') scm.update(options, (), file_list) - self.assertEquals(file_list, [join(self.base_path, x) - for x in ['a', 'b', 'c']]) + self.assertEqual(file_list, [join(self.base_path, x) + for x in ['a', 'b', 'c']]) # The actual commit that is created is unstable, so we verify its tree and # parent instead. - self.assertEquals(scm._Capture(['rev-parse', 'HEAD:']), - 'd2e35c10ac24d6c621e14a1fcadceb533155627d') - self.assertEquals(scm._Capture(['rev-parse', 'HEAD^']), - scm._Capture(['rev-parse', 'origin/master'])) + self.assertEqual(scm._Capture(['rev-parse', 'HEAD:']), + 'd2e35c10ac24d6c621e14a1fcadceb533155627d') + self.assertEqual(scm._Capture(['rev-parse', 'HEAD^']), + scm._Capture(['rev-parse', 'origin/master'])) sys.stdout.close() def testUpdateReset(self): @@ -435,10 +399,12 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): dir_path = join(self.base_path, 'c') os.mkdir(dir_path) - open(join(dir_path, 'nested'), 'w').writelines('new\n') + with open(join(dir_path, 'nested'), 'w') as f: + f.writelines('new\n') file_path = join(self.base_path, 'file') - open(file_path, 'w').writelines('new\n') + with open(file_path, 'w') as f: + f.writelines('new\n') scm = gclient_scm.GitWrapper(self.url, self.root_dir, self.relpath) @@ -461,8 +427,8 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): file_list = [] scm.update(options, (), file_list) - self.assertEquals(scm.revinfo(options, (), None), - '069c602044c5388d2d15c3f875b057c852003458') + self.assertEqual(scm.revinfo(options, (), None), + '069c602044c5388d2d15c3f875b057c852003458') sys.stdout.close() def testUpdateResetDeleteUnversionedTrees(self): @@ -474,10 +440,12 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): dir_path = join(self.base_path, 'dir') os.mkdir(dir_path) - open(join(dir_path, 'nested'), 'w').writelines('new\n') + with open(join(dir_path, 'nested'), 'w') as f: + f.writelines('new\n') file_path = join(self.base_path, 'file') - open(file_path, 'w').writelines('new\n') + with open(file_path, 'w') as f: + f.writelines('new\n') scm = gclient_scm.GitWrapper(self.url, self.root_dir, self.relpath) @@ -494,7 +462,8 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): scm = gclient_scm.GitWrapper(self.url, self.root_dir, self.relpath) file_path = join(self.base_path, 'b') - open(file_path, 'w').writelines('conflict\n') + with open(file_path, 'w') as f: + f.writelines('conflict\n') try: scm.update(options, (), []) self.fail() @@ -544,19 +513,29 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): scm = gclient_scm.GitWrapper(self.url, self.root_dir, self.relpath) file_path = join(self.base_path, 'b') - open(file_path, 'w').writelines('conflict\n') + with open(file_path, 'w') as f: + f.writelines('conflict\n') scm._Run(['commit', '-am', 'test'], options) scm._AskForData = self._GetAskForDataCallback( 'Cannot fast-forward merge, attempt to rebase? ' '(y)es / (q)uit / (s)kip : ', 'y') - exception = ('Conflict while rebasing this branch.\n' - 'Fix the conflict and run gclient again.\n' - 'See \'man git-rebase\' for details.\n') - self.assertRaisesError(exception, scm.update, options, (), []) - exception = ('\n____ . at refs/remotes/origin/master\n' - '\tYou have unstaged changes.\n' - '\tPlease commit, stash, or reset.\n') - self.assertRaisesError(exception, scm.update, options, (), []) + + with self.assertRaises(gclient_scm.gclient_utils.Error) as e: + scm.update(options, (), []) + self.assertEqual( + e.exception.args[0], + 'Conflict while rebasing this branch.\n' + 'Fix the conflict and run gclient again.\n' + 'See \'man git-rebase\' for details.\n') + + with self.assertRaises(gclient_scm.gclient_utils.Error) as e: + scm.update(options, (), []) + self.assertEqual( + e.exception.args[0], + '\n____ . at refs/remotes/origin/master\n' + '\tYou have unstaged changes.\n' + '\tPlease commit, stash, or reset.\n') + sys.stdout.close() def testRevinfo(self): @@ -566,7 +545,7 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): scm = gclient_scm.GitWrapper(self.url, self.root_dir, self.relpath) rev_info = scm.revinfo(options, (), None) - self.assertEquals(rev_info, '069c602044c5388d2d15c3f875b057c852003458') + self.assertEqual(rev_info, '069c602044c5388d2d15c3f875b057c852003458') def testMirrorPushUrl(self): if not self.enabled: @@ -600,11 +579,11 @@ class ManagedGitWrapperTestCase(BaseGitWrapperTestCase): ' fetch_url: %s' % fetch_url, ' mirror: %s' % mirror])) push_url = scm._Capture(['remote', 'get-url', '--push', 'origin']) - self.assertEquals(push_url, self.url) + self.assertEqual(push_url, self.url) sys.stdout.close() -class ManagedGitWrapperTestCaseMox(BaseTestCase): +class ManagedGitWrapperTestCaseMock(unittest.TestCase): class OptionsObject(object): def __init__(self, verbose=False, revision=None, force=False): self.verbose = verbose @@ -627,10 +606,9 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase): value = sys.stdout.getvalue() sys.stdout.close() # pylint: disable=no-member - self.assertEquals(expected, strip_timestamps(value)) + self.assertEqual(expected, strip_timestamps(value)) def setUp(self): - BaseTestCase.setUp(self) self.fake_hash_1 = 't0ta11yf4k3' self.fake_hash_2 = '3v3nf4k3r' self.url = 'git://foo' @@ -639,107 +617,94 @@ class ManagedGitWrapperTestCaseMox(BaseTestCase): self.base_path = os.path.join(self.root_dir, self.relpath) self.backup_base_path = os.path.join(self.root_dir, 'old_%s.git' % self.relpath) - - def tearDown(self): - BaseTestCase.tearDown(self) - - def testGetUsableRevGit(self): + mock.patch('gclient_scm.scm.GIT.ApplyEnvVars').start() + mock.patch('gclient_scm.GitWrapper._CheckMinVersion').start() + mock.patch('gclient_scm.GitWrapper._Fetch').start() + mock.patch('gclient_scm.GitWrapper._DeleteOrMove').start() + mock.patch('sys.stdout', StringIO()).start() + self.addCleanup(mock.patch.stopall) + + @mock.patch('scm.GIT.IsValidRevision') + @mock.patch('os.path.isdir', lambda _: True) + def testGetUsableRevGit(self, mockIsValidRevision): # pylint: disable=no-member options = self.Options(verbose=True) - self.mox.StubOutWithMock(gclient_scm.scm.GIT, 'IsValidRevision', True) - gclient_scm.scm.GIT.IsValidRevision(cwd=self.base_path, rev=self.fake_hash_1 - ).AndReturn(True) - gclient_scm.scm.GIT.IsValidRevision(cwd=self.base_path, rev='1' - ).AndReturn(False) - gclient_scm.scm.GIT.IsValidRevision(cwd=self.base_path, rev='1' - ).AndReturn(False) - - self.mox.StubOutWithMock(gclient_scm.GitWrapper, '_Fetch', True) - # pylint: disable=no-value-for-parameter - gclient_scm.GitWrapper._Fetch(options).AndReturn(None) - - gclient_scm.scm.os.path.isdir(self.base_path).AndReturn(True) - gclient_scm.os.path.isdir(self.base_path).AndReturn(True) - - self.mox.ReplayAll() + mockIsValidRevision.side_effect = lambda cwd, rev: rev != '1' git_scm = gclient_scm.GitWrapper(self.url, self.root_dir, self.relpath) # A [fake] git sha1 with a git repo should work (this is in the case that # the LKGR gets flipped to git sha1's some day). - self.assertEquals(git_scm.GetUsableRev(self.fake_hash_1, options), - self.fake_hash_1) + self.assertEqual(git_scm.GetUsableRev(self.fake_hash_1, options), + self.fake_hash_1) # An SVN rev with an existing purely git repo should raise an exception. self.assertRaises(gclient_scm.gclient_utils.Error, git_scm.GetUsableRev, '1', options) - def testUpdateNoDotGit(self): - options = self.Options() + @mock.patch('gclient_scm.GitWrapper._Clone') + @mock.patch('os.path.isdir') + @mock.patch('os.path.exists') + @mock.patch('subprocess2.check_output') + def testUpdateNoDotGit( + self, mockCheckOutput, mockExists, mockIsdir, mockClone): + mockIsdir.side_effect = lambda path: path == self.base_path + mockExists.side_effect = lambda path: path == self.base_path + mockCheckOutput.return_value = b'' - gclient_scm.os.path.isdir( - os.path.join(self.base_path, '.git', 'hooks')).AndReturn(False) - gclient_scm.os.path.exists(self.backup_base_path).AndReturn(False) - gclient_scm.os.path.exists(self.base_path).AndReturn(True) - gclient_scm.os.path.isdir(self.base_path).AndReturn(True) - gclient_scm.os.path.exists(os.path.join(self.base_path, '.git') - ).AndReturn(False) - self.mox.StubOutWithMock(gclient_scm.GitWrapper, '_Clone', True) - # pylint: disable=no-value-for-parameter - gclient_scm.GitWrapper._Clone('refs/remotes/origin/master', self.url, - options) - self.mox.StubOutWithMock(gclient_scm.subprocess2, 'check_output', True) - gclient_scm.subprocess2.check_output( - ['git', '-c', 'core.quotePath=false', 'ls-files'], cwd=self.base_path, - env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1,).AndReturn('') - gclient_scm.subprocess2.check_output( - ['git', 'rev-parse', '--verify', 'HEAD'], - cwd=self.base_path, - env=gclient_scm.scm.GIT.ApplyEnvVars({}), - stderr=-1, - ).AndReturn('') - - self.mox.ReplayAll() - scm = self._scm_wrapper(self.url, self.root_dir, - self.relpath) + options = self.Options() + scm = gclient_scm.GitWrapper( + self.url, self.root_dir, self.relpath) scm.update(options, None, []) + + env = gclient_scm.scm.GIT.ApplyEnvVars({}) + self.assertEqual( + mockCheckOutput.mock_calls, + [ + mock.call( + ['git', '-c', 'core.quotePath=false', 'ls-files'], + cwd=self.base_path, env=env, stderr=-1), + mock.call( + ['git', 'rev-parse', '--verify', 'HEAD'], + cwd=self.base_path, env=env, stderr=-1), + ]) + mockClone.assert_called_with( + 'refs/remotes/origin/master', self.url, options) self.checkstdout('\n') - def testUpdateConflict(self): - options = self.Options() + @mock.patch('gclient_scm.GitWrapper._Clone') + @mock.patch('os.path.isdir') + @mock.patch('os.path.exists') + @mock.patch('subprocess2.check_output') + def testUpdateConflict( + self, mockCheckOutput, mockExists, mockIsdir, mockClone): + mockIsdir.side_effect = lambda path: path == self.base_path + mockExists.side_effect = lambda path: path == self.base_path + mockCheckOutput.return_value = b'' + mockClone.side_effect = [ + gclient_scm.subprocess2.CalledProcessError( + None, None, None, None, None), + None, + ] - gclient_scm.os.path.isdir( - os.path.join(self.base_path, '.git', 'hooks')).AndReturn(False) - gclient_scm.os.path.exists(self.backup_base_path).AndReturn(False) - gclient_scm.os.path.exists(self.base_path).AndReturn(True) - gclient_scm.os.path.isdir(self.base_path).AndReturn(True) - gclient_scm.os.path.exists(os.path.join(self.base_path, '.git') - ).AndReturn(False) - self.mox.StubOutWithMock(gclient_scm.GitWrapper, '_Clone', True) - # pylint: disable=no-value-for-parameter - gclient_scm.GitWrapper._Clone( - 'refs/remotes/origin/master', self.url, options - ).AndRaise(gclient_scm.subprocess2.CalledProcessError(None, None, None, - None, None)) - self.mox.StubOutWithMock(gclient_scm.GitWrapper, '_DeleteOrMove', True) - gclient_scm.GitWrapper._DeleteOrMove(False) - gclient_scm.GitWrapper._Clone('refs/remotes/origin/master', self.url, - options) - self.mox.StubOutWithMock(gclient_scm.subprocess2, 'check_output', True) - gclient_scm.subprocess2.check_output( - ['git', '-c', 'core.quotePath=false', 'ls-files'], cwd=self.base_path, - env=gclient_scm.scm.GIT.ApplyEnvVars({}), stderr=-1,).AndReturn('') - gclient_scm.subprocess2.check_output( - ['git', 'rev-parse', '--verify', 'HEAD'], - cwd=self.base_path, - env=gclient_scm.scm.GIT.ApplyEnvVars({}), - stderr=-1, - ).AndReturn('') - - self.mox.ReplayAll() - scm = self._scm_wrapper(self.url, self.root_dir, + options = self.Options() + scm = gclient_scm.GitWrapper(self.url, self.root_dir, self.relpath) scm.update(options, None, []) + + env = gclient_scm.scm.GIT.ApplyEnvVars({}) + self.assertEqual( + mockCheckOutput.mock_calls, + [ + mock.call( + ['git', '-c', 'core.quotePath=false', 'ls-files'], + cwd=self.base_path, env=env, stderr=-1), + mock.call( + ['git', 'rev-parse', '--verify', 'HEAD'], + cwd=self.base_path, env=env, stderr=-1), + ]) + mockClone.assert_called_with( + 'refs/remotes/origin/master', self.url, options) self.checkstdout('\n') @@ -784,11 +749,11 @@ class UnmanagedGitWrapperTestCase(BaseGitWrapperTestCase): options.revision = 'unmanaged' scm.update(options, (), file_list) - self.assertEquals(file_list, expected_file_list) - self.assertEquals(scm.revinfo(options, (), None), - '069c602044c5388d2d15c3f875b057c852003458') + self.assertEqual(file_list, expected_file_list) + self.assertEqual(scm.revinfo(options, (), None), + '069c602044c5388d2d15c3f875b057c852003458') # indicates detached HEAD - self.assertEquals(self.getCurrentBranch(), None) + self.assertEqual(self.getCurrentBranch(), None) self.checkInStdout( 'Checked out refs/remotes/origin/master to a detached HEAD') @@ -816,11 +781,11 @@ class UnmanagedGitWrapperTestCase(BaseGitWrapperTestCase): options.revision = 'unmanaged' scm.update(options, (), file_list) - self.assertEquals(file_list, expected_file_list) - self.assertEquals(scm.revinfo(options, (), None), - 'a7142dc9f0009350b96a11f372b6ea658592aa95') + self.assertEqual(file_list, expected_file_list) + self.assertEqual(scm.revinfo(options, (), None), + 'a7142dc9f0009350b96a11f372b6ea658592aa95') # indicates detached HEAD - self.assertEquals(self.getCurrentBranch(), None) + self.assertEqual(self.getCurrentBranch(), None) self.checkInStdout( 'Checked out a7142dc9f0009350b96a11f372b6ea658592aa95 to a detached HEAD') @@ -848,11 +813,11 @@ class UnmanagedGitWrapperTestCase(BaseGitWrapperTestCase): options.revision = 'unmanaged' scm.update(options, (), file_list) - self.assertEquals(file_list, expected_file_list) - self.assertEquals(scm.revinfo(options, (), None), - '9a51244740b25fa2ded5252ca00a3178d3f665a9') + self.assertEqual(file_list, expected_file_list) + self.assertEqual(scm.revinfo(options, (), None), + '9a51244740b25fa2ded5252ca00a3178d3f665a9') # indicates detached HEAD - self.assertEquals(self.getCurrentBranch(), None) + self.assertEqual(self.getCurrentBranch(), None) self.checkInStdout( 'Checked out 9a51244740b25fa2ded5252ca00a3178d3f665a9 ' 'to a detached HEAD') @@ -881,11 +846,11 @@ class UnmanagedGitWrapperTestCase(BaseGitWrapperTestCase): options.revision = 'unmanaged' scm.update(options, (), file_list) - self.assertEquals(file_list, expected_file_list) - self.assertEquals(scm.revinfo(options, (), None), - '9a51244740b25fa2ded5252ca00a3178d3f665a9') + self.assertEqual(file_list, expected_file_list) + self.assertEqual(scm.revinfo(options, (), None), + '9a51244740b25fa2ded5252ca00a3178d3f665a9') # indicates detached HEAD - self.assertEquals(self.getCurrentBranch(), None) + self.assertEqual(self.getCurrentBranch(), None) self.checkInStdout( 'Checked out refs/remotes/origin/feature to a detached HEAD') @@ -913,9 +878,9 @@ class UnmanagedGitWrapperTestCase(BaseGitWrapperTestCase): options.revision = 'unmanaged' scm.update(options, (), file_list) - self.assertEquals(file_list, expected_file_list) - self.assertEquals(scm.revinfo(options, (), None), - '9a51244740b25fa2ded5252ca00a3178d3f665a9') + self.assertEqual(file_list, expected_file_list) + self.assertEqual(scm.revinfo(options, (), None), + '9a51244740b25fa2ded5252ca00a3178d3f665a9') # @refs/heads/feature is AKA @refs/remotes/origin/feature in the clone, so # should be treated as such by gclient. # TODO(mmoss): Though really, we should only allow DEPS to specify branches @@ -924,7 +889,7 @@ class UnmanagedGitWrapperTestCase(BaseGitWrapperTestCase): # defaults at some point). But that will take more work to stop using # refs/remotes/ everywhere that we do (and to stop assuming a DEPS ref will # always resolve locally, like when passing them to show-ref or rev-list). - self.assertEquals(self.getCurrentBranch(), None) + self.assertEqual(self.getCurrentBranch(), None) self.checkInStdout( 'Checked out refs/remotes/origin/feature to a detached HEAD') @@ -940,19 +905,18 @@ class UnmanagedGitWrapperTestCase(BaseGitWrapperTestCase): file_list = [] options.revision = 'unmanaged' scm.update(options, (), file_list) - self.assertEquals(file_list, expected_file_list) - self.assertEquals(scm.revinfo(options, (), None), - '069c602044c5388d2d15c3f875b057c852003458') + self.assertEqual(file_list, expected_file_list) + self.assertEqual(scm.revinfo(options, (), None), + '069c602044c5388d2d15c3f875b057c852003458') self.checkstdout('________ unmanaged solution; skipping .\n') -class CipdWrapperTestCase(BaseTestCase): +class CipdWrapperTestCase(unittest.TestCase): def setUp(self): # Create this before setting up mocks. self._cipd_root_dir = tempfile.mkdtemp() self._workdir = tempfile.mkdtemp() - BaseTestCase.setUp(self) self._cipd_instance_url = 'https://chrome-infra-packages.appspot.com' self._cipd_root = gclient_scm.CipdRoot( @@ -963,12 +927,13 @@ class CipdWrapperTestCase(BaseTestCase): self._cipd_root.add_package('b', 'bar_package', 'bar_version'), self._cipd_root.add_package('b', 'baz_package', 'baz_version'), ] - self.mox.StubOutWithMock(self._cipd_root, 'add_package') - self.mox.StubOutWithMock(self._cipd_root, 'clobber') - self.mox.StubOutWithMock(self._cipd_root, 'ensure') + mock.patch('tempfile.mkdtemp', lambda: self._workdir).start() + mock.patch('gclient_scm.CipdRoot.add_package').start() + mock.patch('gclient_scm.CipdRoot.clobber').start() + mock.patch('gclient_scm.CipdRoot.ensure').start() + self.addCleanup(mock.patch.stopall) def tearDown(self): - BaseTestCase.tearDown(self) rmtree(self._cipd_root_dir) rmtree(self._workdir) @@ -989,14 +954,12 @@ class CipdWrapperTestCase(BaseTestCase): def testRevert(self): """Checks that revert does nothing.""" - scm = self.createScmWithPackageThatSatisfies( - lambda _: True) - - self.mox.ReplayAll() - + scm = self.createScmWithPackageThatSatisfies(lambda _: True) scm.revert(None, (), []) - def testRevinfo(self): + @mock.patch('gclient_scm.gclient_utils.CheckCallAndFilter') + @mock.patch('gclient_scm.gclient_utils.rmtree') + def testRevinfo(self, mockRmtree, mockCheckCallAndFilter): """Checks that revinfo uses the JSON from cipd describe.""" scm = self.createScmWithPackageThatSatisfies(lambda _: True) @@ -1012,31 +975,20 @@ class CipdWrapperTestCase(BaseTestCase): with open(describe_json_path, 'w') as describe_json: json.dump(json_contents, describe_json) - cmd = [ + revinfo = scm.revinfo(None, (), []) + self.assertEqual(revinfo, expected_revinfo) + + mockRmtree.assert_called_with(self._workdir) + mockCheckCallAndFilter.assert_called_with([ 'cipd', 'describe', 'foo_package', '-log-level', 'error', '-version', 'foo_version', '-json-output', describe_json_path, - ] - - self.mox.StubOutWithMock(tempfile, 'mkdtemp') - - tempfile.mkdtemp().AndReturn(self._workdir) - gclient_scm.gclient_utils.CheckCallAndFilter(cmd) - gclient_scm.gclient_utils.rmtree(self._workdir) - - self.mox.ReplayAll() - - revinfo = scm.revinfo(None, (), []) - self.assertEquals(revinfo, expected_revinfo) + ]) def testUpdate(self): """Checks that update does nothing.""" - scm = self.createScmWithPackageThatSatisfies( - lambda _: True) - - self.mox.ReplayAll() - + scm = self.createScmWithPackageThatSatisfies(lambda _: True) scm.update(None, (), []) @@ -1327,7 +1279,7 @@ class GerritChangesTest(fake_repos.FakeReposTestBase): self.url, 'refs/changes/36/1236/1', 'refs/heads/master', self.options, file_list) self.assertEqual(cm.exception.cmd[:2], ['git', 'cherry-pick']) - self.assertIn('error: could not apply', cm.exception.stderr) + self.assertIn(b'error: could not apply', cm.exception.stderr) # Try to apply 'refs/changes/35/1235/1', which doesn't have a merge # conflict.