blob: cf6123611f096b356c14cbefee6b20da68dd88dd [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001#!/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
6from collections import namedtuple
7from os import path
8import search_related_commits
9import shutil
10from subprocess import Popen, PIPE, check_call
11import unittest
12
13
14TEST_CONFIG = {
15 "GIT_REPO": "/tmp/test-v8-search-related-commits",
16}
17
18class TestSearchRelatedCommits(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 setUp(self):
34 if path.exists(self.base_dir):
35 shutil.rmtree(self.base_dir)
36
37 check_call(["git", "init", self.base_dir])
38
39 # Initial commit
40 message = """[turbofan] Sanitize language mode for javascript operators.
41
42 R=mstarzinger@chromium.org
43
44 Review URL: https://codereview.chromium.org/1084243005
45
46 Cr-Commit-Position: refs/heads/master@{#28059}"""
47 self._make_empty_commit(message)
48
49 message = """[crankshaft] Do some stuff
50
51 R=hablich@chromium.org
52
53 Review URL: https://codereview.chromium.org/1084243007
54
55 Cr-Commit-Position: refs/heads/master@{#28030}"""
56
57 self._make_empty_commit(message)
58
59 def tearDown(self):
60 if path.exists(self.base_dir):
61 shutil.rmtree(self.base_dir)
62
63 def _assert_correct_standard_result(
64 self, result, all_commits, hash_of_first_commit):
65 self.assertEqual(len(result), 1, "Master commit not found")
66 self.assertTrue(
67 result.get(hash_of_first_commit),
68 "Master commit is wrong")
69
70 self.assertEqual(
71 len(result[hash_of_first_commit]),
72 1,
73 "Child commit not found")
74 self.assertEqual(
75 all_commits[2],
76 result[hash_of_first_commit][0],
77 "Child commit wrong")
78
79 def _get_commits(self):
80 commits = self._execute_git(
81 ["log", "--format=%H", "--reverse"]).splitlines()
82 return commits
83
84 def _make_empty_commit(self, message):
85 self._execute_git(["commit", "--allow-empty", "-m", message])
86
87 def testSearchByCommitPosition(self):
88 message = """Revert of some stuff.
89 > Cr-Commit-Position: refs/heads/master@{#28059}
90 R=mstarzinger@chromium.org
91
92 Review URL: https://codereview.chromium.org/1084243005
93
94 Cr-Commit-Position: refs/heads/master@{#28088}"""
95
96 self._make_empty_commit(message)
97
98 commits = self._get_commits()
99 hash_of_first_commit = commits[0]
100
101 result = search_related_commits.search_all_related_commits(
102 self.base_dir, hash_of_first_commit, "HEAD", None)
103
104 self._assert_correct_standard_result(result, commits, hash_of_first_commit)
105
106 def testSearchByTitle(self):
107 message = """Revert of some stuff.
108 > [turbofan] Sanitize language mode for javascript operators.
109 > Cr-Commit-Position: refs/heads/master@{#289}
110 R=mstarzinger@chromium.org
111
112 Review URL: https://codereview.chromium.org/1084243005
113
114 Cr-Commit-Position: refs/heads/master@{#28088}"""
115
116 self._make_empty_commit(message)
117
118 commits = self._get_commits()
119 hash_of_first_commit = commits[0]
120
121 result = search_related_commits.search_all_related_commits(
122 self.base_dir, hash_of_first_commit, "HEAD", None)
123
124 self._assert_correct_standard_result(result, commits, hash_of_first_commit)
125
126 def testSearchByHash(self):
127 commits = self._get_commits()
128 hash_of_first_commit = commits[0]
129
130 message = """Revert of some stuff.
131 > [turbofan] Sanitize language mode for javascript operators.
132 > Reverting """ + hash_of_first_commit + """
133 > R=mstarzinger@chromium.org
134
135 Review URL: https://codereview.chromium.org/1084243005
136
137 Cr-Commit-Position: refs/heads/master@{#28088}"""
138
139 self._make_empty_commit(message)
140
141 #Fetch again for an update
142 commits = self._get_commits()
143 hash_of_first_commit = commits[0]
144
145 result = search_related_commits.search_all_related_commits(
146 self.base_dir,
147 hash_of_first_commit,
148 "HEAD",
149 None)
150
151 self._assert_correct_standard_result(result, commits, hash_of_first_commit)
152
153 def testConsiderSeparator(self):
154 commits = self._get_commits()
155 hash_of_first_commit = commits[0]
156
157 # Related commits happen before separator so it is not a hit
158 message = """Revert of some stuff: Not a hit
159 > [turbofan] Sanitize language mode for javascript operators.
160 > Reverting """ + hash_of_first_commit + """
161 > R=mstarzinger@chromium.org
162
163 Review URL: https://codereview.chromium.org/1084243005
164
165 Cr-Commit-Position: refs/heads/master@{#28088}"""
166 self._make_empty_commit(message)
167
168 # Related commits happen before and after separator so it is a hit
169 commit_pos_of_master = "27088"
170 message = """Implement awesome feature: Master commit
171
172 Review URL: https://codereview.chromium.org/1084243235
173
174 Cr-Commit-Position: refs/heads/master@{#""" + commit_pos_of_master + "}"
175 self._make_empty_commit(message)
176
177 # Separator commit
178 message = """Commit which is the origin of the branch
179
180 Review URL: https://codereview.chromium.org/1084243456
181
182 Cr-Commit-Position: refs/heads/master@{#28173}"""
183 self._make_empty_commit(message)
184
185 # Filler commit
186 message = "Some unrelated commit: Not a hit"
187 self._make_empty_commit(message)
188
189 # Related commit after separator: a hit
190 message = "Patch r" + commit_pos_of_master +""" done
191
192 Review URL: https://codereview.chromium.org/1084243235
193
194 Cr-Commit-Position: refs/heads/master@{#29567}"""
195 self._make_empty_commit(message)
196
197 #Fetch again for an update
198 commits = self._get_commits()
199 hash_of_first_commit = commits[0]
200 hash_of_hit = commits[3]
201 hash_of_separator = commits[4]
202 hash_of_child_hit = commits[6]
203
204 result = search_related_commits.search_all_related_commits(
205 self.base_dir,
206 hash_of_first_commit,
207 "HEAD",
208 hash_of_separator)
209
210 self.assertTrue(result.get(hash_of_hit), "Hit not found")
211 self.assertEqual(len(result), 1, "More than one hit found")
212 self.assertEqual(
213 len(result.get(hash_of_hit)),
214 1,
215 "More than one child hit found")
216 self.assertEqual(
217 result.get(hash_of_hit)[0],
218 hash_of_child_hit,
219 "Wrong commit found")
220
221 def testPrettyPrint(self):
222 message = """Revert of some stuff.
223 > [turbofan] Sanitize language mode for javascript operators.
224 > Cr-Commit-Position: refs/heads/master@{#289}
225 R=mstarzinger@chromium.org
226
227 Review URL: https://codereview.chromium.org/1084243005
228
229 Cr-Commit-Position: refs/heads/master@{#28088}"""
230
231 self._make_empty_commit(message)
232
233 commits = self._get_commits()
234 hash_of_first_commit = commits[0]
235 OptionsStruct = namedtuple(
236 "OptionsStruct",
237 "git_dir of until all prettyprint separator verbose")
238 options = OptionsStruct(
239 git_dir= self.base_dir,
240 of= [hash_of_first_commit],
241 until= [commits[2]],
242 all= True,
243 prettyprint= True,
244 separator = None,
245 verbose=False)
246 output = []
247 for current_line in search_related_commits.main(options):
248 output.append(current_line)
249
250 self.assertIs(len(output), 2, "Not exactly two entries written")
251 self.assertTrue(output[0].startswith("+"), "Master entry not marked with +")
252 self.assertTrue(output[1].startswith("| "), "Child entry not marked with |")
253
254 def testNothingFound(self):
255 commits = self._get_commits()
256
257 self._execute_git(["commit", "--allow-empty", "-m", "A"])
258 self._execute_git(["commit", "--allow-empty", "-m", "B"])
259 self._execute_git(["commit", "--allow-empty", "-m", "C"])
260 self._execute_git(["commit", "--allow-empty", "-m", "D"])
261
262 hash_of_first_commit = commits[0]
263 result = search_related_commits.search_all_related_commits(
264 self.base_dir,
265 hash_of_first_commit,
266 "HEAD",
267 None)
268
269 self.assertEqual(len(result), 0, "Results found where none should be.")
270
271
272if __name__ == "__main__":
273 #import sys;sys.argv = ['', 'Test.testName']
274 unittest.main()