OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Unit tests for git_cl.py.""" | 6 """Unit tests for git_cl.py.""" |
7 | 7 |
8 import os | 8 import os |
9 import StringIO | 9 import StringIO |
10 import stat | 10 import stat |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 expected_args, result = self.calls.pop(0) | 86 expected_args, result = self.calls.pop(0) |
87 self.assertEquals( | 87 self.assertEquals( |
88 expected_args, | 88 expected_args, |
89 args, | 89 args, |
90 '@%d Expected: %r Actual: %r' % ( | 90 '@%d Expected: %r Actual: %r' % ( |
91 self._calls_done, expected_args, args)) | 91 self._calls_done, expected_args, args)) |
92 self._calls_done += 1 | 92 self._calls_done += 1 |
93 return result | 93 return result |
94 | 94 |
95 @classmethod | 95 @classmethod |
96 def _upload_calls(cls): | 96 def _upload_calls(cls, similarity): |
97 return cls._git_base_calls() + cls._git_upload_calls() | 97 return cls._git_base_calls(similarity) + cls._git_upload_calls() |
98 | 98 |
99 @staticmethod | 99 @staticmethod |
100 def _git_base_calls(): | 100 def _git_base_calls(similarity): |
| 101 if similarity is None: |
| 102 similarity = '50' |
| 103 similarity_call = ((['git', 'config', '--int', '--get', |
| 104 'branch.master.git-cl-similarity'],), '') |
| 105 else: |
| 106 similarity_call = ((['git', 'config', '--int', |
| 107 'branch.master.git-cl-similarity', similarity],), '') |
101 return [ | 108 return [ |
102 ((['git', 'config', 'gerrit.host'],), ''), | 109 ((['git', 'config', 'gerrit.host'],), ''), |
| 110 ((['git', 'config', 'rietveld.server'],), 'codereview.example.com'), |
| 111 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), |
| 112 similarity_call, |
103 ((['git', 'update-index', '--refresh', '-q'],), ''), | 113 ((['git', 'update-index', '--refresh', '-q'],), ''), |
104 ((['git', 'diff-index', 'HEAD'],), ''), | 114 ((['git', 'diff-index', 'HEAD'],), ''), |
105 ((['git', 'config', 'rietveld.server'],), 'codereview.example.com'), | |
106 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), | 115 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), |
107 ((['git', 'config', 'branch.master.merge'],), 'master'), | 116 ((['git', 'config', 'branch.master.merge'],), 'master'), |
108 ((['git', 'config', 'branch.master.remote'],), 'origin'), | 117 ((['git', 'config', 'branch.master.remote'],), 'origin'), |
109 ((['git', 'rev-parse', '--show-cdup'],), ''), | 118 ((['git', 'rev-parse', '--show-cdup'],), ''), |
110 ((['git', 'rev-parse', 'HEAD'],), '12345'), | 119 ((['git', 'rev-parse', 'HEAD'],), '12345'), |
111 ((['git', 'diff', '--name-status', '-r', 'master...', '.'],), | 120 ((['git', 'diff', '--name-status', '-r', 'master...', '.'],), |
112 'M\t.gitignore\n'), | 121 'M\t.gitignore\n'), |
113 ((['git', 'config', 'branch.master.rietveldissue'],), ''), | 122 ((['git', 'config', 'branch.master.rietveldissue'],), ''), |
114 ((['git', 'config', 'branch.master.rietveldpatchset'],), ''), | 123 ((['git', 'config', 'branch.master.rietveldpatchset'],), ''), |
115 ((['git', 'log', '--pretty=format:%s%n%n%b', 'master...'],), 'foo'), | 124 ((['git', 'log', '--pretty=format:%s%n%n%b', 'master...'],), 'foo'), |
116 ((['git', 'config', 'user.email'],), 'me@example.com'), | 125 ((['git', 'config', 'user.email'],), 'me@example.com'), |
117 ((['git', 'diff', '--no-ext-diff', '--stat', '--find-copies-harder', | 126 ((['git', 'diff', '--no-ext-diff', '--stat', '--find-copies-harder', |
118 '-l100000', 'master...'],), | 127 '-C'+similarity, '-l100000', 'master...'],), |
119 '+dat'), | 128 '+dat'), |
120 ((['git', 'log', '--pretty=format:%s\n\n%b', 'master..'],), 'desc\n'), | 129 ((['git', 'log', '--pretty=format:%s\n\n%b', 'master..'],), 'desc\n'), |
121 ] | 130 ] |
122 | 131 |
123 @staticmethod | 132 @staticmethod |
124 def _git_upload_calls(): | 133 def _git_upload_calls(): |
125 return [ | 134 return [ |
126 ((['git', 'config', 'rietveld.cc'],), ''), | 135 ((['git', 'config', 'rietveld.cc'],), ''), |
127 ((['git', 'config', 'branch.master.base-url'],), ''), | 136 ((['git', 'config', 'branch.master.base-url'],), ''), |
128 ((['git', 'config', '--get-regexp', '^svn-remote\\.'],), | 137 ((['git', 'config', '--get-regexp', '^svn-remote\\.'],), |
129 (('', None), 0)), | 138 (('', None), 0)), |
130 ((['git', 'rev-parse', '--show-cdup'],), ''), | 139 ((['git', 'rev-parse', '--show-cdup'],), ''), |
131 ((['git', 'svn', 'info'],), ''), | 140 ((['git', 'svn', 'info'],), ''), |
132 ((['git', 'config', 'branch.master.rietveldissue', '1'],), ''), | 141 ((['git', 'config', 'branch.master.rietveldissue', '1'],), ''), |
133 ((['git', 'config', 'branch.master.rietveldserver', | 142 ((['git', 'config', 'branch.master.rietveldserver', |
134 'https://codereview.example.com'],), ''), | 143 'https://codereview.example.com'],), ''), |
135 ((['git', 'config', 'branch.master.rietveldpatchset', '2'],), ''), | 144 ((['git', 'config', 'branch.master.rietveldpatchset', '2'],), ''), |
136 ] | 145 ] |
137 | 146 |
138 @classmethod | 147 @classmethod |
139 def _dcommit_calls_1(cls): | 148 def _dcommit_calls_1(cls): |
140 return [ | 149 return [ |
141 ((['git', 'config', '--get-regexp', '^svn-remote\\.'],), | 150 ((['git', 'config', '--get-regexp', '^svn-remote\\.'],), |
142 ((('svn-remote.svn.url svn://svn.chromium.org/chrome\n' | 151 ((('svn-remote.svn.url svn://svn.chromium.org/chrome\n' |
143 'svn-remote.svn.fetch trunk/src:refs/remotes/origin/master'), | 152 'svn-remote.svn.fetch trunk/src:refs/remotes/origin/master'), |
144 None), | 153 None), |
145 0)), | 154 0)), |
146 ((['git', 'config', 'rietveld.server'],), 'codereview.example.com'), | 155 ((['git', 'config', 'rietveld.server'],), 'codereview.example.com'), |
147 ((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'), | 156 ((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'), |
| 157 ((['git', 'config', '--int', '--get', |
| 158 'branch.working.git-cl-similarity'],), ''), |
| 159 ((['git', 'symbolic-ref', 'HEAD'],), 'refs/heads/working'), |
148 ((['git', 'config', 'branch.working.merge'],), 'refs/heads/master'), | 160 ((['git', 'config', 'branch.working.merge'],), 'refs/heads/master'), |
149 ((['git', 'config', 'branch.working.remote'],), 'origin'), | 161 ((['git', 'config', 'branch.working.remote'],), 'origin'), |
150 ((['git', 'rev-list', '--merges', | 162 ((['git', 'rev-list', '--merges', |
151 '--grep=^SVN changes up to revision [0-9]*$', | 163 '--grep=^SVN changes up to revision [0-9]*$', |
152 'refs/remotes/origin/master^!'],), ''), | 164 'refs/remotes/origin/master^!'],), ''), |
153 ((['git', 'update-index', '--refresh', '-q'],), ''), | 165 ((['git', 'update-index', '--refresh', '-q'],), ''), |
154 ((['git', 'diff-index', 'HEAD'],), ''), | 166 ((['git', 'diff-index', 'HEAD'],), ''), |
155 ((['git', 'rev-list', '^refs/heads/working', | 167 ((['git', 'rev-list', '^refs/heads/working', |
156 'refs/remotes/origin/master'],), | 168 'refs/remotes/origin/master'],), |
157 ''), | 169 ''), |
(...skipping 28 matching lines...) Expand all Loading... |
186 'codereview.example.com'), | 198 'codereview.example.com'), |
187 (('GitClHooksBypassedCommit', | 199 (('GitClHooksBypassedCommit', |
188 'Issue https://codereview.example.com/12345 bypassed hook when ' | 200 'Issue https://codereview.example.com/12345 bypassed hook when ' |
189 'committing'), None), | 201 'committing'), None), |
190 ] | 202 ] |
191 | 203 |
192 @classmethod | 204 @classmethod |
193 def _dcommit_calls_3(cls): | 205 def _dcommit_calls_3(cls): |
194 return [ | 206 return [ |
195 ((['git', 'diff', '--no-ext-diff', '--stat', '--find-copies-harder', | 207 ((['git', 'diff', '--no-ext-diff', '--stat', '--find-copies-harder', |
196 '-l100000', 'refs/remotes/origin/master', 'refs/heads/working'],), | 208 '-C50', '-l100000', 'refs/remotes/origin/master', |
| 209 'refs/heads/working'],), |
197 (' PRESUBMIT.py | 2 +-\n' | 210 (' PRESUBMIT.py | 2 +-\n' |
198 ' 1 files changed, 1 insertions(+), 1 deletions(-)\n')), | 211 ' 1 files changed, 1 insertions(+), 1 deletions(-)\n')), |
199 (('About to commit; enter to confirm.',), None), | 212 (('About to commit; enter to confirm.',), None), |
200 ((['git', 'show-ref', '--quiet', '--verify', | 213 ((['git', 'show-ref', '--quiet', '--verify', |
201 'refs/heads/git-cl-commit'],), | 214 'refs/heads/git-cl-commit'],), |
202 (('', None), 0)), | 215 (('', None), 0)), |
203 ((['git', 'branch', '-D', 'git-cl-commit'],), ''), | 216 ((['git', 'branch', '-D', 'git-cl-commit'],), ''), |
204 ((['git', 'show-ref', '--quiet', '--verify', | 217 ((['git', 'show-ref', '--quiet', '--verify', |
205 'refs/heads/git-cl-cherry-pick'],), ''), | 218 'refs/heads/git-cl-cherry-pick'],), ''), |
206 ((['git', 'rev-parse', '--show-cdup'],), '\n'), | 219 ((['git', 'rev-parse', '--show-cdup'],), '\n'), |
207 ((['git', 'checkout', '-q', '-b', 'git-cl-commit'],), ''), | 220 ((['git', 'checkout', '-q', '-b', 'git-cl-commit'],), ''), |
208 ((['git', 'reset', '--soft', 'refs/remotes/origin/master'],), ''), | 221 ((['git', 'reset', '--soft', 'refs/remotes/origin/master'],), ''), |
209 ((['git', 'commit', '-m', | 222 ((['git', 'commit', '-m', |
210 'Issue: 12345\n\nReview URL: https://codereview.example.com/12345'],), | 223 'Issue: 12345\n\nReview URL: https://codereview.example.com/12345'],), |
211 ''), | 224 ''), |
212 ((['git', 'svn', 'dcommit', '--no-rebase', '--rmdir'],), (('', None), 0)), | 225 ((['git', 'svn', 'dcommit', '-C50', '--no-rebase', '--rmdir'],), |
| 226 (('', None), 0)), |
213 ((['git', 'checkout', '-q', 'working'],), ''), | 227 ((['git', 'checkout', '-q', 'working'],), ''), |
214 ((['git', 'branch', '-D', 'git-cl-commit'],), ''), | 228 ((['git', 'branch', '-D', 'git-cl-commit'],), ''), |
215 ] | 229 ] |
216 | 230 |
217 @staticmethod | 231 @staticmethod |
218 def _cmd_line(description, args): | 232 def _cmd_line(description, args, similarity): |
219 """Returns the upload command line passed to upload.RealMain().""" | 233 """Returns the upload command line passed to upload.RealMain().""" |
220 return [ | 234 return [ |
221 'upload', '--assume_yes', '--server', | 235 'upload', '--assume_yes', '--server', |
222 'https://codereview.example.com', | 236 'https://codereview.example.com', |
223 '--message', description | 237 '--message', description |
224 ] + args + [ | 238 ] + args + [ |
225 '--cc', 'joe@example.com', | 239 '--cc', 'joe@example.com', |
| 240 '--git_similarity', similarity or '50', |
226 'master...' | 241 'master...' |
227 ] | 242 ] |
228 | 243 |
229 def _run_reviewer_test( | 244 def _run_reviewer_test( |
230 self, | 245 self, |
231 upload_args, | 246 upload_args, |
232 expected_description, | 247 expected_description, |
233 returned_description, | 248 returned_description, |
234 final_description, | 249 final_description, |
235 reviewers): | 250 reviewers): |
236 """Generic reviewer test framework.""" | 251 """Generic reviewer test framework.""" |
237 self.calls = self._upload_calls() | 252 try: |
| 253 similarity = upload_args[upload_args.index('--similarity')+1] |
| 254 except ValueError: |
| 255 similarity = None |
| 256 self.calls = self._upload_calls(similarity) |
238 def RunEditor(desc, _): | 257 def RunEditor(desc, _): |
239 self.assertEquals( | 258 self.assertEquals( |
240 '# Enter a description of the change.\n' | 259 '# Enter a description of the change.\n' |
241 '# This will displayed on the codereview site.\n' | 260 '# This will displayed on the codereview site.\n' |
242 '# The first line will also be used as the subject of the review.\n' + | 261 '# The first line will also be used as the subject of the review.\n' + |
243 expected_description, | 262 expected_description, |
244 desc) | 263 desc) |
245 return returned_description | 264 return returned_description |
246 self.mock(git_cl.gclient_utils, 'RunEditor', RunEditor) | 265 self.mock(git_cl.gclient_utils, 'RunEditor', RunEditor) |
247 def check_upload(args): | 266 def check_upload(args): |
248 self.assertEquals(self._cmd_line(final_description, reviewers), args) | 267 cmd_line = self._cmd_line(final_description, reviewers, similarity) |
| 268 self.assertEquals(cmd_line, args) |
249 return 1, 2 | 269 return 1, 2 |
250 self.mock(git_cl.upload, 'RealMain', check_upload) | 270 self.mock(git_cl.upload, 'RealMain', check_upload) |
251 git_cl.main(['upload'] + upload_args) | 271 git_cl.main(['upload'] + upload_args) |
252 | 272 |
253 def test_no_reviewer(self): | 273 def test_no_reviewer(self): |
254 self._run_reviewer_test( | 274 self._run_reviewer_test( |
255 [], | 275 [], |
256 'desc\n\nBUG=\n', | 276 'desc\n\nBUG=\n', |
257 '# Blah blah comment.\ndesc\n\nBUG=\n', | 277 '# Blah blah comment.\ndesc\n\nBUG=\n', |
258 'desc\n\nBUG=\n', | 278 'desc\n\nBUG=\n', |
259 []) | 279 []) |
260 | 280 |
| 281 def test_keep_similarity(self): |
| 282 self._run_reviewer_test( |
| 283 ['--similarity', '70'], |
| 284 'desc\n\nBUG=\n', |
| 285 '# Blah blah comment.\ndesc\n\nBUG=\n', |
| 286 'desc\n\nBUG=\n', |
| 287 []) |
| 288 |
261 def test_reviewers_cmd_line(self): | 289 def test_reviewers_cmd_line(self): |
262 # Reviewer is passed as-is | 290 # Reviewer is passed as-is |
263 description = 'desc\n\nR=foo@example.com\nBUG=\n' | 291 description = 'desc\n\nR=foo@example.com\nBUG=\n' |
264 self._run_reviewer_test( | 292 self._run_reviewer_test( |
265 ['-r' 'foo@example.com'], | 293 ['-r' 'foo@example.com'], |
266 description, | 294 description, |
267 '\n%s\n' % description, | 295 '\n%s\n' % description, |
268 description, | 296 description, |
269 ['--reviewers', 'foo@example.com']) | 297 ['--reviewers', 'foo@example.com']) |
270 | 298 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 | 330 |
303 def test_reviewer_send_mail_no_rev(self): | 331 def test_reviewer_send_mail_no_rev(self): |
304 # Fails without a reviewer. | 332 # Fails without a reviewer. |
305 class FileMock(object): | 333 class FileMock(object): |
306 buf = StringIO.StringIO() | 334 buf = StringIO.StringIO() |
307 def write(self, content): | 335 def write(self, content): |
308 self.buf.write(content) | 336 self.buf.write(content) |
309 | 337 |
310 mock = FileMock() | 338 mock = FileMock() |
311 try: | 339 try: |
312 self.calls = self._git_base_calls() | 340 self.calls = self._git_base_calls(None) |
313 def RunEditor(desc, _): | 341 def RunEditor(desc, _): |
314 return desc | 342 return desc |
315 self.mock(git_cl.gclient_utils, 'RunEditor', RunEditor) | 343 self.mock(git_cl.gclient_utils, 'RunEditor', RunEditor) |
316 self.mock(sys, 'stderr', mock) | 344 self.mock(sys, 'stderr', mock) |
317 git_cl.main(['upload', '--send-mail']) | 345 git_cl.main(['upload', '--send-mail']) |
318 self.fail() | 346 self.fail() |
319 except SystemExit: | 347 except SystemExit: |
320 self.assertEquals( | 348 self.assertEquals( |
321 'Must specify reviewers to send email.\n', mock.buf.getvalue()) | 349 'Must specify reviewers to send email.\n', mock.buf.getvalue()) |
322 | 350 |
323 def test_dcommit(self): | 351 def test_dcommit(self): |
324 self.calls = ( | 352 self.calls = ( |
325 self._dcommit_calls_1() + | 353 self._dcommit_calls_1() + |
326 self._dcommit_calls_normal() + | 354 self._dcommit_calls_normal() + |
327 self._dcommit_calls_3()) | 355 self._dcommit_calls_3()) |
328 git_cl.main(['dcommit']) | 356 git_cl.main(['dcommit']) |
329 | 357 |
330 def test_dcommit_bypass_hooks(self): | 358 def test_dcommit_bypass_hooks(self): |
331 self.calls = ( | 359 self.calls = ( |
332 self._dcommit_calls_1() + | 360 self._dcommit_calls_1() + |
333 self._dcommit_calls_bypassed() + | 361 self._dcommit_calls_bypassed() + |
334 self._dcommit_calls_3()) | 362 self._dcommit_calls_3()) |
335 git_cl.main(['dcommit', '--bypass-hooks']) | 363 git_cl.main(['dcommit', '--bypass-hooks']) |
336 | 364 |
337 | 365 |
338 @staticmethod | 366 @staticmethod |
339 def _gerrit_base_calls(): | 367 def _gerrit_base_calls(): |
340 return [ | 368 return [ |
341 ((['git', 'config', 'gerrit.host'],), 'gerrit.example.com'), | 369 ((['git', 'config', 'gerrit.host'],), 'gerrit.example.com'), |
| 370 ((['git', 'config', 'rietveld.server'],), 'codereview.example.com'), |
| 371 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), |
| 372 ((['git', 'config', '--int', '--get', |
| 373 'branch.master.git-cl-similarity'],), ''), |
342 ((['git', 'update-index', '--refresh', '-q'],), ''), | 374 ((['git', 'update-index', '--refresh', '-q'],), ''), |
343 ((['git', 'diff-index', 'HEAD'],), ''), | 375 ((['git', 'diff-index', 'HEAD'],), ''), |
344 ((['git', 'config', 'rietveld.server'],), 'codereview.example.com'), | |
345 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), | 376 ((['git', 'symbolic-ref', 'HEAD'],), 'master'), |
346 ((['git', 'config', 'branch.master.merge'],), 'master'), | 377 ((['git', 'config', 'branch.master.merge'],), 'master'), |
347 ((['git', 'config', 'branch.master.remote'],), 'origin'), | 378 ((['git', 'config', 'branch.master.remote'],), 'origin'), |
348 ((['git', 'rev-parse', '--show-cdup'],), ''), | 379 ((['git', 'rev-parse', '--show-cdup'],), ''), |
349 ((['git', 'rev-parse', 'HEAD'],), '12345'), | 380 ((['git', 'rev-parse', 'HEAD'],), '12345'), |
350 ((['git', 'diff', '--name-status', '-r', 'master...', '.'],), | 381 ((['git', 'diff', '--name-status', '-r', 'master...', '.'],), |
351 'M\t.gitignore\n'), | 382 'M\t.gitignore\n'), |
352 ((['git', 'config', 'branch.master.rietveldissue'],), ''), | 383 ((['git', 'config', 'branch.master.rietveldissue'],), ''), |
353 ((['git', 'config', 'branch.master.rietveldpatchset'],), ''), | 384 ((['git', 'config', 'branch.master.rietveldpatchset'],), ''), |
354 ((['git', 'log', '--pretty=format:%s%n%n%b', 'master...'],), 'foo'), | 385 ((['git', 'log', '--pretty=format:%s%n%n%b', 'master...'],), 'foo'), |
355 ((['git', 'config', 'user.email'],), 'me@example.com'), | 386 ((['git', 'config', 'user.email'],), 'me@example.com'), |
356 ((['git', 'diff', '--no-ext-diff', '--stat', '--find-copies-harder', | 387 ((['git', 'diff', '--no-ext-diff', '--stat', '--find-copies-harder', |
357 '-l100000', 'master...'],), | 388 '-C50', '-l100000', 'master...'],), |
358 '+dat'), | 389 '+dat'), |
359 ] | 390 ] |
360 | 391 |
361 @staticmethod | 392 @staticmethod |
362 def _gerrit_upload_calls(description, reviewers): | 393 def _gerrit_upload_calls(description, reviewers): |
363 calls = [ | 394 calls = [ |
364 ((['git', 'log', '--pretty=format:%s\n\n%b', 'master..'],), | 395 ((['git', 'log', '--pretty=format:%s\n\n%b', 'master..'],), |
365 description), | 396 description), |
366 ((['git', 'config', 'rietveld.cc'],), '') | 397 ((['git', 'config', 'rietveld.cc'],), '') |
367 ] | 398 ] |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 ((['git', 'config', 'rietveld.viewvc-url'],), ''), | 489 ((['git', 'config', 'rietveld.viewvc-url'],), ''), |
459 (('ViewVC URL:',), ''), | 490 (('ViewVC URL:',), ''), |
460 # DownloadHooks(True) | 491 # DownloadHooks(True) |
461 ((commit_msg_path, os.X_OK,), True), | 492 ((commit_msg_path, os.X_OK,), True), |
462 ] | 493 ] |
463 git_cl.main(['config']) | 494 git_cl.main(['config']) |
464 | 495 |
465 | 496 |
466 if __name__ == '__main__': | 497 if __name__ == '__main__': |
467 unittest.main() | 498 unittest.main() |
OLD | NEW |