git_squash_branch_test.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #!/usr/bin/env vpython3
  2. # coding=utf-8
  3. # Copyright 2024 The Chromium Authors. All rights reserved.
  4. # Use of this source code is governed by a BSD-style license that can be
  5. # found in the LICENSE file.
  6. """Tests for git_squash_branch."""
  7. import os
  8. import sys
  9. import unittest
  10. DEPOT_TOOLS_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  11. sys.path.insert(0, DEPOT_TOOLS_ROOT)
  12. from testing_support import git_test_utils
  13. import git_squash_branch
  14. import git_common
  15. git_common.TEST_MODE = True
  16. class GitSquashBranchTest(git_test_utils.GitRepoReadWriteTestBase):
  17. # Empty repo.
  18. REPO_SCHEMA = """
  19. """
  20. def setUp(self):
  21. super(GitSquashBranchTest, self).setUp()
  22. # Note: Using the REPO_SCHEMA wouldn't simplify this test so it is not
  23. # used.
  24. #
  25. # Create a repo with the follow schema
  26. #
  27. # main <- branchA <- branchB <- branchC
  28. # ^
  29. # \ branchD
  30. #
  31. # where each branch has 2 commits.
  32. # The repo is empty. Add the first commit or else most commands don't
  33. # work, including `git branch`, which doesn't even show the main branch.
  34. self.repo.git('commit', '-m', 'First commit', '--allow-empty')
  35. # Create the first branch downstream from `main` with 2 commits.
  36. self.repo.git('checkout', '-B', 'branchA', '--track', 'main')
  37. self._createFileAndCommit('fileA1')
  38. self._createFileAndCommit('fileA2')
  39. # Create a branch downstream from `branchA` with 2 commits.
  40. self.repo.git('checkout', '-B', 'branchB', '--track', 'branchA')
  41. self._createFileAndCommit('fileB1')
  42. self._createFileAndCommit('fileB2')
  43. # Create another branch downstream from `branchB` with 2 commits.
  44. self.repo.git('checkout', '-B', 'branchC', '--track', 'branchB')
  45. self._createFileAndCommit('fileC1')
  46. self._createFileAndCommit('fileC2')
  47. # Create another branch downstream from `branchA` with 2 commits.
  48. self.repo.git('checkout', '-B', 'branchD', '--track', 'branchA')
  49. self._createFileAndCommit('fileD1')
  50. self._createFileAndCommit('fileD2')
  51. def testGitSquashBranchFailsWithDivergedBranch(self):
  52. self.assertEqual(self._getCountAheadOfUpstream('branchA'), 2)
  53. self.assertEqual(self._getCountAheadOfUpstream('branchB'), 2)
  54. self.assertEqual(self._getCountAheadOfUpstream('branchC'), 2)
  55. self.assertEqual(self._getCountAheadOfUpstream('branchD'), 2)
  56. self.repo.git('checkout', 'branchB')
  57. self._createFileAndCommit('fileB3')
  58. self.repo.git('checkout', 'branchA')
  59. # We have now made a state where branchC has diverged from branchB.
  60. output, _ = self.repo.capture_stdio(git_squash_branch.main, [])
  61. self.assertIn('some children have diverged', output)
  62. def testGitSquashBranchRootOnly(self):
  63. self.assertEqual(self._getCountAheadOfUpstream('branchA'), 2)
  64. self.assertEqual(self._getCountAheadOfUpstream('branchB'), 2)
  65. self.assertEqual(self._getCountAheadOfUpstream('branchC'), 2)
  66. self.assertEqual(self._getCountAheadOfUpstream('branchD'), 2)
  67. self.repo.git('checkout', 'branchA')
  68. self.repo.run(git_squash_branch.main, [])
  69. self.assertEqual(self._getCountAheadOfUpstream('branchA'), 1)
  70. self.assertEqual(self._getCountAheadOfUpstream('branchB'), 2)
  71. self.assertEqual(self._getCountAheadOfUpstream('branchC'), 2)
  72. self.assertEqual(self._getCountAheadOfUpstream('branchD'), 2)
  73. def testGitSquashBranchLeaf(self):
  74. self.assertEqual(self._getCountAheadOfUpstream('branchA'), 2)
  75. self.assertEqual(self._getCountAheadOfUpstream('branchB'), 2)
  76. self.assertEqual(self._getCountAheadOfUpstream('branchC'), 2)
  77. self.assertEqual(self._getCountAheadOfUpstream('branchD'), 2)
  78. self.repo.git('checkout', 'branchD')
  79. self.repo.run(git_squash_branch.main, [])
  80. self.assertEqual(self._getCountAheadOfUpstream('branchA'), 2)
  81. self.assertEqual(self._getCountAheadOfUpstream('branchB'), 2)
  82. self.assertEqual(self._getCountAheadOfUpstream('branchC'), 2)
  83. self.assertEqual(self._getCountAheadOfUpstream('branchD'), 1)
  84. def testGitSquashBranchSequential(self):
  85. self.assertEqual(self._getCountAheadOfUpstream('branchA'), 2)
  86. self.assertEqual(self._getCountAheadOfUpstream('branchB'), 2)
  87. self.assertEqual(self._getCountAheadOfUpstream('branchC'), 2)
  88. self.assertEqual(self._getCountAheadOfUpstream('branchD'), 2)
  89. self.repo.git('checkout', 'branchA')
  90. self.repo.run(git_squash_branch.main, [])
  91. self.assertEqual(self._getCountAheadOfUpstream('branchA'), 1)
  92. self.assertEqual(self._getCountAheadOfUpstream('branchB'), 2)
  93. self.assertEqual(self._getCountAheadOfUpstream('branchC'), 2)
  94. self.assertEqual(self._getCountAheadOfUpstream('branchD'), 2)
  95. self.repo.git('checkout', 'branchB')
  96. self.repo.run(git_squash_branch.main, [])
  97. self.assertEqual(self._getCountAheadOfUpstream('branchA'), 1)
  98. self.assertEqual(self._getCountAheadOfUpstream('branchB'), 1)
  99. self.assertEqual(self._getCountAheadOfUpstream('branchC'), 2)
  100. self.assertEqual(self._getCountAheadOfUpstream('branchD'), 2)
  101. # Creates a file with arbitrary contents and commit it to the current
  102. # branch.
  103. def _createFileAndCommit(self, filename):
  104. with self.repo.open(filename, 'w') as f:
  105. f.write('content')
  106. self.repo.git('add', filename)
  107. self.repo.git_commit('Added file ' + filename)
  108. # Returns the count of how many commits `branch` is ahead of its upstream.
  109. def _getCountAheadOfUpstream(self, branch):
  110. upstream = branch + '@{u}'
  111. output = self.repo.git('rev-list', '--count',
  112. upstream + '..' + branch).stdout
  113. return int(output)
  114. if __name__ == '__main__':
  115. unittest.main()