1#!/usr/bin/env python 2# Copyright 2015 the V8 project authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import mergeinfo 7import shutil 8import unittest 9 10from collections import namedtuple 11from os import path 12from subprocess import Popen, PIPE, check_call 13 14TEST_CONFIG = { 15 "GIT_REPO": "/tmp/test-v8-search-related-commits", 16} 17 18class TestMergeInfo(unittest.TestCase): 19 20 base_dir = TEST_CONFIG["GIT_REPO"] 21 22 def _execute_git(self, git_args): 23 24 fullCommand = ["git", "-C", self.base_dir] + git_args 25 p = Popen(args=fullCommand, stdin=PIPE, 26 stdout=PIPE, stderr=PIPE) 27 output, err = p.communicate() 28 rc = p.returncode 29 if rc != 0: 30 raise Exception(err) 31 return output 32 33 def _update_origin(self): 34 # Fetch from origin to get/update the origin/main branch 35 self._execute_git(['fetch', 'origin']) 36 37 def setUp(self): 38 if path.exists(self.base_dir): 39 shutil.rmtree(self.base_dir) 40 41 check_call(["git", "init", self.base_dir]) 42 43 # Add fake remote with name 'origin' 44 self._execute_git(['remote', 'add', 'origin', self.base_dir]) 45 46 # Initial commit 47 message = '''Initial commit''' 48 49 self._make_empty_commit(message) 50 51 def tearDown(self): 52 if path.exists(self.base_dir): 53 shutil.rmtree(self.base_dir) 54 55 def _assert_correct_standard_result( 56 self, result, all_commits, hash_of_first_commit): 57 self.assertEqual(len(result), 1, "Main commit not found") 58 self.assertTrue( 59 result.get(hash_of_first_commit), 60 "Main commit is wrong") 61 62 self.assertEqual( 63 len(result[hash_of_first_commit]), 64 1, 65 "Child commit not found") 66 self.assertEqual( 67 all_commits[2], 68 result[hash_of_first_commit][0], 69 "Child commit wrong") 70 71 def _get_commits(self): 72 commits = self._execute_git( 73 ["log", "--format=%H", "--reverse"]).splitlines() 74 return commits 75 76 def _get_branches(self, hash): 77 return mergeinfo.get_branches_for_commit(self.base_dir, hash) 78 79 def _make_empty_commit(self, message): 80 self._execute_git(["commit", "--allow-empty", "-m", message]) 81 self._update_origin() 82 return self._get_commits()[-1] 83 84 def testCanDescribeCommit(self): 85 commits = self._get_commits() 86 hash_of_first_commit = commits[0] 87 88 result = mergeinfo.describe_commit( 89 self.base_dir, 90 hash_of_first_commit).splitlines() 91 92 self.assertEqual( 93 result[0], 94 'commit ' + hash_of_first_commit) 95 96 def testCanDescribeCommitSingleLine(self): 97 commits = self._get_commits() 98 hash_of_first_commit = commits[0] 99 100 result = mergeinfo.describe_commit( 101 self.base_dir, 102 hash_of_first_commit, True).splitlines() 103 104 self.assertEqual( 105 str(result[0]), 106 str(hash_of_first_commit[0:7]) + ' Initial commit') 107 108 def testSearchFollowUpCommits(self): 109 commits = self._get_commits() 110 hash_of_first_commit = commits[0] 111 112 message = 'Follow-up commit of ' + hash_of_first_commit 113 self._make_empty_commit(message) 114 self._make_empty_commit(message) 115 self._make_empty_commit(message) 116 commits = self._get_commits() 117 message = 'Not related commit' 118 self._make_empty_commit(message) 119 120 followups = mergeinfo.get_followup_commits( 121 self.base_dir, 122 hash_of_first_commit) 123 self.assertEqual(set(followups), set(commits[1:])) 124 125 def testSearchMerges(self): 126 self._execute_git(['branch', 'test']) 127 self._execute_git(['checkout', 'main']) 128 message = 'real initial commit' 129 self._make_empty_commit(message) 130 commits = self._get_commits() 131 hash_of_first_commit = commits[0] 132 133 self._execute_git(['checkout', 'test']) 134 message = 'Not related commit' 135 self._make_empty_commit(message) 136 137 # This should be found 138 message = 'Merge ' + hash_of_first_commit 139 hash_of_hit = self._make_empty_commit(message) 140 141 # This should be ignored 142 message = 'Cr-Branched-From: ' + hash_of_first_commit 143 hash_of_ignored = self._make_empty_commit(message) 144 145 self._execute_git(['checkout', 'main']) 146 147 followups = mergeinfo.get_followup_commits( 148 self.base_dir, 149 hash_of_first_commit) 150 151 # Check if follow ups and merges are not overlapping 152 self.assertEqual(len(followups), 0) 153 154 message = 'Follow-up commit of ' + hash_of_first_commit 155 hash_of_followup = self._make_empty_commit(message) 156 157 merges = mergeinfo.get_merge_commits(self.base_dir, hash_of_first_commit) 158 # Check if follow up is ignored 159 self.assertTrue(hash_of_followup not in merges) 160 161 # Check for proper return of merges 162 self.assertTrue(hash_of_hit in merges) 163 self.assertTrue(hash_of_ignored not in merges) 164 165 def testIsLkgr(self): 166 commits = self._get_commits() 167 hash_of_first_commit = commits[0] 168 self._make_empty_commit('This one is the lkgr head') 169 self._execute_git(['branch', 'remotes/origin/lkgr']) 170 hash_of_not_lkgr = self._make_empty_commit('This one is not yet lkgr') 171 172 branches = self._get_branches(hash_of_first_commit); 173 self.assertTrue(mergeinfo.is_lkgr(branches)) 174 branches = self._get_branches(hash_of_not_lkgr); 175 self.assertFalse(mergeinfo.is_lkgr(branches)) 176 177 def testShowFirstCanary(self): 178 commits = self._get_commits() 179 hash_of_first_commit = commits[0] 180 181 branches = self._get_branches(hash_of_first_commit); 182 self.assertEqual(mergeinfo.get_first_canary(branches), 'No Canary coverage') 183 184 self._execute_git(['branch', 'remotes/origin/chromium/2345']) 185 self._execute_git(['branch', 'remotes/origin/chromium/2346']) 186 187 branches = self._get_branches(hash_of_first_commit); 188 self.assertEqual(mergeinfo.get_first_canary(branches), '2345') 189 190 def testFirstV8Version(self): 191 commits = self._get_commits() 192 hash_of_first_commit = commits[0] 193 194 self._execute_git(['branch', 'remotes/origin/chromium/2345']) 195 self._execute_git(['branch', 'remotes/origin/chromium/2346']) 196 branches = self._get_branches(hash_of_first_commit); 197 self.assertEqual(mergeinfo.get_first_v8_version(branches), '--') 198 199 self._execute_git(['branch', 'remotes/origin/5.7.1']) 200 self._execute_git(['branch', 'remotes/origin/5.8.1']) 201 branches = self._get_branches(hash_of_first_commit); 202 self.assertEqual(mergeinfo.get_first_v8_version(branches), '5.7.1') 203 204 self._execute_git(['branch', 'remotes/origin/5.6.1']) 205 branches = self._get_branches(hash_of_first_commit); 206 self.assertEqual(mergeinfo.get_first_v8_version(branches), '5.6.1') 207 208if __name__ == "__main__": 209 unittest.main() 210