Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1586)

Side by Side Diff: tests/git_hyper_blame_test.py

Issue 1629253002: git hyper-blame: Added approx. line number translation. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@git-hyper-blame
Patch Set: Added Caveats section to man page. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tests/git_common_test.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2016 The Chromium Authors. All rights reserved. 2 # Copyright 2016 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 """Tests for git_dates.""" 5 """Tests for git_dates."""
6 6
7 import datetime 7 import datetime
8 import os 8 import os
9 import shutil 9 import shutil
10 import StringIO 10 import StringIO
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 def testIgnoreFilePopulate(self): 272 def testIgnoreFilePopulate(self):
273 """Tests a blame ignoring the commit that added data to an empty file.""" 273 """Tests a blame ignoring the commit that added data to an empty file."""
274 # Ignore A. Expect A to get blamed anyway. 274 # Ignore A. Expect A to get blamed anyway.
275 expected_output = [self.blame_line('B', '1) not anymore')] 275 expected_output = [self.blame_line('B', '1) not anymore')]
276 retval, output = self.run_hyperblame(['B'], 'some/files/empty', 'tag_B') 276 retval, output = self.run_hyperblame(['B'], 'some/files/empty', 'tag_B')
277 self.assertEqual(0, retval) 277 self.assertEqual(0, retval)
278 self.assertEqual(expected_output, output) 278 self.assertEqual(expected_output, output)
279 279
280 class GitHyperBlameLineMotionTest(GitHyperBlameTestBase): 280 class GitHyperBlameLineMotionTest(GitHyperBlameTestBase):
281 REPO_SCHEMA = """ 281 REPO_SCHEMA = """
282 A B C D E 282 A B C D E F
283 """ 283 """
284 284
285 COMMIT_A = { 285 COMMIT_A = {
286 'file': {'data': 'A\ngreen\nblue\n'}, 286 'file': {'data': 'A\ngreen\nblue\n'},
287 } 287 }
288 288
289 # Change "green" to "yellow". 289 # Change "green" to "yellow".
290 COMMIT_B = { 290 COMMIT_B = {
291 'file': {'data': 'A\nyellow\nblue\n'}, 291 'file': {'data': 'A\nyellow\nblue\n'},
292 } 292 }
293 293
294 # Insert 2 lines at the top, 294 # Insert 2 lines at the top,
295 # Change "yellow" to "red". 295 # Change "yellow" to "red".
296 # Insert 1 line at the bottom.
296 COMMIT_C = { 297 COMMIT_C = {
297 'file': {'data': 'X\nY\nA\nred\nblue\n'}, 298 'file': {'data': 'X\nY\nA\nred\nblue\nZ\n'},
298 } 299 }
299 300
300 # Insert 2 more lines at the top. 301 # Insert 2 more lines at the top.
301 COMMIT_D = { 302 COMMIT_D = {
302 'file': {'data': 'earth\nfire\nX\nY\nA\nred\nblue\n'}, 303 'file': {'data': 'earth\nfire\nX\nY\nA\nred\nblue\nZ\n'},
303 } 304 }
304 305
305 # Insert a line before "red", and indent "red" and "blue". 306 # Insert a line before "red", and indent "red" and "blue".
306 COMMIT_E = { 307 COMMIT_E = {
307 'file': {'data': 'earth\nfire\nX\nY\nA\ncolors:\n red\n blue\n'}, 308 'file': {'data': 'earth\nfire\nX\nY\nA\ncolors:\n red\n blue\nZ\n'},
308 } 309 }
309 310
311 # Insert a line between "A" and "colors".
312 COMMIT_F = {
313 'file': {'data': 'earth\nfire\nX\nY\nA\nB\ncolors:\n red\n blue\nZ\n'},
314 }
315
316 def testCacheDiffHunks(self):
317 """Tests the cache_diff_hunks internal function."""
318 expected_hunks = [((0, 0), (1, 2)),
319 ((2, 1), (4, 1)),
320 ((3, 0), (6, 1)),
321 ]
322 hunks = self.repo.run(self.git_hyper_blame.cache_diff_hunks, 'tag_B',
323 'tag_C')
324 self.assertEqual(expected_hunks, hunks)
325
326 def testApproxLinenoAcrossRevs(self):
327 """Tests the approx_lineno_across_revs internal function."""
328 # Note: For all of these tests, the "old revision" and "new revision" are
329 # reversed, which matches the usage by hyper_blame.
330
331 # Test an unchanged line before any hunks in the diff. Should be unchanged.
332 lineno = self.repo.run(self.git_hyper_blame.approx_lineno_across_revs,
333 'file', 'file', 'tag_B', 'tag_A', 1)
334 self.assertEqual(1, lineno)
335
336 # Test an unchanged line after all hunks in the diff. Should be matched to
337 # the line's previous position in the file.
338 lineno = self.repo.run(self.git_hyper_blame.approx_lineno_across_revs,
339 'file', 'file', 'tag_D', 'tag_C', 6)
340 self.assertEqual(4, lineno)
341
342 # Test a line added in a new hunk. Should be matched to the line *before*
343 # where the hunk was inserted in the old version of the file.
344 lineno = self.repo.run(self.git_hyper_blame.approx_lineno_across_revs,
345 'file', 'file', 'tag_F', 'tag_E', 6)
346 self.assertEqual(5, lineno)
347
348 # Test lines added in a new hunk at the very start of the file. This tests
349 # an edge case: normally it would be matched to the line *before* where the
350 # hunk was inserted (Line 0), but since the hunk is at the start of the
351 # file, we match to Line 1.
352 lineno = self.repo.run(self.git_hyper_blame.approx_lineno_across_revs,
353 'file', 'file', 'tag_C', 'tag_B', 1)
354 self.assertEqual(1, lineno)
355 lineno = self.repo.run(self.git_hyper_blame.approx_lineno_across_revs,
356 'file', 'file', 'tag_C', 'tag_B', 2)
357 self.assertEqual(1, lineno)
358
359 # Test an unchanged line in between hunks in the diff. Should be matched to
360 # the line's previous position in the file.
361 lineno = self.repo.run(self.git_hyper_blame.approx_lineno_across_revs,
362 'file', 'file', 'tag_C', 'tag_B', 3)
363 self.assertEqual(1, lineno)
364
365 # Test a changed line. Should be matched to the hunk's previous position in
366 # the file.
367 lineno = self.repo.run(self.git_hyper_blame.approx_lineno_across_revs,
368 'file', 'file', 'tag_C', 'tag_B', 4)
369 self.assertEqual(2, lineno)
370
371 # Test a line added in a new hunk at the very end of the file. Should be
372 # matched to the line *before* where the hunk was inserted (the last line of
373 # the file). Technically same as the case above but good to boundary test.
374 lineno = self.repo.run(self.git_hyper_blame.approx_lineno_across_revs,
375 'file', 'file', 'tag_C', 'tag_B', 6)
376 self.assertEqual(3, lineno)
377
310 def testInterHunkLineMotion(self): 378 def testInterHunkLineMotion(self):
311 """Tests a blame with line motion in another hunk in the ignored commit.""" 379 """Tests a blame with line motion in another hunk in the ignored commit."""
312 # This test was mostly written as a demonstration of the limitations of the 380 # Blame from D, ignoring C.
313 # current algorithm (it exhibits non-ideal behaviour).
314 381
315 # Blame from D, ignoring C.
316 # Lines 1, 2 were added by D. 382 # Lines 1, 2 were added by D.
317 # Lines 3, 4 were added by C (but ignored, so blame A, B, respectively). 383 # Lines 3, 4 were added by C (but ignored, so blame A).
318 # TODO(mgiuca): Ideally, this would blame both of these lines on A, because
319 # they add lines nowhere near the changes made by B.
320 # Line 5 was added by A. 384 # Line 5 was added by A.
321 # Line 6 was modified by C (but ignored, so blame A). 385 # Line 6 was modified by C (but ignored, so blame B). (Note: This requires
322 # TODO(mgiuca): Ideally, Line 6 would be blamed on B, because that was the 386 # the algorithm to figure out that Line 6 in D == Line 4 in C ~= Line 2 in
323 # last commit to touch that line (changing "green" to "yellow"), but the 387 # B, so it blames B. Otherwise, it would blame A.)
324 # algorithm isn't yet able to figure out that Line 6 in D == Line 4 in C ~=
325 # Line 2 in B.
326 # Line 7 was added by A. 388 # Line 7 was added by A.
389 # Line 8 was added by C (but ignored, so blame A).
327 expected_output = [self.blame_line('D', ' 1) earth'), 390 expected_output = [self.blame_line('D', ' 1) earth'),
328 self.blame_line('D', ' 2) fire'), 391 self.blame_line('D', ' 2) fire'),
329 self.blame_line('A', '3*) X'), 392 self.blame_line('A', '3*) X'),
330 self.blame_line('B', '4*) Y'), 393 self.blame_line('A', '4*) Y'),
331 self.blame_line('A', ' 5) A'), 394 self.blame_line('A', ' 5) A'),
332 self.blame_line('A', '6*) red'), 395 self.blame_line('B', '6*) red'),
333 self.blame_line('A', ' 7) blue'), 396 self.blame_line('A', ' 7) blue'),
397 self.blame_line('A', '8*) Z'),
334 ] 398 ]
335 retval, output = self.run_hyperblame(['C'], 'file', 'tag_D') 399 retval, output = self.run_hyperblame(['C'], 'file', 'tag_D')
336 self.assertEqual(0, retval) 400 self.assertEqual(0, retval)
337 self.assertEqual(expected_output, output) 401 self.assertEqual(expected_output, output)
338 402
339 def testIntraHunkLineMotion(self): 403 def testIntraHunkLineMotion(self):
340 """Tests a blame with line motion in the same hunk in the ignored commit.""" 404 """Tests a blame with line motion in the same hunk in the ignored commit."""
341 # This test was mostly written as a demonstration of the limitations of the 405 # This test was mostly written as a demonstration of the limitations of the
342 # current algorithm (it exhibits non-ideal behaviour). 406 # current algorithm (it exhibits non-ideal behaviour).
343 407
344 # Blame from E, ignoring E. 408 # Blame from E, ignoring E.
345 # Line 6 was added by E (but ignored, so blame C). 409 # Line 6 was added by E (but ignored, so blame C).
346 # Lines 7, 8 were modified by E (but ignored, so blame A). 410 # Lines 7, 8 were modified by E (but ignored, so blame A).
347 # TODO(mgiuca): Ideally, this would blame Line 7 on C, because the line 411 # TODO(mgiuca): Ideally, this would blame Line 7 on C, because the line
348 # "red" was added by C, and this is just a small change to that line. But 412 # "red" was added by C, and this is just a small change to that line. But
349 # the current algorithm can't deal with line motion within a hunk, so it 413 # the current algorithm can't deal with line motion within a hunk, so it
350 # just assumes Line 7 in E ~= Line 7 in D == Line 3 in A (which was "blue"). 414 # just assumes Line 7 in E ~= Line 7 in D == Line 3 in A (which was "blue").
351 expected_output = [self.blame_line('D', ' 1) earth'), 415 expected_output = [self.blame_line('D', ' 1) earth'),
352 self.blame_line('D', ' 2) fire'), 416 self.blame_line('D', ' 2) fire'),
353 self.blame_line('C', ' 3) X'), 417 self.blame_line('C', ' 3) X'),
354 self.blame_line('C', ' 4) Y'), 418 self.blame_line('C', ' 4) Y'),
355 self.blame_line('A', ' 5) A'), 419 self.blame_line('A', ' 5) A'),
356 self.blame_line('C', '6*) colors:'), 420 self.blame_line('C', '6*) colors:'),
357 self.blame_line('A', '7*) red'), 421 self.blame_line('A', '7*) red'),
358 self.blame_line('A', '8*) blue'), 422 self.blame_line('A', '8*) blue'),
423 self.blame_line('C', ' 9) Z'),
359 ] 424 ]
360 retval, output = self.run_hyperblame(['E'], 'file', 'tag_E') 425 retval, output = self.run_hyperblame(['E'], 'file', 'tag_E')
361 self.assertEqual(0, retval) 426 self.assertEqual(0, retval)
362 self.assertEqual(expected_output, output) 427 self.assertEqual(expected_output, output)
363 428
364 429
365 if __name__ == '__main__': 430 if __name__ == '__main__':
366 sys.exit(coverage_utils.covered_main( 431 sys.exit(coverage_utils.covered_main(
367 os.path.join(DEPOT_TOOLS_ROOT, 'git_hyper_blame.py'))) 432 os.path.join(DEPOT_TOOLS_ROOT, 'git_hyper_blame.py')))
OLDNEW
« no previous file with comments | « tests/git_common_test.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698