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

Side by Side Diff: scripts/tools/blink_roller/auto_roll_test.py

Issue 2205383002: Remove Blink auto-roll script (scripts/tools/blink_roller/). (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Created 4 years, 4 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
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2014 The Chromium 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
6
7 import datetime
8 import unittest
9
10 import auto_roll
11
12 # auto_roll.py imports find_depot_tools.
13 from testing_support.super_mox import SuperMoxTestBase
14
15
16 # pylint: disable=W0212
17
18
19 def _do_fetches():
20 auto_roll.subprocess2.check_call(
21 ['git', '--git-dir', './.git', 'fetch'])
22 auto_roll.subprocess2.check_call(
23 ['git', '--git-dir', './third_party/test_project/.git', 'fetch'])
24
25
26 class SheriffCalendarTest(SuperMoxTestBase):
27
28 def test_complete_email(self):
29 expected_emails = ['foo@chromium.org', 'bar@google.com', 'baz@chromium.org']
30 names = ['foo', 'bar@google.com', 'baz']
31 self.assertEqual(map(auto_roll._complete_email, names), expected_emails)
32
33 def test_emails(self):
34 expected_emails = ['foo@bar.com', 'baz@baz.com']
35 auto_roll._emails_from_url = lambda urls: expected_emails
36 self.assertEqual(auto_roll._current_gardener_emails(), expected_emails)
37 self.assertEqual(auto_roll._current_sheriff_emails(), expected_emails)
38
39 def _assert_parse(self, js_string, expected_emails):
40 self.assertEqual(
41 auto_roll._names_from_sheriff_js(js_string), expected_emails)
42
43 def test_names_from_sheriff_js(self):
44 self._assert_parse('document.write(\'none (channel is sheriff)\')', [])
45 self._assert_parse('document.write(\'foo, bar\')', ['foo', 'bar'])
46
47 def test_email_regexp(self):
48 self.assertTrue(auto_roll._email_is_valid('somebody@example.com'))
49 self.assertTrue(auto_roll._email_is_valid('somebody@example.domain.com'))
50 self.assertTrue(auto_roll._email_is_valid('somebody@example-domain.com'))
51 self.assertTrue(auto_roll._email_is_valid('some.body@example.com'))
52 self.assertTrue(auto_roll._email_is_valid('some_body@example.com'))
53 self.assertTrue(auto_roll._email_is_valid('some+body@example.com'))
54 self.assertTrue(auto_roll._email_is_valid('some+body@com'))
55 self.assertTrue(auto_roll._email_is_valid('some/body@example.com'))
56 # These are valid according to the standard, but not supported here.
57 self.assertFalse(auto_roll._email_is_valid('some~body@example.com'))
58 self.assertFalse(auto_roll._email_is_valid('some!body@example.com'))
59 self.assertFalse(auto_roll._email_is_valid('some?body@example.com'))
60 self.assertFalse(auto_roll._email_is_valid('some" "body@example.com'))
61 self.assertFalse(auto_roll._email_is_valid('"{somebody}"@example.com'))
62 # Bogus.
63 self.assertFalse(auto_roll._email_is_valid('rm -rf /#@example.com'))
64 self.assertFalse(auto_roll._email_is_valid('some body@example.com'))
65 self.assertFalse(auto_roll._email_is_valid('[some body]@example.com'))
66
67 def test_filter_emails(self):
68 input_emails = ['foo@bar.com', 'baz@baz.com', 'bogus email @ !!!']
69 expected_emails = ['foo@bar.com', 'baz@baz.com']
70 self.assertEquals(auto_roll._filter_emails(input_emails), expected_emails)
71 self.checkstdout('WARNING: Not including bogus email @ !!! '
72 '(invalid email address)\n')
73
74 class AutoRollTest(SuperMoxTestBase):
75
76 TEST_PROJECT = 'test_project'
77 TEST_AUTHOR = 'test_author@chromium.org'
78 PATH_TO_CHROME = '.'
79
80 DATETIME_FORMAT = '%d-%d-%d %d:%d:%d.%d'
81 CURRENT_DATETIME = (2014, 4, 1, 14, 57, 21, 01)
82 RECENT_ISSUE_CREATED = (2014, 4, 1, 13, 57, 21, 01)
83 OLD_ISSUE_CREATED = (2014, 2, 1, 13, 57, 21, 01)
84 CURRENT_DATETIME_STR = DATETIME_FORMAT % CURRENT_DATETIME
85 RECENT_ISSUE_CREATED_STR = DATETIME_FORMAT % RECENT_ISSUE_CREATED
86 OLD_ISSUE_CREATED_STR = DATETIME_FORMAT % OLD_ISSUE_CREATED
87
88 OLDER_REV = 'cfcf604fbdcf6e2d9b982a2fab3fc9f1e3f8cd65'
89 OLD_REV = 'b9af6489f6f2004ad11b82c6057f7007e3c35372'
90 NEW_REV = '79539998e04afab3ee9c3016881755ca52f60a73'
91
92 _GIT_LOG = '''
93 commit %s
94 Author: Test Author <test_author@example.com>
95 Date: Wed Apr 2 14:00:14 2014 -0400
96
97 Make some changes.
98 '''
99 GIT_LOG_UPDATED = _GIT_LOG % NEW_REV
100 GIT_LOG_TOO_OLD = _GIT_LOG % OLDER_REV
101
102 _commit_timestamps = {
103 OLDER_REV: '1399573100',
104 OLD_REV: '1399573342',
105 NEW_REV: '1399598876',
106 }
107
108 class MockHttpRpcServer(object):
109 def __init__(self, *args, **kwargs):
110 pass
111
112 class MockDateTime(datetime.datetime):
113 @classmethod
114 def utcnow(cls):
115 return AutoRollTest.MockDateTime(*AutoRollTest.CURRENT_DATETIME)
116
117 class MockFile(object):
118 def __init__(self, contents):
119 self._contents = contents
120
121 def read(self):
122 return self._contents
123
124 def setUp(self):
125 SuperMoxTestBase.setUp(self)
126 self.mox.StubOutWithMock(auto_roll.rietveld.Rietveld, 'add_comment')
127 self.mox.StubOutWithMock(auto_roll.rietveld.Rietveld, 'close_issue')
128 self.mox.StubOutWithMock(auto_roll.rietveld.Rietveld,
129 'get_issue_properties')
130 self.mox.StubOutWithMock(auto_roll.rietveld.Rietveld, 'search')
131 self.mox.StubOutWithMock(auto_roll.scm.GIT, 'Capture')
132 self.mox.StubOutWithMock(auto_roll.subprocess2, 'call')
133 self.mox.StubOutWithMock(auto_roll.subprocess2, 'check_call')
134 self.mox.StubOutWithMock(auto_roll.subprocess2, 'check_output')
135 self.mox.StubOutWithMock(auto_roll.urllib2, 'urlopen')
136 auto_roll.datetime.datetime = self.MockDateTime
137 auto_roll.rietveld.upload.HttpRpcServer = self.MockHttpRpcServer
138 self._arb = auto_roll.AutoRoller(self.TEST_PROJECT,
139 self.TEST_AUTHOR,
140 self.PATH_TO_CHROME)
141
142 def _make_issue(self, old_rev, new_rev, created_datetime=None,
143 svn_range_str=''):
144 description = auto_roll.ROLL_DESCRIPTION_STR % {
145 'dep_path': 'src/third_party/test_project',
146 'before_rev': self._display_rev(old_rev),
147 'after_rev': self._display_rev(new_rev),
148 'svn_range': svn_range_str,
149 'revlog_url': '',
150 }
151 return {
152 'author': self.TEST_AUTHOR,
153 'commit': created_datetime or self.RECENT_ISSUE_CREATED_STR,
154 'created': created_datetime or self.RECENT_ISSUE_CREATED_STR,
155 'description': description,
156 'issue': 1234567,
157 'messages': [],
158 'modified': created_datetime or self.RECENT_ISSUE_CREATED_STR,
159 'subject': description.splitlines()[0],
160 }
161
162 def _get_last_revision(self):
163 revinfo = (
164 'src/third_party/test_project: '
165 'https://chromium.googlesource.com/test_project.git@%s' %
166 str(self.OLD_REV))
167 auto_roll.subprocess2.check_output(['gclient', 'revinfo'],
168 cwd='.').AndReturn(revinfo)
169
170 def _get_current_revision(self):
171 self._parse_origin_master(returnval=self.NEW_REV)
172
173 def _upload_issue(self, custom_message=None):
174 _do_fetches()
175
176 self._get_last_revision()
177 self._get_current_revision()
178
179 self._compare_revs(self.OLD_REV, self.NEW_REV)
180
181 auto_roll.subprocess2.check_call(['git', 'clean', '-d', '-f'], cwd='.')
182 auto_roll.subprocess2.call(['git', 'rebase', '--abort'], cwd='.')
183 auto_roll.subprocess2.call(['git', 'branch', '-D', 'test_project_roll'],
184 cwd='.')
185 auto_roll.subprocess2.check_call(['git', 'checkout', 'origin/master', '-f'],
186 cwd='.')
187 auto_roll.subprocess2.check_call(['git', 'checkout',
188 '-b', 'test_project_roll',
189 '-t', 'origin/master', '-f'], cwd='.')
190
191 issue = self._make_issue(self.OLD_REV, self.NEW_REV,
192 created_datetime=self.CURRENT_DATETIME_STR)
193
194 if custom_message:
195 message = custom_message
196 else:
197 message = issue['description']
198
199 message += '\nTBR='
200 cmd = [
201 'roll-dep-svn', 'third_party/%s' % self.TEST_PROJECT, str(self.NEW_REV),
202 ]
203 auto_roll.subprocess2.check_call(cmd, cwd='.')
204
205 auto_roll.subprocess2.check_call(['git', 'add', 'DEPS'], cwd='.')
206 auto_roll.subprocess2.check_call(['git', 'commit', '--no-edit'], cwd='.')
207 auto_roll.subprocess2.check_output(
208 ['git', 'log', '-n1', '--format=%B', 'HEAD'],
209 cwd='.').AndReturn(issue['description'])
210 auto_roll.subprocess2.check_call(['git', 'cl', 'upload', '--bypass-hooks',
211 '-f', '--use-commit-queue',
212 '-m', message],
213 cwd='.')
214 auto_roll.subprocess2.check_call(['git', 'checkout', 'origin/master', '-f'],
215 cwd='.')
216 auto_roll.subprocess2.check_call(['git', 'branch', '-D',
217 'test_project_roll'], cwd='.')
218
219 self._arb._rietveld.search(owner=self.TEST_AUTHOR,
220 closed=2).AndReturn([issue])
221 self._arb._rietveld.add_comment(issue['issue'],
222 self._arb.ROLL_BOT_INSTRUCTIONS)
223
224 def test_should_stop(self):
225 _do_fetches()
226 issue = self._make_issue(self.OLD_REV, self.NEW_REV,
227 created_datetime=self.OLD_ISSUE_CREATED_STR)
228 issue['messages'].append({
229 'text': 'STOP',
230 'sender': self.TEST_AUTHOR,
231 'date': '2014-3-31 13:57:21.01'
232 })
233 search_results = [issue]
234 self._arb._rietveld.search(owner=self.TEST_AUTHOR,
235 closed=2).AndReturn(search_results)
236 self._arb._rietveld.get_issue_properties(issue['issue'],
237 messages=True).AndReturn(issue)
238 self._arb._rietveld.add_comment(issue['issue'], '''
239 Rollbot was stopped by the presence of 'STOP' in an earlier comment.
240 The last update to this issue was over 12:00:00 hours ago.
241 Please close this issue as soon as possible to allow the bot to continue.
242
243 Please email (dpranke@chromium.org) if the Rollbot is causing trouble.
244 ''')
245
246 self.mox.ReplayAll()
247 self.assertEquals(self._arb.main(), 1)
248 self.checkstdout('https://codereview.chromium.org/%d/: Rollbot was '
249 'stopped by test_author@chromium.org on at 2014-3-31 '
250 '13:57:21.01, waiting.\n' % issue['issue'])
251
252 def test_already_rolling(self):
253 _do_fetches()
254 issue = self._make_issue(self.OLD_REV, self.NEW_REV)
255 search_results = [issue]
256 self._arb._rietveld.search(owner=self.TEST_AUTHOR,
257 closed=2).AndReturn(search_results)
258 self._arb._rietveld.get_issue_properties(issue['issue'],
259 messages=True).AndReturn(issue)
260 self._get_last_revision()
261 self._short_rev(self.OLD_REV)
262 self.mox.ReplayAll()
263 self.assertEquals(self._arb.main(), 0)
264 self.checkstdout('https://codereview.chromium.org/%d/ started %s ago\n'
265 'https://codereview.chromium.org/%d/ is still active, '
266 'nothing to do.\n'
267 % (issue['issue'], '0:59:59.900001', issue['issue']))
268
269 def test_old_issue(self):
270 issue = self._make_issue(self.OLD_REV, self.NEW_REV,
271 created_datetime=self.OLD_ISSUE_CREATED_STR)
272 search_results = [issue]
273 self._arb._rietveld.search(owner=self.TEST_AUTHOR,
274 closed=2).AndReturn(search_results)
275 self._arb._rietveld.get_issue_properties(issue['issue'],
276 messages=True).AndReturn(issue)
277 comment_str = ('Giving up on this roll after 1 day, 0:00:00. Closing, will '
278 'open a new roll.')
279 self._arb._rietveld.add_comment(issue['issue'], comment_str)
280 self._arb._rietveld.close_issue(issue['issue'])
281 self._upload_issue()
282 self.mox.ReplayAll()
283 self.assertEquals(self._arb.main(), 0)
284 self.checkstdout('https://codereview.chromium.org/%d/ started %s ago\n'
285 'Closing https://codereview.chromium.org/%d/ with message:'
286 ' \'%s\'\n'
287 % (issue['issue'], '59 days, 0:59:59.900001',
288 issue['issue'], comment_str))
289
290 def test_failed_cq(self):
291 issue = self._make_issue(self.OLD_REV, self.NEW_REV)
292 issue['commit'] = False
293 search_results = [issue]
294 self._arb._rietveld.search(owner=self.TEST_AUTHOR,
295 closed=2).AndReturn(search_results)
296 self._arb._rietveld.get_issue_properties(issue['issue'],
297 messages=True).AndReturn(issue)
298 comment_str = 'No longer marked for the CQ. Closing, will open a new roll.'
299 self._arb._rietveld.add_comment(issue['issue'], comment_str)
300 self._arb._rietveld.close_issue(issue['issue'])
301 self._upload_issue()
302 self.mox.ReplayAll()
303 self.assertEquals(self._arb.main(), 0)
304 self.checkstdout('Closing https://codereview.chromium.org/%d/ with message:'
305 ' \'%s\'\n' % (issue['issue'], comment_str))
306
307 def test_no_roll_backwards(self):
308 _do_fetches()
309 self._arb._rietveld.search(owner=self.TEST_AUTHOR, closed=2).AndReturn([])
310 self._get_last_revision()
311 auto_roll.subprocess2.check_output(
312 ['git', '--git-dir', './third_party/test_project/.git', 'rev-parse',
313 'origin/master']).AndReturn(self.OLDER_REV)
314 self._compare_revs(self.OLD_REV, self.OLDER_REV)
315
316 self.mox.ReplayAll()
317 self.assertEquals(self._arb.main(), 0)
318 self.checkstdout('Already at %s refusing to roll backwards to %s.\n' % (
319 self.OLD_REV, self.OLDER_REV))
320
321 def test_upload_issue(self):
322 self._arb._rietveld.search(owner=self.TEST_AUTHOR, closed=2).AndReturn([])
323 self._upload_issue()
324 self.mox.ReplayAll()
325 self.assertEquals(self._arb.main(), 0)
326
327 def test_notry(self):
328 class MockOptions:
329 def __init__(self):
330 self.notry = True
331
332 self._arb = auto_roll.AutoRoller(self.TEST_PROJECT,
333 self.TEST_AUTHOR,
334 self.PATH_TO_CHROME,
335 options=MockOptions())
336
337 self._arb._rietveld.search(owner=self.TEST_AUTHOR, closed=2).AndReturn([])
338 svn_range_str = ''
339 commit_msg = self._make_issue(self.OLD_REV, self.NEW_REV,
340 svn_range_str=svn_range_str)['description']
341 commit_msg += ('\nSheriffs: In case of breakage, do NOT revert this roll, '
342 'revert the\noffending commit in the test_project '
343 'repository instead.\n\nNOTRY=true')
344 self._upload_issue(custom_message=commit_msg)
345 self.mox.ReplayAll()
346 self.assertEquals(self._arb.main(), 0)
347
348 def test_last_revision(self):
349 # Verify that AutoRoll._last_roll_revision() returns a string.
350 self._get_last_revision()
351 self.mox.ReplayAll()
352 self.assertEquals(type(self._arb._last_roll_revision()), str)
353
354 def test_current_revision(self):
355 # Verify that AutoRoll._current_revision() returns a string.
356 self._get_current_revision()
357 self.mox.ReplayAll()
358 self.assertEquals(type(self._arb._current_revision()), str)
359
360 def test_extra_trybots(self):
361 self._arb._cq_extra_trybots = ['sometrybot']
362 self._arb._rietveld.search(owner=self.TEST_AUTHOR, closed=2).AndReturn([])
363 svn_range_str = ''
364 commit_msg = self._make_issue(self.OLD_REV, self.NEW_REV,
365 svn_range_str=svn_range_str)['description']
366 commit_msg += '\nCQ_INCLUDE_TRYBOTS=sometrybot'
367 self._upload_issue(custom_message=commit_msg)
368 self.mox.ReplayAll()
369 self.assertEquals(self._arb.main(), 0)
370
371 # pylint: disable=R0201
372 def _display_rev(self, rev):
373 return rev[:7]
374
375 # pylint: disable=R0201
376 def _short_rev(self, rev):
377 auto_roll.subprocess2.check_output(['git', '--git-dir',
378 './third_party/test_project/.git',
379 'rev-parse', '--short', rev]
380 ).AndReturn(self._display_rev(rev))
381
382 def _compare_revs(self, old_rev, new_rev):
383 merge_base_cmd = ['git', '--git-dir', './third_party/test_project/.git',
384 'merge-base', '--is-ancestor', new_rev, old_rev]
385 if self._commit_timestamps[old_rev] < self._commit_timestamps[new_rev]:
386 err = auto_roll.subprocess2.CalledProcessError(1, '', '', '', '')
387 auto_roll.subprocess2.check_call(merge_base_cmd).AndRaise(err)
388 else:
389 auto_roll.subprocess2.check_call(merge_base_cmd)
390 return
391
392 # pylint: disable=R0201
393 def _parse_origin_master(self, returnval):
394 auto_roll.subprocess2.check_output(
395 ['git', '--git-dir', './third_party/test_project/.git', 'rev-parse',
396 'origin/master']).AndReturn(returnval)
397
398
399 if __name__ == '__main__':
400 unittest.main()
OLDNEW
« no previous file with comments | « scripts/tools/blink_roller/auto_roll.py ('k') | scripts/tools/blink_roller/auto_roll_wrapper.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698