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

Side by Side Diff: tools/push-to-trunk/test_scripts.py

Issue 868473004: External name changes of release scripts. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 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
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2013 the V8 project authors. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following
11 # disclaimer in the documentation and/or other materials provided
12 # with the distribution.
13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived
15 # from this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 import os
30 import shutil
31 import tempfile
32 import traceback
33 import unittest
34
35 import auto_push
36 from auto_push import CheckLastPush
37 import auto_roll
38 import common_includes
39 from common_includes import *
40 import merge_to_branch
41 from merge_to_branch import *
42 import push_to_trunk
43 from push_to_trunk import *
44 import chromium_roll
45 from chromium_roll import ChromiumRoll
46 import releases
47 from releases import Releases
48 from auto_tag import AutoTag
49
50
51 TEST_CONFIG = {
52 "DEFAULT_CWD": None,
53 "BRANCHNAME": "test-prepare-push",
54 "CANDIDATESBRANCH": "test-candidates-push",
55 "PERSISTFILE_BASENAME": "/tmp/test-v8-push-to-candidates-tempfile",
56 "CHANGELOG_ENTRY_FILE":
57 "/tmp/test-v8-push-to-candidates-tempfile-changelog-entry",
58 "PATCH_FILE": "/tmp/test-v8-push-to-candidates-tempfile-patch",
59 "COMMITMSG_FILE": "/tmp/test-v8-push-to-candidates-tempfile-commitmsg",
60 "CHROMIUM": "/tmp/test-v8-push-to-candidates-tempfile-chromium",
61 "SETTINGS_LOCATION": None,
62 "ALREADY_MERGING_SENTINEL_FILE":
63 "/tmp/test-merge-to-branch-tempfile-already-merging",
64 "TEMPORARY_PATCH_FILE": "/tmp/test-merge-to-branch-tempfile-temporary-patch",
65 "CLUSTERFUZZ_API_KEY_FILE": "/tmp/test-fake-cf-api-key",
66 }
67
68
69 AUTO_PUSH_ARGS = [
70 "-a", "author@chromium.org",
71 "-r", "reviewer@chromium.org",
72 ]
73
74
75 class ToplevelTest(unittest.TestCase):
76 def testSortBranches(self):
77 S = releases.SortBranches
78 self.assertEquals(["3.1", "2.25"], S(["2.25", "3.1"])[0:2])
79 self.assertEquals(["3.0", "2.25"], S(["2.25", "3.0", "2.24"])[0:2])
80 self.assertEquals(["3.11", "3.2"], S(["3.11", "3.2", "2.24"])[0:2])
81
82 def testFilterDuplicatesAndReverse(self):
83 F = releases.FilterDuplicatesAndReverse
84 self.assertEquals([], F([]))
85 self.assertEquals([["100", "10"]], F([["100", "10"]]))
86 self.assertEquals([["99", "9"], ["100", "10"]],
87 F([["100", "10"], ["99", "9"]]))
88 self.assertEquals([["98", "9"], ["100", "10"]],
89 F([["100", "10"], ["99", "9"], ["98", "9"]]))
90 self.assertEquals([["98", "9"], ["99", "10"]],
91 F([["100", "10"], ["99", "10"], ["98", "9"]]))
92
93 def testBuildRevisionRanges(self):
94 B = releases.BuildRevisionRanges
95 self.assertEquals({}, B([]))
96 self.assertEquals({"10": "100"}, B([["100", "10"]]))
97 self.assertEquals({"10": "100", "9": "99:99"},
98 B([["100", "10"], ["99", "9"]]))
99 self.assertEquals({"10": "100", "9": "97:99"},
100 B([["100", "10"], ["98", "9"], ["97", "9"]]))
101 self.assertEquals({"10": "100", "9": "99:99", "3": "91:98"},
102 B([["100", "10"], ["99", "9"], ["91", "3"]]))
103 self.assertEquals({"13": "101", "12": "100:100", "9": "94:97",
104 "3": "91:93, 98:99"},
105 B([["101", "13"], ["100", "12"], ["98", "3"],
106 ["94", "9"], ["91", "3"]]))
107
108 def testMakeComment(self):
109 self.assertEquals("# Line 1\n# Line 2\n#",
110 MakeComment(" Line 1\n Line 2\n"))
111 self.assertEquals("#Line 1\n#Line 2",
112 MakeComment("Line 1\n Line 2"))
113
114 def testStripComments(self):
115 self.assertEquals(" Line 1\n Line 3\n",
116 StripComments(" Line 1\n# Line 2\n Line 3\n#\n"))
117 self.assertEquals("\nLine 2 ### Test\n #",
118 StripComments("###\n# \n\n# Line 1\nLine 2 ### Test\n #"))
119
120 def testMakeChangeLogBodySimple(self):
121 commits = [
122 ["Title text 1",
123 "Title text 1\n\nBUG=\n",
124 "author1@chromium.org"],
125 ["Title text 2.",
126 "Title text 2\n\nBUG=1234\n",
127 "author2@chromium.org"],
128 ]
129 self.assertEquals(" Title text 1.\n"
130 " (author1@chromium.org)\n\n"
131 " Title text 2 (Chromium issue 1234).\n"
132 " (author2@chromium.org)\n\n",
133 MakeChangeLogBody(commits))
134
135 def testMakeChangeLogBodyEmpty(self):
136 self.assertEquals("", MakeChangeLogBody([]))
137
138 def testMakeChangeLogBodyAutoFormat(self):
139 commits = [
140 ["Title text 1!",
141 "Title text 1\nLOG=y\nBUG=\n",
142 "author1@chromium.org"],
143 ["Title text 2",
144 "Title text 2\n\nBUG=1234\n",
145 "author2@chromium.org"],
146 ["Title text 3",
147 "Title text 3\n\nBUG=1234\nLOG = Yes\n",
148 "author3@chromium.org"],
149 ["Title text 3",
150 "Title text 4\n\nBUG=1234\nLOG=\n",
151 "author4@chromium.org"],
152 ]
153 self.assertEquals(" Title text 1.\n\n"
154 " Title text 3 (Chromium issue 1234).\n\n",
155 MakeChangeLogBody(commits, True))
156
157 def testRegressWrongLogEntryOnTrue(self):
158 body = """
159 Check elimination: Learn from if(CompareMap(x)) on true branch.
160
161 BUG=
162 R=verwaest@chromium.org
163
164 Committed: https://code.google.com/p/v8/source/detail?r=18210
165 """
166 self.assertEquals("", MakeChangeLogBody([["title", body, "author"]], True))
167
168 def testMakeChangeLogBugReferenceEmpty(self):
169 self.assertEquals("", MakeChangeLogBugReference(""))
170 self.assertEquals("", MakeChangeLogBugReference("LOG="))
171 self.assertEquals("", MakeChangeLogBugReference(" BUG ="))
172 self.assertEquals("", MakeChangeLogBugReference("BUG=none\t"))
173
174 def testMakeChangeLogBugReferenceSimple(self):
175 self.assertEquals("(issue 987654)",
176 MakeChangeLogBugReference("BUG = v8:987654"))
177 self.assertEquals("(Chromium issue 987654)",
178 MakeChangeLogBugReference("BUG=987654 "))
179
180 def testMakeChangeLogBugReferenceFromBody(self):
181 self.assertEquals("(Chromium issue 1234567)",
182 MakeChangeLogBugReference("Title\n\nTBR=\nBUG=\n"
183 " BUG=\tchromium:1234567\t\n"
184 "R=somebody\n"))
185
186 def testMakeChangeLogBugReferenceMultiple(self):
187 # All issues should be sorted and grouped. Multiple references to the same
188 # issue should be filtered.
189 self.assertEquals("(issues 123, 234, Chromium issue 345)",
190 MakeChangeLogBugReference("Title\n\n"
191 "BUG=v8:234\n"
192 " BUG\t= 345, \tv8:234,\n"
193 "BUG=v8:123\n"
194 "R=somebody\n"))
195 self.assertEquals("(Chromium issues 123, 234)",
196 MakeChangeLogBugReference("Title\n\n"
197 "BUG=234,,chromium:123 \n"
198 "R=somebody\n"))
199 self.assertEquals("(Chromium issues 123, 234)",
200 MakeChangeLogBugReference("Title\n\n"
201 "BUG=chromium:234, , 123\n"
202 "R=somebody\n"))
203 self.assertEquals("(issues 345, 456)",
204 MakeChangeLogBugReference("Title\n\n"
205 "\t\tBUG=v8:345,v8:456\n"
206 "R=somebody\n"))
207 self.assertEquals("(issue 123, Chromium issues 345, 456)",
208 MakeChangeLogBugReference("Title\n\n"
209 "BUG=chromium:456\n"
210 "BUG = none\n"
211 "R=somebody\n"
212 "BUG=456,v8:123, 345"))
213
214 # TODO(machenbach): These test don't make much sense when the formatting is
215 # done later.
216 def testMakeChangeLogBugReferenceLong(self):
217 # -----------------00--------10--------20--------30--------
218 self.assertEquals("(issues 234, 1234567890, 1234567"
219 "8901234567890, Chromium issues 12345678,"
220 " 123456789)",
221 MakeChangeLogBugReference("BUG=v8:234\n"
222 "BUG=v8:1234567890\n"
223 "BUG=v8:12345678901234567890\n"
224 "BUG=123456789\n"
225 "BUG=12345678\n"))
226 # -----------------00--------10--------20--------30--------
227 self.assertEquals("(issues 234, 1234567890, 1234567"
228 "8901234567890, Chromium issues"
229 " 123456789, 1234567890)",
230 MakeChangeLogBugReference("BUG=v8:234\n"
231 "BUG=v8:12345678901234567890\n"
232 "BUG=v8:1234567890\n"
233 "BUG=123456789\n"
234 "BUG=1234567890\n"))
235 # -----------------00--------10--------20--------30--------
236 self.assertEquals("(Chromium issues 234, 1234567890"
237 ", 12345678901234567, "
238 "1234567890123456789)",
239 MakeChangeLogBugReference("BUG=234\n"
240 "BUG=12345678901234567\n"
241 "BUG=1234567890123456789\n"
242 "BUG=1234567890\n"))
243
244
245 def Cmd(*args, **kwargs):
246 """Convenience function returning a shell command test expectation."""
247 return {
248 "name": "command",
249 "args": args,
250 "ret": args[-1],
251 "cb": kwargs.get("cb"),
252 "cwd": kwargs.get("cwd", TEST_CONFIG["DEFAULT_CWD"]),
253 }
254
255
256 def RL(text, cb=None):
257 """Convenience function returning a readline test expectation."""
258 return {
259 "name": "readline",
260 "args": [],
261 "ret": text,
262 "cb": cb,
263 "cwd": None,
264 }
265
266
267 def URL(*args, **kwargs):
268 """Convenience function returning a readurl test expectation."""
269 return {
270 "name": "readurl",
271 "args": args[:-1],
272 "ret": args[-1],
273 "cb": kwargs.get("cb"),
274 "cwd": None,
275 }
276
277
278 class SimpleMock(object):
279 def __init__(self):
280 self._recipe = []
281 self._index = -1
282
283 def Expect(self, recipe):
284 self._recipe = recipe
285
286 def Call(self, name, *args, **kwargs): # pragma: no cover
287 self._index += 1
288 try:
289 expected_call = self._recipe[self._index]
290 except IndexError:
291 raise NoRetryException("Calling %s %s" % (name, " ".join(args)))
292
293 if not isinstance(expected_call, dict):
294 raise NoRetryException("Found wrong expectation type for %s %s" %
295 (name, " ".join(args)))
296
297 if expected_call["name"] != name:
298 raise NoRetryException("Expected action: %s %s - Actual: %s" %
299 (expected_call["name"], expected_call["args"], name))
300
301 # Check if the given working directory matches the expected one.
302 if expected_call["cwd"] != kwargs.get("cwd"):
303 raise NoRetryException("Expected cwd: %s in %s %s - Actual: %s" %
304 (expected_call["cwd"],
305 expected_call["name"],
306 expected_call["args"],
307 kwargs.get("cwd")))
308
309 # The number of arguments in the expectation must match the actual
310 # arguments.
311 if len(args) > len(expected_call['args']):
312 raise NoRetryException("When calling %s with arguments, the "
313 "expectations must consist of at least as many arguments." %
314 name)
315
316 # Compare expected and actual arguments.
317 for (expected_arg, actual_arg) in zip(expected_call['args'], args):
318 if expected_arg != actual_arg:
319 raise NoRetryException("Expected: %s - Actual: %s" %
320 (expected_arg, actual_arg))
321
322 # The expected call contains an optional callback for checking the context
323 # at the time of the call.
324 if expected_call['cb']:
325 try:
326 expected_call['cb']()
327 except:
328 tb = traceback.format_exc()
329 raise NoRetryException("Caught exception from callback: %s" % tb)
330
331 # If the return value is an exception, raise it instead of returning.
332 if isinstance(expected_call['ret'], Exception):
333 raise expected_call['ret']
334 return expected_call['ret']
335
336 def AssertFinished(self): # pragma: no cover
337 if self._index < len(self._recipe) -1:
338 raise NoRetryException("Called mock too seldom: %d vs. %d" %
339 (self._index, len(self._recipe)))
340
341
342 class ScriptTest(unittest.TestCase):
343 def MakeEmptyTempFile(self):
344 handle, name = tempfile.mkstemp()
345 os.close(handle)
346 self._tmp_files.append(name)
347 return name
348
349 def MakeEmptyTempDirectory(self):
350 name = tempfile.mkdtemp()
351 self._tmp_files.append(name)
352 return name
353
354
355 def WriteFakeVersionFile(self, minor=22, build=4, patch=0):
356 version_file = os.path.join(TEST_CONFIG["DEFAULT_CWD"], VERSION_FILE)
357 if not os.path.exists(os.path.dirname(version_file)):
358 os.makedirs(os.path.dirname(version_file))
359 with open(version_file, "w") as f:
360 f.write(" // Some line...\n")
361 f.write("\n")
362 f.write("#define MAJOR_VERSION 3\n")
363 f.write("#define MINOR_VERSION %s\n" % minor)
364 f.write("#define BUILD_NUMBER %s\n" % build)
365 f.write("#define PATCH_LEVEL %s\n" % patch)
366 f.write(" // Some line...\n")
367 f.write("#define IS_CANDIDATE_VERSION 0\n")
368
369 def MakeStep(self):
370 """Convenience wrapper."""
371 options = ScriptsBase(TEST_CONFIG, self, self._state).MakeOptions([])
372 return MakeStep(step_class=Step, state=self._state,
373 config=TEST_CONFIG, side_effect_handler=self,
374 options=options)
375
376 def RunStep(self, script=PushToCandidates, step_class=Step, args=None):
377 """Convenience wrapper."""
378 args = args if args is not None else ["-m"]
379 return script(TEST_CONFIG, self, self._state).RunSteps([step_class], args)
380
381 def Call(self, fun, *args, **kwargs):
382 print "Calling %s with %s and %s" % (str(fun), str(args), str(kwargs))
383
384 def Command(self, cmd, args="", prefix="", pipe=True, cwd=None):
385 print "%s %s" % (cmd, args)
386 print "in %s" % cwd
387 return self._mock.Call("command", cmd + " " + args, cwd=cwd)
388
389 def ReadLine(self):
390 return self._mock.Call("readline")
391
392 def ReadURL(self, url, params):
393 if params is not None:
394 return self._mock.Call("readurl", url, params)
395 else:
396 return self._mock.Call("readurl", url)
397
398 def ReadClusterFuzzAPI(self, api_key, **params):
399 # TODO(machenbach): Use a mock for this and add a test that stops rolling
400 # due to clustefuzz results.
401 return []
402
403 def Sleep(self, seconds):
404 pass
405
406 def GetDate(self):
407 return "1999-07-31"
408
409 def GetUTCStamp(self):
410 return "100000"
411
412 def Expect(self, *args):
413 """Convenience wrapper."""
414 self._mock.Expect(*args)
415
416 def setUp(self):
417 self._mock = SimpleMock()
418 self._tmp_files = []
419 self._state = {}
420 TEST_CONFIG["DEFAULT_CWD"] = self.MakeEmptyTempDirectory()
421
422 def tearDown(self):
423 if os.path.exists(TEST_CONFIG["PERSISTFILE_BASENAME"]):
424 shutil.rmtree(TEST_CONFIG["PERSISTFILE_BASENAME"])
425
426 # Clean up temps. Doesn't work automatically.
427 for name in self._tmp_files:
428 if os.path.isfile(name):
429 os.remove(name)
430 if os.path.isdir(name):
431 shutil.rmtree(name)
432
433 self._mock.AssertFinished()
434
435 def testGitMock(self):
436 self.Expect([Cmd("git --version", "git version 1.2.3"),
437 Cmd("git dummy", "")])
438 self.assertEquals("git version 1.2.3", self.MakeStep().Git("--version"))
439 self.assertEquals("", self.MakeStep().Git("dummy"))
440
441 def testCommonPrepareDefault(self):
442 self.Expect([
443 Cmd("git status -s -uno", ""),
444 Cmd("git status -s -b -uno", "## some_branch"),
445 Cmd("git fetch", ""),
446 Cmd("git branch", " branch1\n* %s" % TEST_CONFIG["BRANCHNAME"]),
447 RL("Y"),
448 Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
449 ])
450 self.MakeStep().CommonPrepare()
451 self.MakeStep().PrepareBranch()
452 self.assertEquals("some_branch", self._state["current_branch"])
453
454 def testCommonPrepareNoConfirm(self):
455 self.Expect([
456 Cmd("git status -s -uno", ""),
457 Cmd("git status -s -b -uno", "## some_branch"),
458 Cmd("git fetch", ""),
459 Cmd("git branch", " branch1\n* %s" % TEST_CONFIG["BRANCHNAME"]),
460 RL("n"),
461 ])
462 self.MakeStep().CommonPrepare()
463 self.assertRaises(Exception, self.MakeStep().PrepareBranch)
464 self.assertEquals("some_branch", self._state["current_branch"])
465
466 def testCommonPrepareDeleteBranchFailure(self):
467 self.Expect([
468 Cmd("git status -s -uno", ""),
469 Cmd("git status -s -b -uno", "## some_branch"),
470 Cmd("git fetch", ""),
471 Cmd("git branch", " branch1\n* %s" % TEST_CONFIG["BRANCHNAME"]),
472 RL("Y"),
473 Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], None),
474 ])
475 self.MakeStep().CommonPrepare()
476 self.assertRaises(Exception, self.MakeStep().PrepareBranch)
477 self.assertEquals("some_branch", self._state["current_branch"])
478
479 def testInitialEnvironmentChecks(self):
480 TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
481 os.environ["EDITOR"] = "vi"
482 self.Expect([
483 Cmd("which vi", "/usr/bin/vi"),
484 ])
485 self.MakeStep().InitialEnvironmentChecks(TEST_CONFIG["DEFAULT_CWD"])
486
487 def testTagTimeout(self):
488 self.Expect([
489 Cmd("git fetch", ""),
490 Cmd("git log -1 --format=%H --grep=\"Title\" origin/candidates", ""),
491 Cmd("git fetch", ""),
492 Cmd("git log -1 --format=%H --grep=\"Title\" origin/candidates", ""),
493 Cmd("git fetch", ""),
494 Cmd("git log -1 --format=%H --grep=\"Title\" origin/candidates", ""),
495 Cmd("git fetch", ""),
496 Cmd("git log -1 --format=%H --grep=\"Title\" origin/candidates", ""),
497 ])
498 args = ["--branch", "candidates", "ab12345"]
499 self._state["version"] = "tag_name"
500 self._state["commit_title"] = "Title"
501 self.assertRaises(Exception,
502 lambda: self.RunStep(MergeToBranch, TagRevision, args))
503
504 def testReadAndPersistVersion(self):
505 self.WriteFakeVersionFile(build=5)
506 step = self.MakeStep()
507 step.ReadAndPersistVersion()
508 self.assertEquals("3", step["major"])
509 self.assertEquals("22", step["minor"])
510 self.assertEquals("5", step["build"])
511 self.assertEquals("0", step["patch"])
512
513 def testRegex(self):
514 self.assertEqual("(issue 321)",
515 re.sub(r"BUG=v8:(.*)$", r"(issue \1)", "BUG=v8:321"))
516 self.assertEqual("(Chromium issue 321)",
517 re.sub(r"BUG=(.*)$", r"(Chromium issue \1)", "BUG=321"))
518
519 cl = " too little\n\ttab\ttab\n too much\n trailing "
520 cl = MSub(r"\t", r" ", cl)
521 cl = MSub(r"^ {1,7}([^ ])", r" \1", cl)
522 cl = MSub(r"^ {9,80}([^ ])", r" \1", cl)
523 cl = MSub(r" +$", r"", cl)
524 self.assertEqual(" too little\n"
525 " tab tab\n"
526 " too much\n"
527 " trailing", cl)
528
529 self.assertEqual("//\n#define BUILD_NUMBER 3\n",
530 MSub(r"(?<=#define BUILD_NUMBER)(?P<space>\s+)\d*$",
531 r"\g<space>3",
532 "//\n#define BUILD_NUMBER 321\n"))
533
534 def testPreparePushRevision(self):
535 # Tests the default push hash used when the --revision option is not set.
536 self.Expect([
537 Cmd("git log -1 --format=%H HEAD", "push_hash")
538 ])
539
540 self.RunStep(PushToCandidates, PreparePushRevision)
541 self.assertEquals("push_hash", self._state["push_hash"])
542
543 def testPrepareChangeLog(self):
544 self.WriteFakeVersionFile()
545 TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
546
547 self.Expect([
548 Cmd("git log --format=%H 1234..push_hash", "rev1\nrev2\nrev3\nrev4"),
549 Cmd("git log -1 --format=%s rev1", "Title text 1"),
550 Cmd("git log -1 --format=%B rev1", "Title\n\nBUG=\nLOG=y\n"),
551 Cmd("git log -1 --format=%an rev1", "author1@chromium.org"),
552 Cmd("git log -1 --format=%s rev2", "Title text 2."),
553 Cmd("git log -1 --format=%B rev2", "Title\n\nBUG=123\nLOG= \n"),
554 Cmd("git log -1 --format=%an rev2", "author2@chromium.org"),
555 Cmd("git log -1 --format=%s rev3", "Title text 3"),
556 Cmd("git log -1 --format=%B rev3", "Title\n\nBUG=321\nLOG=true\n"),
557 Cmd("git log -1 --format=%an rev3", "author3@chromium.org"),
558 Cmd("git log -1 --format=%s rev4", "Title text 4"),
559 Cmd("git log -1 --format=%B rev4",
560 ("Title\n\nBUG=456\nLOG=Y\n\n"
561 "Review URL: https://codereview.chromium.org/9876543210\n")),
562 URL("https://codereview.chromium.org/9876543210/description",
563 "Title\n\nBUG=456\nLOG=N\n\n"),
564 Cmd("git log -1 --format=%an rev4", "author4@chromium.org"),
565 ])
566
567 self._state["last_push_master"] = "1234"
568 self._state["push_hash"] = "push_hash"
569 self._state["version"] = "3.22.5"
570 self.RunStep(PushToCandidates, PrepareChangeLog)
571
572 actual_cl = FileToText(TEST_CONFIG["CHANGELOG_ENTRY_FILE"])
573
574 expected_cl = """1999-07-31: Version 3.22.5
575
576 Title text 1.
577
578 Title text 3 (Chromium issue 321).
579
580 Performance and stability improvements on all platforms.
581 #
582 # The change log above is auto-generated. Please review if all relevant
583 # commit messages from the list below are included.
584 # All lines starting with # will be stripped.
585 #
586 # Title text 1.
587 # (author1@chromium.org)
588 #
589 # Title text 2 (Chromium issue 123).
590 # (author2@chromium.org)
591 #
592 # Title text 3 (Chromium issue 321).
593 # (author3@chromium.org)
594 #
595 # Title text 4 (Chromium issue 456).
596 # (author4@chromium.org)
597 #
598 #"""
599
600 self.assertEquals(expected_cl, actual_cl)
601
602 def testEditChangeLog(self):
603 TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
604 TextToFile(" New \n\tLines \n", TEST_CONFIG["CHANGELOG_ENTRY_FILE"])
605 os.environ["EDITOR"] = "vi"
606 self.Expect([
607 RL(""), # Open editor.
608 Cmd("vi %s" % TEST_CONFIG["CHANGELOG_ENTRY_FILE"], ""),
609 ])
610
611 self.RunStep(PushToCandidates, EditChangeLog)
612
613 self.assertEquals("New\n Lines",
614 FileToText(TEST_CONFIG["CHANGELOG_ENTRY_FILE"]))
615
616 TAGS = """
617 4425.0
618 0.0.0.0
619 3.9.6
620 3.22.4
621 test_tag
622 """
623
624 # Version as tag: 3.22.4.0. Version on master: 3.22.6.
625 # Make sure that the latest version is 3.22.6.0.
626 def testGetLatestVersion(self):
627 self.Expect([
628 Cmd("git tag", self.TAGS),
629 Cmd("git checkout -f origin/master -- src/version.cc",
630 "", cb=lambda: self.WriteFakeVersionFile(22, 6)),
631 ])
632
633 self.RunStep(PushToCandidates, GetLatestVersion)
634
635 self.assertEquals("3", self._state["latest_major"])
636 self.assertEquals("22", self._state["latest_minor"])
637 self.assertEquals("6", self._state["latest_build"])
638 self.assertEquals("0", self._state["latest_patch"])
639
640 def _TestSquashCommits(self, change_log, expected_msg):
641 TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
642 with open(TEST_CONFIG["CHANGELOG_ENTRY_FILE"], "w") as f:
643 f.write(change_log)
644
645 self.Expect([
646 Cmd("git diff origin/candidates hash1", "patch content"),
647 ])
648
649 self._state["push_hash"] = "hash1"
650 self._state["date"] = "1999-11-11"
651
652 self.RunStep(PushToCandidates, SquashCommits)
653 self.assertEquals(FileToText(TEST_CONFIG["COMMITMSG_FILE"]), expected_msg)
654
655 patch = FileToText(TEST_CONFIG["PATCH_FILE"])
656 self.assertTrue(re.search(r"patch content", patch))
657
658 def testSquashCommitsUnformatted(self):
659 change_log = """1999-11-11: Version 3.22.5
660
661 Log text 1.
662 Chromium issue 12345
663
664 Performance and stability improvements on all platforms.\n"""
665 commit_msg = """Version 3.22.5 (based on hash1)
666
667 Log text 1. Chromium issue 12345
668
669 Performance and stability improvements on all platforms."""
670 self._TestSquashCommits(change_log, commit_msg)
671
672 def testSquashCommitsFormatted(self):
673 change_log = """1999-11-11: Version 3.22.5
674
675 Long commit message that fills more than 80 characters (Chromium issue
676 12345).
677
678 Performance and stability improvements on all platforms.\n"""
679 commit_msg = """Version 3.22.5 (based on hash1)
680
681 Long commit message that fills more than 80 characters (Chromium issue 12345).
682
683 Performance and stability improvements on all platforms."""
684 self._TestSquashCommits(change_log, commit_msg)
685
686 def testSquashCommitsQuotationMarks(self):
687 change_log = """Line with "quotation marks".\n"""
688 commit_msg = """Line with "quotation marks"."""
689 self._TestSquashCommits(change_log, commit_msg)
690
691 def testBootstrapper(self):
692 work_dir = self.MakeEmptyTempDirectory()
693 class FakeScript(ScriptsBase):
694 def _Steps(self):
695 return []
696
697 # Use the test configuration without the fake testing default work dir.
698 fake_config = dict(TEST_CONFIG)
699 del(fake_config["DEFAULT_CWD"])
700
701 self.Expect([
702 Cmd("fetch v8", "", cwd=work_dir),
703 ])
704 FakeScript(fake_config, self).Run(["--work-dir", work_dir])
705
706 def _PushToCandidates(self, force=False, manual=False):
707 TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
708
709 # The version file on master has build level 5, while the version
710 # file from candidates has build level 4.
711 self.WriteFakeVersionFile(build=5)
712
713 TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
714 master_change_log = "2014-03-17: Sentinel\n"
715 TextToFile(master_change_log,
716 os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE))
717 os.environ["EDITOR"] = "vi"
718
719 commit_msg_squashed = """Version 3.22.5 (squashed - based on push_hash)
720
721 Log text 1 (issue 321).
722
723 Performance and stability improvements on all platforms."""
724
725 commit_msg = """Version 3.22.5 (based on push_hash)
726
727 Log text 1 (issue 321).
728
729 Performance and stability improvements on all platforms."""
730
731 def ResetChangeLog():
732 """On 'git co -b new_branch origin/candidates',
733 and 'git checkout -- ChangeLog',
734 the ChangLog will be reset to its content on candidates."""
735 candidates_change_log = """1999-04-05: Version 3.22.4
736
737 Performance and stability improvements on all platforms.\n"""
738 TextToFile(candidates_change_log,
739 os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE))
740
741 def ResetToCandidates():
742 ResetChangeLog()
743 self.WriteFakeVersionFile()
744
745 def CheckVersionCommit():
746 commit = FileToText(TEST_CONFIG["COMMITMSG_FILE"])
747 self.assertEquals(commit_msg, commit)
748 version = FileToText(
749 os.path.join(TEST_CONFIG["DEFAULT_CWD"], VERSION_FILE))
750 self.assertTrue(re.search(r"#define MINOR_VERSION\s+22", version))
751 self.assertTrue(re.search(r"#define BUILD_NUMBER\s+5", version))
752 self.assertFalse(re.search(r"#define BUILD_NUMBER\s+6", version))
753 self.assertTrue(re.search(r"#define PATCH_LEVEL\s+0", version))
754 self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version))
755
756 # Check that the change log on the candidates branch got correctly
757 # modified.
758 change_log = FileToText(
759 os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE))
760 self.assertEquals(
761 """1999-07-31: Version 3.22.5
762
763 Log text 1 (issue 321).
764
765 Performance and stability improvements on all platforms.
766
767
768 1999-04-05: Version 3.22.4
769
770 Performance and stability improvements on all platforms.\n""",
771 change_log)
772
773 force_flag = " -f" if not manual else ""
774 expectations = []
775 if not force:
776 expectations.append(Cmd("which vi", "/usr/bin/vi"))
777 expectations += [
778 Cmd("git status -s -uno", ""),
779 Cmd("git status -s -b -uno", "## some_branch\n"),
780 Cmd("git fetch", ""),
781 Cmd("git fetch origin +refs/tags/*:refs/tags/*", ""),
782 Cmd("git branch", " branch1\n* branch2\n"),
783 Cmd("git branch", " branch1\n* branch2\n"),
784 Cmd(("git new-branch %s --upstream origin/master" %
785 TEST_CONFIG["BRANCHNAME"]),
786 ""),
787 Cmd(("git log -1 --format=%H --grep="
788 "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\" "
789 "origin/candidates"), "hash2\n"),
790 Cmd("git log -1 hash2", "Log message\n"),
791 ]
792 if manual:
793 expectations.append(RL("Y")) # Confirm last push.
794 expectations += [
795 Cmd("git log -1 --format=%s hash2",
796 "Version 3.4.5 (based on abc3)\n"),
797 Cmd("git tag", self.TAGS),
798 Cmd("git checkout -f origin/master -- src/version.cc",
799 "", cb=self.WriteFakeVersionFile),
800 Cmd("git log --format=%H abc3..push_hash", "rev1\n"),
801 Cmd("git log -1 --format=%s rev1", "Log text 1.\n"),
802 Cmd("git log -1 --format=%B rev1", "Text\nLOG=YES\nBUG=v8:321\nText\n"),
803 Cmd("git log -1 --format=%an rev1", "author1@chromium.org\n"),
804 ]
805 if manual:
806 expectations.append(RL("")) # Open editor.
807 if not force:
808 expectations.append(
809 Cmd("vi %s" % TEST_CONFIG["CHANGELOG_ENTRY_FILE"], ""))
810 expectations += [
811 Cmd("git fetch", ""),
812 Cmd("git checkout -f origin/master", ""),
813 Cmd("git diff origin/candidates push_hash", "patch content\n"),
814 Cmd(("git new-branch %s --upstream origin/candidates" %
815 TEST_CONFIG["CANDIDATESBRANCH"]), "", cb=ResetToCandidates),
816 Cmd("git apply --index --reject \"%s\"" % TEST_CONFIG["PATCH_FILE"], ""),
817 Cmd("git checkout -f origin/candidates -- ChangeLog", "",
818 cb=ResetChangeLog),
819 Cmd("git checkout -f origin/candidates -- src/version.cc", "",
820 cb=self.WriteFakeVersionFile),
821 Cmd("git commit -am \"%s\"" % commit_msg_squashed, ""),
822 ]
823 if manual:
824 expectations.append(RL("Y")) # Sanity check.
825 expectations += [
826 Cmd("git cl land -f --bypass-hooks", ""),
827 Cmd("git checkout -f master", ""),
828 Cmd("git fetch", ""),
829 Cmd("git branch -D %s" % TEST_CONFIG["CANDIDATESBRANCH"], ""),
830 Cmd(("git new-branch %s --upstream origin/candidates" %
831 TEST_CONFIG["CANDIDATESBRANCH"]), "", cb=ResetToCandidates),
832 Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], "",
833 cb=CheckVersionCommit),
834 Cmd("git cl land -f --bypass-hooks", ""),
835 Cmd("git fetch", ""),
836 Cmd("git log -1 --format=%H --grep="
837 "\"Version 3.22.5 (based on push_hash)\""
838 " origin/candidates", "hsh_to_tag"),
839 Cmd("git tag 3.22.5 hsh_to_tag", ""),
840 Cmd("git push origin 3.22.5", ""),
841 Cmd("git checkout -f some_branch", ""),
842 Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
843 Cmd("git branch -D %s" % TEST_CONFIG["CANDIDATESBRANCH"], ""),
844 ]
845 self.Expect(expectations)
846
847 args = ["-a", "author@chromium.org", "--revision", "push_hash"]
848 if force: args.append("-f")
849 if manual: args.append("-m")
850 else: args += ["-r", "reviewer@chromium.org"]
851 PushToCandidates(TEST_CONFIG, self).Run(args)
852
853 cl = FileToText(os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE))
854 self.assertTrue(re.search(r"^\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl))
855 self.assertTrue(re.search(r" Log text 1 \(issue 321\).", cl))
856 self.assertTrue(re.search(r"1999\-04\-05: Version 3\.22\.4", cl))
857
858 # Note: The version file is on build number 5 again in the end of this test
859 # since the git command that merges to master is mocked out.
860
861 def testPushToCandidatesManual(self):
862 self._PushToCandidates(manual=True)
863
864 def testPushToCandidatesSemiAutomatic(self):
865 self._PushToCandidates()
866
867 def testPushToCandidatesForced(self):
868 self._PushToCandidates(force=True)
869
870 C_V8_22624_LOG = """V8 CL.
871
872 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22624 123
873
874 """
875
876 C_V8_123455_LOG = """V8 CL.
877
878 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@123455 123
879
880 """
881
882 C_V8_123456_LOG = """V8 CL.
883
884 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@123456 123
885
886 """
887
888 def testChromiumRoll(self):
889 googlers_mapping_py = "%s-mapping.py" % TEST_CONFIG["PERSISTFILE_BASENAME"]
890 with open(googlers_mapping_py, "w") as f:
891 f.write("""
892 def list_to_dict(entries):
893 return {"g_name@google.com": "c_name@chromium.org"}
894 def get_list():
895 pass""")
896
897 # Setup fake directory structures.
898 TEST_CONFIG["CHROMIUM"] = self.MakeEmptyTempDirectory()
899 TextToFile("", os.path.join(TEST_CONFIG["CHROMIUM"], ".git"))
900 chrome_dir = TEST_CONFIG["CHROMIUM"]
901 os.makedirs(os.path.join(chrome_dir, "v8"))
902
903 # Write fake deps file.
904 TextToFile("Some line\n \"v8_revision\": \"123444\",\n some line",
905 os.path.join(chrome_dir, "DEPS"))
906 def WriteDeps():
907 TextToFile("Some line\n \"v8_revision\": \"22624\",\n some line",
908 os.path.join(chrome_dir, "DEPS"))
909
910 expectations = [
911 Cmd("git fetch origin", ""),
912 Cmd(("git log -1 --format=%H --grep="
913 "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\" "
914 "origin/candidates"), "push_hash\n"),
915 Cmd("git log -1 --format=%s push_hash",
916 "Version 3.22.5 (based on bleeding_edge revision r22622)\n"),
917 URL("https://chromium-build.appspot.com/p/chromium/sheriff_v8.js",
918 "document.write('g_name')"),
919 Cmd("git status -s -uno", "", cwd=chrome_dir),
920 Cmd("git checkout -f master", "", cwd=chrome_dir),
921 Cmd("gclient sync --nohooks", "syncing...", cwd=chrome_dir),
922 Cmd("git pull", "", cwd=chrome_dir),
923 Cmd("git fetch origin", ""),
924 Cmd("git new-branch v8-roll-push_hash", "", cwd=chrome_dir),
925 Cmd("roll-dep v8 push_hash", "rolled", cb=WriteDeps, cwd=chrome_dir),
926 Cmd(("git commit -am \"Update V8 to version 3.22.5 "
927 "(based on bleeding_edge revision r22622).\n\n"
928 "Please reply to the V8 sheriff c_name@chromium.org in "
929 "case of problems.\n\nTBR=c_name@chromium.org\" "
930 "--author \"author@chromium.org <author@chromium.org>\""),
931 "", cwd=chrome_dir),
932 Cmd("git cl upload --send-mail --email \"author@chromium.org\" -f", "",
933 cwd=chrome_dir),
934 ]
935 self.Expect(expectations)
936
937 args = ["-a", "author@chromium.org", "-c", chrome_dir,
938 "--sheriff", "--googlers-mapping", googlers_mapping_py,
939 "-r", "reviewer@chromium.org"]
940 ChromiumRoll(TEST_CONFIG, self).Run(args)
941
942 deps = FileToText(os.path.join(chrome_dir, "DEPS"))
943 self.assertTrue(re.search("\"v8_revision\": \"22624\"", deps))
944
945 def testCheckLastPushRecently(self):
946 self.Expect([
947 Cmd(("git log -1 --format=%H --grep="
948 "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\" "
949 "origin/candidates"), "hash2\n"),
950 Cmd("git log -1 --format=%s hash2",
951 "Version 3.4.5 (based on abc123)\n"),
952 ])
953
954 self._state["candidate"] = "abc123"
955 self.assertEquals(0, self.RunStep(
956 auto_push.AutoPush, CheckLastPush, AUTO_PUSH_ARGS))
957
958 def testAutoPush(self):
959 TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
960
961 self.Expect([
962 Cmd("git status -s -uno", ""),
963 Cmd("git status -s -b -uno", "## some_branch\n"),
964 Cmd("git fetch", ""),
965 Cmd("git fetch origin +refs/heads/candidate:refs/heads/candidate", ""),
966 Cmd("git show-ref -s refs/heads/candidate", "abc123\n"),
967 Cmd(("git log -1 --format=%H --grep=\""
968 "^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\""
969 " origin/candidates"), "push_hash\n"),
970 Cmd("git log -1 --format=%s push_hash",
971 "Version 3.4.5 (based on abc101)\n"),
972 ])
973
974 auto_push.AutoPush(TEST_CONFIG, self).Run(AUTO_PUSH_ARGS + ["--push"])
975
976 state = json.loads(FileToText("%s-state.json"
977 % TEST_CONFIG["PERSISTFILE_BASENAME"]))
978
979 self.assertEquals("abc123", state["candidate"])
980
981 def testAutoRollExistingRoll(self):
982 self.Expect([
983 URL("https://codereview.chromium.org/search",
984 "owner=author%40chromium.org&limit=30&closed=3&format=json",
985 ("{\"results\": [{\"subject\": \"different\"},"
986 "{\"subject\": \"Update V8 to Version...\"}]}")),
987 ])
988
989 result = auto_roll.AutoRoll(TEST_CONFIG, self).Run(
990 AUTO_PUSH_ARGS + ["-c", TEST_CONFIG["CHROMIUM"]])
991 self.assertEquals(0, result)
992
993 # Snippet from the original DEPS file.
994 FAKE_DEPS = """
995 vars = {
996 "v8_revision": "abcd123455",
997 }
998 deps = {
999 "src/v8":
1000 (Var("googlecode_url") % "v8") + "/" + Var("v8_branch") + "@" +
1001 Var("v8_revision"),
1002 }
1003 """
1004
1005 def testAutoRollUpToDate(self):
1006 TEST_CONFIG["CHROMIUM"] = self.MakeEmptyTempDirectory()
1007 TextToFile(self.FAKE_DEPS, os.path.join(TEST_CONFIG["CHROMIUM"], "DEPS"))
1008 self.Expect([
1009 URL("https://codereview.chromium.org/search",
1010 "owner=author%40chromium.org&limit=30&closed=3&format=json",
1011 ("{\"results\": [{\"subject\": \"different\"}]}")),
1012 Cmd("git fetch", ""),
1013 Cmd(("git log -1 --format=%H --grep="
1014 "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\" "
1015 "origin/candidates"), "push_hash\n"),
1016 Cmd("git log -1 --format=%B push_hash", self.C_V8_22624_LOG),
1017 Cmd("git log -1 --format=%B abcd123455", self.C_V8_123455_LOG),
1018 ])
1019
1020 result = auto_roll.AutoRoll(TEST_CONFIG, self).Run(
1021 AUTO_PUSH_ARGS + ["-c", TEST_CONFIG["CHROMIUM"]])
1022 self.assertEquals(0, result)
1023
1024 def testAutoRoll(self):
1025 TEST_CONFIG["CHROMIUM"] = self.MakeEmptyTempDirectory()
1026 TextToFile(self.FAKE_DEPS, os.path.join(TEST_CONFIG["CHROMIUM"], "DEPS"))
1027 TEST_CONFIG["CLUSTERFUZZ_API_KEY_FILE"] = self.MakeEmptyTempFile()
1028 TextToFile("fake key", TEST_CONFIG["CLUSTERFUZZ_API_KEY_FILE"])
1029
1030 self.Expect([
1031 URL("https://codereview.chromium.org/search",
1032 "owner=author%40chromium.org&limit=30&closed=3&format=json",
1033 ("{\"results\": [{\"subject\": \"different\"}]}")),
1034 Cmd("git fetch", ""),
1035 Cmd(("git log -1 --format=%H --grep="
1036 "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\" "
1037 "origin/candidates"), "push_hash\n"),
1038 Cmd("git log -1 --format=%B push_hash", self.C_V8_123456_LOG),
1039 Cmd("git log -1 --format=%B abcd123455", self.C_V8_123455_LOG),
1040 ])
1041
1042 result = auto_roll.AutoRoll(TEST_CONFIG, self).Run(
1043 AUTO_PUSH_ARGS + ["-c", TEST_CONFIG["CHROMIUM"], "--roll"])
1044 self.assertEquals(0, result)
1045
1046 def testMergeToBranch(self):
1047 TEST_CONFIG["ALREADY_MERGING_SENTINEL_FILE"] = self.MakeEmptyTempFile()
1048 TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
1049 self.WriteFakeVersionFile(build=5)
1050 os.environ["EDITOR"] = "vi"
1051 extra_patch = self.MakeEmptyTempFile()
1052
1053 def VerifyPatch(patch):
1054 return lambda: self.assertEquals(patch,
1055 FileToText(TEST_CONFIG["TEMPORARY_PATCH_FILE"]))
1056
1057 msg = """Version 3.22.5.1 (cherry-pick)
1058
1059 Merged ab12345
1060 Merged ab23456
1061 Merged ab34567
1062 Merged ab45678
1063 Merged ab56789
1064
1065 Title4
1066
1067 Title2
1068
1069 Title3
1070
1071 Title1
1072
1073 Revert "Something"
1074
1075 BUG=123,234,345,456,567,v8:123
1076 LOG=N
1077 """
1078
1079 def VerifyLand():
1080 commit = FileToText(TEST_CONFIG["COMMITMSG_FILE"])
1081 self.assertEquals(msg, commit)
1082 version = FileToText(
1083 os.path.join(TEST_CONFIG["DEFAULT_CWD"], VERSION_FILE))
1084 self.assertTrue(re.search(r"#define MINOR_VERSION\s+22", version))
1085 self.assertTrue(re.search(r"#define BUILD_NUMBER\s+5", version))
1086 self.assertTrue(re.search(r"#define PATCH_LEVEL\s+1", version))
1087 self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version))
1088
1089 self.Expect([
1090 Cmd("git status -s -uno", ""),
1091 Cmd("git status -s -b -uno", "## some_branch\n"),
1092 Cmd("git fetch", ""),
1093 Cmd("git branch", " branch1\n* branch2\n"),
1094 Cmd("git new-branch %s --upstream origin/candidates" %
1095 TEST_CONFIG["BRANCHNAME"], ""),
1096 Cmd(("git log --format=%H --grep=\"Port ab12345\" "
1097 "--reverse origin/master"),
1098 "ab45678\nab23456"),
1099 Cmd("git log -1 --format=%s ab45678", "Title1"),
1100 Cmd("git log -1 --format=%s ab23456", "Title2"),
1101 Cmd(("git log --format=%H --grep=\"Port ab23456\" "
1102 "--reverse origin/master"),
1103 ""),
1104 Cmd(("git log --format=%H --grep=\"Port ab34567\" "
1105 "--reverse origin/master"),
1106 "ab56789"),
1107 Cmd("git log -1 --format=%s ab56789", "Title3"),
1108 RL("Y"), # Automatically add corresponding ports (ab34567, ab56789)?
1109 # Simulate git being down which stops the script.
1110 Cmd("git log -1 --format=%s ab12345", None),
1111 # Restart script in the failing step.
1112 Cmd("git log -1 --format=%s ab12345", "Title4"),
1113 Cmd("git log -1 --format=%s ab23456", "Title2"),
1114 Cmd("git log -1 --format=%s ab34567", "Title3"),
1115 Cmd("git log -1 --format=%s ab45678", "Title1"),
1116 Cmd("git log -1 --format=%s ab56789", "Revert \"Something\""),
1117 Cmd("git log -1 ab12345", "Title4\nBUG=123\nBUG=234"),
1118 Cmd("git log -1 ab23456", "Title2\n BUG = v8:123,345"),
1119 Cmd("git log -1 ab34567", "Title3\nLOG=n\nBUG=567, 456"),
1120 Cmd("git log -1 ab45678", "Title1\nBUG="),
1121 Cmd("git log -1 ab56789", "Revert \"Something\"\nBUG=none"),
1122 Cmd("git log -1 -p ab12345", "patch4"),
1123 Cmd(("git apply --index --reject \"%s\"" %
1124 TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1125 "", cb=VerifyPatch("patch4")),
1126 Cmd("git log -1 -p ab23456", "patch2"),
1127 Cmd(("git apply --index --reject \"%s\"" %
1128 TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1129 "", cb=VerifyPatch("patch2")),
1130 Cmd("git log -1 -p ab34567", "patch3"),
1131 Cmd(("git apply --index --reject \"%s\"" %
1132 TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1133 "", cb=VerifyPatch("patch3")),
1134 Cmd("git log -1 -p ab45678", "patch1"),
1135 Cmd(("git apply --index --reject \"%s\"" %
1136 TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1137 "", cb=VerifyPatch("patch1")),
1138 Cmd("git log -1 -p ab56789", "patch5\n"),
1139 Cmd(("git apply --index --reject \"%s\"" %
1140 TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1141 "", cb=VerifyPatch("patch5\n")),
1142 Cmd("git apply --index --reject \"%s\"" % extra_patch, ""),
1143 RL("Y"), # Automatically increment patch level?
1144 Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], ""),
1145 RL("reviewer@chromium.org"), # V8 reviewer.
1146 Cmd("git cl upload --send-mail -r \"reviewer@chromium.org\" "
1147 "--bypass-hooks --cc \"ulan@chromium.org\"", ""),
1148 Cmd("git checkout -f %s" % TEST_CONFIG["BRANCHNAME"], ""),
1149 RL("LGTM"), # Enter LGTM for V8 CL.
1150 Cmd("git cl presubmit", "Presubmit successfull\n"),
1151 Cmd("git cl land -f --bypass-hooks", "Closing issue\n",
1152 cb=VerifyLand),
1153 Cmd("git fetch", ""),
1154 Cmd("git log -1 --format=%H --grep=\""
1155 "Version 3.22.5.1 (cherry-pick)"
1156 "\" origin/candidates",
1157 ""),
1158 Cmd("git fetch", ""),
1159 Cmd("git log -1 --format=%H --grep=\""
1160 "Version 3.22.5.1 (cherry-pick)"
1161 "\" origin/candidates",
1162 "hsh_to_tag"),
1163 Cmd("git tag 3.22.5.1 hsh_to_tag", ""),
1164 Cmd("git push origin 3.22.5.1", ""),
1165 Cmd("git checkout -f some_branch", ""),
1166 Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
1167 ])
1168
1169 # ab12345 and ab34567 are patches. ab23456 (included) and ab45678 are the
1170 # MIPS ports of ab12345. ab56789 is the MIPS port of ab34567.
1171 args = ["-f", "-p", extra_patch, "--branch", "candidates",
1172 "ab12345", "ab23456", "ab34567"]
1173
1174 # The first run of the script stops because of git being down.
1175 self.assertRaises(GitFailedException,
1176 lambda: MergeToBranch(TEST_CONFIG, self).Run(args))
1177
1178 # Test that state recovery after restarting the script works.
1179 args += ["-s", "4"]
1180 MergeToBranch(TEST_CONFIG, self).Run(args)
1181
1182 def testReleases(self):
1183 c_hash2_commit_log = """Revert something.
1184
1185 BUG=12345
1186
1187 Reason:
1188 > Some reason.
1189 > Cr-Commit-Position: refs/heads/master@{#12345}
1190 > git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12345 003-1c4
1191
1192 Review URL: https://codereview.chromium.org/12345
1193
1194 Cr-Commit-Position: refs/heads/master@{#4567}
1195 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4567 0039-1c4b
1196
1197 """
1198 c_hash3_commit_log = """Simple.
1199
1200 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3456 0039-1c4b
1201
1202 """
1203 c_hash_234_commit_log = """Version 3.3.1.1 (cherry-pick).
1204
1205 Merged abc12.
1206
1207 Review URL: fake.com
1208
1209 Cr-Commit-Position: refs/heads/candidates@{#234}
1210 """
1211 c_hash_123_commit_log = """Version 3.3.1.0
1212
1213 git-svn-id: googlecode@123 0039-1c4b
1214 """
1215 c_hash_345_commit_log = """Version 3.4.0.
1216
1217 Cr-Commit-Position: refs/heads/candidates@{#345}
1218 """
1219
1220 json_output = self.MakeEmptyTempFile()
1221 csv_output = self.MakeEmptyTempFile()
1222 self.WriteFakeVersionFile()
1223
1224 TEST_CONFIG["CHROMIUM"] = self.MakeEmptyTempDirectory()
1225 chrome_dir = TEST_CONFIG["CHROMIUM"]
1226 chrome_v8_dir = os.path.join(chrome_dir, "v8")
1227 os.makedirs(chrome_v8_dir)
1228 def WriteDEPS(revision):
1229 TextToFile("Line\n \"v8_revision\": \"%s\",\n line\n" % revision,
1230 os.path.join(chrome_dir, "DEPS"))
1231 WriteDEPS(567)
1232
1233 def ResetVersion(minor, build, patch=0):
1234 return lambda: self.WriteFakeVersionFile(minor=minor,
1235 build=build,
1236 patch=patch)
1237
1238 def ResetDEPS(revision):
1239 return lambda: WriteDEPS(revision)
1240
1241 self.Expect([
1242 Cmd("git status -s -uno", ""),
1243 Cmd("git status -s -b -uno", "## some_branch\n"),
1244 Cmd("git fetch", ""),
1245 Cmd("git branch", " branch1\n* branch2\n"),
1246 Cmd("git new-branch %s" % TEST_CONFIG["BRANCHNAME"], ""),
1247 Cmd("git branch -r", " branch-heads/3.21\n branch-heads/3.3\n"),
1248 Cmd("git reset --hard branch-heads/3.3", ""),
1249 Cmd("git log --format=%H", "hash1\nhash_234"),
1250 Cmd("git diff --name-only hash1 hash1^", ""),
1251 Cmd("git diff --name-only hash_234 hash_234^", VERSION_FILE),
1252 Cmd("git checkout -f hash_234 -- %s" % VERSION_FILE, "",
1253 cb=ResetVersion(3, 1, 1)),
1254 Cmd("git log -1 --format=%B hash_234", c_hash_234_commit_log),
1255 Cmd("git log -1 --format=%s hash_234", ""),
1256 Cmd("git log -1 --format=%B hash_234", c_hash_234_commit_log),
1257 Cmd("git log -1 --format=%ci hash_234", "18:15"),
1258 Cmd("git checkout -f HEAD -- %s" % VERSION_FILE, "",
1259 cb=ResetVersion(22, 5)),
1260 Cmd("git reset --hard branch-heads/3.21", ""),
1261 Cmd("git log --format=%H", "hash_123\nhash4\nhash5\n"),
1262 Cmd("git diff --name-only hash_123 hash_123^", VERSION_FILE),
1263 Cmd("git checkout -f hash_123 -- %s" % VERSION_FILE, "",
1264 cb=ResetVersion(21, 2)),
1265 Cmd("git log -1 --format=%B hash_123", c_hash_123_commit_log),
1266 Cmd("git log -1 --format=%s hash_123", ""),
1267 Cmd("git log -1 --format=%B hash_123", c_hash_123_commit_log),
1268 Cmd("git log -1 --format=%ci hash_123", "03:15"),
1269 Cmd("git checkout -f HEAD -- %s" % VERSION_FILE, "",
1270 cb=ResetVersion(22, 5)),
1271 Cmd("git reset --hard origin/candidates", ""),
1272 Cmd("git log --format=%H", "hash_345\n"),
1273 Cmd("git diff --name-only hash_345 hash_345^", VERSION_FILE),
1274 Cmd("git checkout -f hash_345 -- %s" % VERSION_FILE, "",
1275 cb=ResetVersion(22, 3)),
1276 Cmd("git log -1 --format=%B hash_345", c_hash_345_commit_log),
1277 Cmd("git log -1 --format=%s hash_345", ""),
1278 Cmd("git log -1 --format=%B hash_345", c_hash_345_commit_log),
1279 Cmd("git log -1 --format=%ci hash_345", ""),
1280 Cmd("git checkout -f HEAD -- %s" % VERSION_FILE, "",
1281 cb=ResetVersion(22, 5)),
1282 Cmd("git reset --hard origin/master", ""),
1283 Cmd("git status -s -uno", "", cwd=chrome_dir),
1284 Cmd("git checkout -f master", "", cwd=chrome_dir),
1285 Cmd("git pull", "", cwd=chrome_dir),
1286 Cmd("git new-branch %s" % TEST_CONFIG["BRANCHNAME"], "",
1287 cwd=chrome_dir),
1288 Cmd("git fetch origin", "", cwd=chrome_v8_dir),
1289 Cmd("git log --format=%H --grep=\"V8\"", "c_hash1\nc_hash2\nc_hash3\n",
1290 cwd=chrome_dir),
1291 Cmd("git diff --name-only c_hash1 c_hash1^", "", cwd=chrome_dir),
1292 Cmd("git diff --name-only c_hash2 c_hash2^", "DEPS", cwd=chrome_dir),
1293 Cmd("git checkout -f c_hash2 -- DEPS", "",
1294 cb=ResetDEPS("0123456789012345678901234567890123456789"),
1295 cwd=chrome_dir),
1296 Cmd("git log -1 --format=%B c_hash2", c_hash2_commit_log,
1297 cwd=chrome_dir),
1298 Cmd("git log -1 --format=%B 0123456789012345678901234567890123456789",
1299 self.C_V8_22624_LOG, cwd=chrome_v8_dir),
1300 Cmd("git diff --name-only c_hash3 c_hash3^", "DEPS", cwd=chrome_dir),
1301 Cmd("git checkout -f c_hash3 -- DEPS", "", cb=ResetDEPS(345),
1302 cwd=chrome_dir),
1303 Cmd("git log -1 --format=%B c_hash3", c_hash3_commit_log,
1304 cwd=chrome_dir),
1305 Cmd("git checkout -f HEAD -- DEPS", "", cb=ResetDEPS(567),
1306 cwd=chrome_dir),
1307 Cmd("git branch -r", " weird/123\n branch-heads/7\n", cwd=chrome_dir),
1308 Cmd("git checkout -f branch-heads/7 -- DEPS", "", cb=ResetDEPS(345),
1309 cwd=chrome_dir),
1310 Cmd("git checkout -f HEAD -- DEPS", "", cb=ResetDEPS(567),
1311 cwd=chrome_dir),
1312 Cmd("git checkout -f master", "", cwd=chrome_dir),
1313 Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], "", cwd=chrome_dir),
1314 Cmd("git checkout -f some_branch", ""),
1315 Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
1316 ])
1317
1318 args = ["-c", TEST_CONFIG["CHROMIUM"],
1319 "--json", json_output,
1320 "--csv", csv_output,
1321 "--max-releases", "1"]
1322 Releases(TEST_CONFIG, self).Run(args)
1323
1324 # Check expected output.
1325 csv = ("3.22.3,candidates,345,3456:4566,\r\n"
1326 "3.21.2,3.21,123,,\r\n"
1327 "3.3.1.1,3.3,234,,abc12\r\n")
1328 self.assertEquals(csv, FileToText(csv_output))
1329
1330 expected_json = [
1331 {
1332 "revision": "345",
1333 "revision_git": "hash_345",
1334 "bleeding_edge": "",
1335 "bleeding_edge_git": "",
1336 "patches_merged": "",
1337 "version": "3.22.3",
1338 "chromium_revision": "3456:4566",
1339 "branch": "candidates",
1340 "review_link": "",
1341 "date": "",
1342 "chromium_branch": "7",
1343 "revision_link": "https://code.google.com/p/v8/source/detail?r=345",
1344 },
1345 {
1346 "revision": "123",
1347 "revision_git": "hash_123",
1348 "patches_merged": "",
1349 "bleeding_edge": "",
1350 "bleeding_edge_git": "",
1351 "version": "3.21.2",
1352 "chromium_revision": "",
1353 "branch": "3.21",
1354 "review_link": "",
1355 "date": "03:15",
1356 "chromium_branch": "",
1357 "revision_link": "https://code.google.com/p/v8/source/detail?r=123",
1358 },
1359 {
1360 "revision": "234",
1361 "revision_git": "hash_234",
1362 "patches_merged": "abc12",
1363 "bleeding_edge": "",
1364 "bleeding_edge_git": "",
1365 "version": "3.3.1.1",
1366 "chromium_revision": "",
1367 "branch": "3.3",
1368 "review_link": "fake.com",
1369 "date": "18:15",
1370 "chromium_branch": "",
1371 "revision_link": "https://code.google.com/p/v8/source/detail?r=234",
1372 },
1373 ]
1374 self.assertEquals(expected_json, json.loads(FileToText(json_output)))
1375
1376
1377 class SystemTest(unittest.TestCase):
1378 def testReload(self):
1379 options = ScriptsBase(
1380 TEST_CONFIG, DEFAULT_SIDE_EFFECT_HANDLER, {}).MakeOptions([])
1381 step = MakeStep(step_class=PrepareChangeLog, number=0, state={}, config={},
1382 options=options,
1383 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER)
1384 body = step.Reload(
1385 """------------------------------------------------------------------------
1386 r17997 | machenbach@chromium.org | 2013-11-22 11:04:04 +0100 (...) | 6 lines
1387
1388 Prepare push to trunk. Now working on version 3.23.11.
1389
1390 R=danno@chromium.org
1391
1392 Review URL: https://codereview.chromium.org/83173002
1393
1394 ------------------------------------------------------------------------""")
1395 self.assertEquals(
1396 """Prepare push to trunk. Now working on version 3.23.11.
1397
1398 R=danno@chromium.org
1399
1400 Committed: https://code.google.com/p/v8/source/detail?r=17997""", body)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698