Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2016 The LUCI Authors. All rights reserved. | 2 # Copyright 2016 The LUCI Authors. All rights reserved. |
| 3 # Use of this source code is governed under the Apache License, Version 2.0 | 3 # Use of this source code is governed under the Apache License, Version 2.0 |
| 4 # that can be found in the LICENSE file. | 4 # that can be found in the LICENSE file. |
| 5 | 5 |
| 6 import base64 | 6 import base64 |
| 7 import io | 7 import io |
| 8 import json | 8 import json |
| 9 import os | 9 import os |
| 10 import sys | 10 import sys |
| 11 import unittest | 11 import unittest |
| 12 import time | 12 import time |
| 13 | 13 |
| 14 import test_env | 14 import test_env |
| 15 | 15 |
| 16 import mock | 16 import mock |
| 17 import subprocess42 | 17 import subprocess42 |
| 18 | 18 |
| 19 from recipe_engine import fetch | 19 from recipe_engine import fetch |
| 20 from recipe_engine import requests_ssl | 20 from recipe_engine import requests_ssl |
| 21 | 21 |
| 22 | 22 |
| 23 class TestGit(unittest.TestCase): | 23 class TestGit(unittest.TestCase): |
|
martiniss
2016/09/26 22:58:02
Can you add a test case like in the bug? :)
dnj
2016/09/26 23:48:57
Done.
| |
| 24 @mock.patch('recipe_engine.fetch._run_git') | 24 |
| 25 def test_fresh_clone(self, run_git): | 25 def setUp(self): |
| 26 self._patchers = [ | |
| 27 mock.patch('logging.warning'), | |
| 28 mock.patch('recipe_engine.fetch.GitBackend.Git._resolve_git', | |
| 29 return_value='GIT'), | |
| 30 ] | |
| 31 for p in self._patchers: | |
| 32 p.start() | |
| 33 | |
| 34 def tearDown(self): | |
| 35 for p in reversed(self._patchers): | |
| 36 p.stop() | |
| 37 | |
| 38 @mock.patch('recipe_engine.fetch.GitBackend.Git._execute') | |
| 39 def test_fresh_clone(self, git): | |
| 26 fetch.GitBackend().checkout( | 40 fetch.GitBackend().checkout( |
| 27 'repo', 'revision', 'dir', allow_fetch=True) | 41 'repo', 'revision', 'dir', allow_fetch=True) |
| 28 run_git.assert_has_calls([ | 42 git.assert_has_calls([ |
| 29 mock.call(None, 'clone', '-q', 'repo', 'dir'), | 43 mock.call('GIT', 'clone', '-q', 'repo', 'dir'), |
| 30 mock.call('dir', 'config', 'remote.origin.url', 'repo'), | 44 mock.call('GIT', '-C', 'dir', 'config', 'remote.origin.url', 'repo'), |
| 31 mock.call('dir', 'rev-parse', '-q', '--verify', 'revision^{commit}'), | 45 mock.call('GIT', '-C', 'dir', 'rev-parse', '-q', '--verify', |
| 32 mock.call('dir', 'reset', '-q', '--hard', 'revision'), | 46 'revision^{commit}'), |
| 47 mock.call('GIT', '-C', 'dir', 'reset', '-q', '--hard', 'revision'), | |
| 33 ]) | 48 ]) |
| 34 | 49 |
| 35 @mock.patch('os.path.isdir') | 50 @mock.patch('os.path.isdir') |
| 36 @mock.patch('recipe_engine.fetch._run_git') | 51 @mock.patch('recipe_engine.fetch.GitBackend.Git._execute') |
| 37 def test_existing_checkout(self, run_git, isdir): | 52 def test_existing_checkout(self, git, isdir): |
| 38 isdir.return_value = True | 53 isdir.return_value = True |
| 39 fetch.GitBackend().checkout( | 54 fetch.GitBackend().checkout( |
| 40 'repo', 'revision', 'dir', allow_fetch=True) | 55 'repo', 'revision', 'dir', allow_fetch=True) |
| 41 isdir.assert_has_calls([ | 56 isdir.assert_has_calls([ |
| 42 mock.call('dir'), | 57 mock.call('dir'), |
| 43 mock.call('dir/.git'), | 58 mock.call('dir/.git'), |
| 44 ]) | 59 ]) |
| 45 run_git.assert_has_calls([ | 60 git.assert_has_calls([ |
| 46 mock.call('dir', 'config', 'remote.origin.url', 'repo'), | 61 mock.call('GIT', '-C', 'dir', 'config', 'remote.origin.url', 'repo'), |
| 47 mock.call('dir', 'rev-parse', '-q', '--verify', 'revision^{commit}'), | 62 mock.call('GIT', '-C', 'dir', 'rev-parse', '-q', '--verify', |
| 48 mock.call('dir', 'reset', '-q', '--hard', 'revision'), | 63 'revision^{commit}'), |
| 64 mock.call('GIT', '-C', 'dir', 'reset', '-q', '--hard', 'revision'), | |
| 49 ]) | 65 ]) |
| 50 | 66 |
| 51 @mock.patch('recipe_engine.fetch._run_git') | 67 @mock.patch('recipe_engine.fetch.GitBackend.Git._execute') |
| 52 def test_clone_not_allowed(self, run_git): | 68 def test_clone_not_allowed(self, git): |
| 53 with self.assertRaises(fetch.FetchNotAllowedError): | 69 with self.assertRaises(fetch.FetchNotAllowedError): |
| 54 fetch.GitBackend().checkout( | 70 fetch.GitBackend().checkout( |
| 55 'repo', 'revision', 'dir', allow_fetch=False) | 71 'repo', 'revision', 'dir', allow_fetch=False) |
| 56 | 72 |
| 57 @mock.patch('os.path.isdir') | 73 @mock.patch('os.path.isdir') |
| 58 @mock.patch('recipe_engine.fetch._run_git') | 74 @mock.patch('recipe_engine.fetch.GitBackend.Git._execute') |
| 59 def test_unclean_filesystem(self, run_git, isdir): | 75 def test_unclean_filesystem(self, git, isdir): |
| 60 isdir.side_effect = [True, False] | 76 isdir.side_effect = [True, False] |
| 61 with self.assertRaises(fetch.UncleanFilesystemError): | 77 with self.assertRaises(fetch.UncleanFilesystemError): |
| 62 fetch.GitBackend().checkout( | 78 fetch.GitBackend().checkout( |
| 63 'repo', 'revision', 'dir', allow_fetch=False) | 79 'repo', 'revision', 'dir', allow_fetch=False) |
| 64 isdir.assert_has_calls([ | 80 isdir.assert_has_calls([ |
| 65 mock.call('dir'), | 81 mock.call('dir'), |
| 66 mock.call('dir/.git'), | 82 mock.call('dir/.git'), |
| 67 ]) | 83 ]) |
| 68 | 84 |
| 69 @mock.patch('os.path.isdir') | 85 @mock.patch('os.path.isdir') |
| 70 @mock.patch('recipe_engine.fetch._run_git') | 86 @mock.patch('recipe_engine.fetch.GitBackend.Git._execute') |
| 71 def test_origin_mismatch(self, run_git, isdir): | 87 def test_origin_mismatch(self, git, isdir): |
| 72 run_git.return_value = 'not-repo' | 88 git.return_value = 'not-repo' |
| 73 isdir.return_value = True | 89 isdir.return_value = True |
| 74 | 90 |
| 75 # This should not raise UncleanFilesystemError, but instead | 91 # This should not raise UncleanFilesystemError, but instead |
| 76 # set the right origin automatically. | 92 # set the right origin automatically. |
| 77 fetch.GitBackend().checkout( | 93 fetch.GitBackend().checkout( |
| 78 'repo', 'revision', 'dir', allow_fetch=False) | 94 'repo', 'revision', 'dir', allow_fetch=False) |
| 79 | 95 |
| 80 isdir.assert_has_calls([ | 96 isdir.assert_has_calls([ |
| 81 mock.call('dir'), | 97 mock.call('dir'), |
| 82 mock.call('dir/.git'), | 98 mock.call('dir/.git'), |
| 83 ]) | 99 ]) |
| 84 run_git.assert_has_calls([ | 100 git.assert_has_calls([ |
| 85 mock.call('dir', 'config', 'remote.origin.url', 'repo'), | 101 mock.call('GIT', '-C', 'dir', 'config', 'remote.origin.url', 'repo'), |
| 86 ]) | 102 ]) |
| 87 | 103 |
| 88 @mock.patch('os.path.isdir') | 104 @mock.patch('os.path.isdir') |
| 89 @mock.patch('recipe_engine.fetch._run_git') | 105 @mock.patch('recipe_engine.fetch.GitBackend.Git._execute') |
| 90 def test_rev_parse_fail(self, run_git, isdir): | 106 def test_rev_parse_fail(self, git, isdir): |
| 91 run_git.side_effect = [ | 107 git.side_effect = [ |
| 92 None, | 108 None, |
| 93 subprocess42.CalledProcessError(1, ['fakecmd']), | 109 subprocess42.CalledProcessError(1, ['fakecmd']), |
| 94 None, | 110 None, |
| 95 None, | 111 None, |
| 96 ] | 112 ] |
| 97 isdir.return_value = True | 113 isdir.return_value = True |
| 98 fetch.GitBackend().checkout( | 114 fetch.GitBackend().checkout( |
| 99 'repo', 'revision', 'dir', allow_fetch=True) | 115 'repo', 'revision', 'dir', allow_fetch=True) |
| 100 isdir.assert_has_calls([ | 116 isdir.assert_has_calls([ |
| 101 mock.call('dir'), | 117 mock.call('dir'), |
| 102 mock.call('dir/.git'), | 118 mock.call('dir/.git'), |
| 103 ]) | 119 ]) |
| 104 run_git.assert_has_calls([ | 120 git.assert_has_calls([ |
| 105 mock.call('dir', 'config', 'remote.origin.url', 'repo'), | 121 mock.call('GIT', '-C', 'dir', 'config', 'remote.origin.url', 'repo'), |
| 106 mock.call('dir', 'rev-parse', '-q', '--verify', 'revision^{commit}'), | 122 mock.call('GIT', '-C', 'dir', 'rev-parse', '-q', '--verify', |
| 107 mock.call('dir', 'fetch'), | 123 'revision^{commit}'), |
| 108 mock.call('dir', 'reset', '-q', '--hard', 'revision'), | 124 mock.call('GIT', '-C', 'dir', 'fetch'), |
| 125 mock.call('GIT', '-C', 'dir', 'reset', '-q', '--hard', 'revision'), | |
| 109 ]) | 126 ]) |
| 110 | 127 |
| 111 @mock.patch('os.path.isdir') | 128 @mock.patch('os.path.isdir') |
| 112 @mock.patch('recipe_engine.fetch._run_git') | 129 @mock.patch('recipe_engine.fetch.GitBackend.Git._execute') |
| 113 def test_rev_parse_fetch_not_allowed(self, run_git, isdir): | 130 def test_rev_parse_fetch_not_allowed(self, git, isdir): |
| 114 run_git.side_effect = [ | 131 git.side_effect = [ |
| 115 None, | 132 None, |
| 116 subprocess42.CalledProcessError(1, ['fakecmd']), | 133 subprocess42.CalledProcessError(1, ['fakecmd']), |
| 117 ] | 134 ] |
| 118 isdir.return_value = True | 135 isdir.return_value = True |
| 119 with self.assertRaises(fetch.FetchNotAllowedError): | 136 with self.assertRaises(fetch.FetchNotAllowedError): |
| 120 fetch.GitBackend().checkout( | 137 fetch.GitBackend().checkout( |
| 121 'repo', 'revision', 'dir', allow_fetch=False) | 138 'repo', 'revision', 'dir', allow_fetch=False) |
| 122 isdir.assert_has_calls([ | 139 isdir.assert_has_calls([ |
| 123 mock.call('dir'), | 140 mock.call('dir'), |
| 124 mock.call('dir/.git'), | 141 mock.call('dir/.git'), |
| 125 ]) | 142 ]) |
| 126 run_git.assert_has_calls([ | 143 git.assert_has_calls([ |
| 127 mock.call('dir', 'config', 'remote.origin.url', 'repo'), | 144 mock.call('GIT', '-C', 'dir', 'config', 'remote.origin.url', 'repo'), |
| 128 mock.call('dir', 'rev-parse', '-q', '--verify', 'revision^{commit}'), | 145 mock.call('GIT', '-C', 'dir', 'rev-parse', '-q', '--verify', |
| 146 'revision^{commit}'), | |
| 129 ]) | 147 ]) |
| 130 | 148 |
| 131 @mock.patch('recipe_engine.fetch._run_git') | 149 @mock.patch('recipe_engine.fetch.GitBackend.Git._execute') |
| 132 def test_commit_metadata(self, run_git): | 150 def test_commit_metadata(self, git): |
| 133 run_git.side_effect = ['author', 'message'] | 151 git.side_effect = ['author', 'message'] |
| 134 result = fetch.GitBackend().commit_metadata( | 152 result = fetch.GitBackend().commit_metadata( |
| 135 'repo', 'revision', 'dir', allow_fetch=True) | 153 'repo', 'revision', 'dir', allow_fetch=True) |
| 136 self.assertEqual(result, { | 154 self.assertEqual(result, { |
| 137 'author': 'author', | 155 'author': 'author', |
| 138 'message': 'message', | 156 'message': 'message', |
| 139 }) | 157 }) |
| 140 run_git.assert_has_calls([ | 158 git.assert_has_calls([ |
| 141 mock.call('dir', 'show', '-s', '--pretty=%aE', 'revision'), | 159 mock.call('GIT', '-C', 'dir', 'show', '-s', '--pretty=%aE', 'revision'), |
| 142 mock.call('dir', 'show', '-s', '--pretty=%B', 'revision'), | 160 mock.call('GIT', '-C', 'dir', 'show', '-s', '--pretty=%B', 'revision'), |
| 143 ]) | 161 ]) |
| 144 | 162 |
| 145 | 163 |
| 146 class TestGitiles(unittest.TestCase): | 164 class TestGitiles(unittest.TestCase): |
| 147 def setUp(self): | 165 def setUp(self): |
| 148 requests_ssl.disable_check() | 166 requests_ssl.disable_check() |
| 149 | 167 |
| 150 @mock.patch('__builtin__.open', mock.mock_open()) | 168 @mock.patch('__builtin__.open', mock.mock_open()) |
| 151 @mock.patch('shutil.rmtree') | 169 @mock.patch('shutil.rmtree') |
| 152 @mock.patch('os.makedirs') | 170 @mock.patch('os.makedirs') |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 'author': 'author', | 319 'author': 'author', |
| 302 'message': 'message', | 320 'message': 'message', |
| 303 }) | 321 }) |
| 304 self.assertEqual(counts['sleeps'], 4) | 322 self.assertEqual(counts['sleeps'], 4) |
| 305 requests_get.assert_has_calls([ | 323 requests_get.assert_has_calls([ |
| 306 mock.call('repo/+/revision?format=JSON'), | 324 mock.call('repo/+/revision?format=JSON'), |
| 307 ] * 5) | 325 ] * 5) |
| 308 | 326 |
| 309 if __name__ == '__main__': | 327 if __name__ == '__main__': |
| 310 unittest.main() | 328 unittest.main() |
| OLD | NEW |