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