Upstream version 11.40.277.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 fetch", ""),
450       Cmd("git svn fetch", ""),
451       Cmd("git branch", "  branch1\n* %s" % TEST_CONFIG["BRANCHNAME"]),
452       RL("Y"),
453       Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
454     ])
455     self.MakeStep().CommonPrepare()
456     self.MakeStep().PrepareBranch()
457     self.assertEquals("some_branch", self._state["current_branch"])
458
459   def testCommonPrepareNoConfirm(self):
460     self.Expect([
461       Cmd("git status -s -uno", ""),
462       Cmd("git status -s -b -uno", "## some_branch"),
463       Cmd("git fetch", ""),
464       Cmd("git svn fetch", ""),
465       Cmd("git branch", "  branch1\n* %s" % TEST_CONFIG["BRANCHNAME"]),
466       RL("n"),
467     ])
468     self.MakeStep().CommonPrepare()
469     self.assertRaises(Exception, self.MakeStep().PrepareBranch)
470     self.assertEquals("some_branch", self._state["current_branch"])
471
472   def testCommonPrepareDeleteBranchFailure(self):
473     self.Expect([
474       Cmd("git status -s -uno", ""),
475       Cmd("git status -s -b -uno", "## some_branch"),
476       Cmd("git fetch", ""),
477       Cmd("git svn fetch", ""),
478       Cmd("git branch", "  branch1\n* %s" % TEST_CONFIG["BRANCHNAME"]),
479       RL("Y"),
480       Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], None),
481     ])
482     self.MakeStep().CommonPrepare()
483     self.assertRaises(Exception, self.MakeStep().PrepareBranch)
484     self.assertEquals("some_branch", self._state["current_branch"])
485
486   def testInitialEnvironmentChecks(self):
487     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
488     os.environ["EDITOR"] = "vi"
489     self.Expect([
490       Cmd("which vi", "/usr/bin/vi"),
491     ])
492     self.MakeStep().InitialEnvironmentChecks(TEST_CONFIG["DEFAULT_CWD"])
493
494   def testTagTimeout(self):
495     self.Expect([
496       Cmd("git fetch", ""),
497       Cmd("git log -1 --format=%H --grep=\"Title\" origin/candidates", ""),
498       Cmd("git fetch", ""),
499       Cmd("git log -1 --format=%H --grep=\"Title\" origin/candidates", ""),
500       Cmd("git fetch", ""),
501       Cmd("git log -1 --format=%H --grep=\"Title\" origin/candidates", ""),
502       Cmd("git fetch", ""),
503       Cmd("git log -1 --format=%H --grep=\"Title\" origin/candidates", ""),
504     ])
505     args = ["--branch", "candidates", "--vc-interface", "git_read_svn_write",
506             "12345"]
507     self._state["version"] = "tag_name"
508     self._state["commit_title"] = "Title"
509     self.assertRaises(Exception,
510         lambda: self.RunStep(MergeToBranch, TagRevision, args))
511
512   def testReadAndPersistVersion(self):
513     self.WriteFakeVersionFile(build=5)
514     step = self.MakeStep()
515     step.ReadAndPersistVersion()
516     self.assertEquals("3", step["major"])
517     self.assertEquals("22", step["minor"])
518     self.assertEquals("5", step["build"])
519     self.assertEquals("0", step["patch"])
520
521   def testRegex(self):
522     self.assertEqual("(issue 321)",
523                      re.sub(r"BUG=v8:(.*)$", r"(issue \1)", "BUG=v8:321"))
524     self.assertEqual("(Chromium issue 321)",
525                      re.sub(r"BUG=(.*)$", r"(Chromium issue \1)", "BUG=321"))
526
527     cl = "  too little\n\ttab\ttab\n         too much\n        trailing  "
528     cl = MSub(r"\t", r"        ", cl)
529     cl = MSub(r"^ {1,7}([^ ])", r"        \1", cl)
530     cl = MSub(r"^ {9,80}([^ ])", r"        \1", cl)
531     cl = MSub(r" +$", r"", cl)
532     self.assertEqual("        too little\n"
533                      "        tab        tab\n"
534                      "        too much\n"
535                      "        trailing", cl)
536
537     self.assertEqual("//\n#define BUILD_NUMBER  3\n",
538                      MSub(r"(?<=#define BUILD_NUMBER)(?P<space>\s+)\d*$",
539                           r"\g<space>3",
540                           "//\n#define BUILD_NUMBER  321\n"))
541
542   def testPreparePushRevision(self):
543     # Tests the default push hash used when the --revision option is not set.
544     self.Expect([
545       Cmd("git log -1 --format=%H HEAD", "push_hash")
546     ])
547
548     self.RunStep(PushToTrunk, PreparePushRevision)
549     self.assertEquals("push_hash", self._state["push_hash"])
550
551   def testPrepareChangeLog(self):
552     self.WriteFakeVersionFile()
553     TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
554
555     self.Expect([
556       Cmd("git log --format=%H 1234..push_hash", "rev1\nrev2\nrev3\nrev4"),
557       Cmd("git log -1 --format=%s rev1", "Title text 1"),
558       Cmd("git log -1 --format=%B rev1", "Title\n\nBUG=\nLOG=y\n"),
559       Cmd("git log -1 --format=%an rev1", "author1@chromium.org"),
560       Cmd("git log -1 --format=%s rev2", "Title text 2."),
561       Cmd("git log -1 --format=%B rev2", "Title\n\nBUG=123\nLOG= \n"),
562       Cmd("git log -1 --format=%an rev2", "author2@chromium.org"),
563       Cmd("git log -1 --format=%s rev3", "Title text 3"),
564       Cmd("git log -1 --format=%B rev3", "Title\n\nBUG=321\nLOG=true\n"),
565       Cmd("git log -1 --format=%an rev3", "author3@chromium.org"),
566       Cmd("git log -1 --format=%s rev4", "Title text 4"),
567       Cmd("git log -1 --format=%B rev4",
568        ("Title\n\nBUG=456\nLOG=Y\n\n"
569         "Review URL: https://codereview.chromium.org/9876543210\n")),
570       URL("https://codereview.chromium.org/9876543210/description",
571           "Title\n\nBUG=456\nLOG=N\n\n"),
572       Cmd("git log -1 --format=%an rev4", "author4@chromium.org"),
573     ])
574
575     self._state["last_push_bleeding_edge"] = "1234"
576     self._state["push_hash"] = "push_hash"
577     self._state["version"] = "3.22.5"
578     self.RunStep(PushToTrunk, PrepareChangeLog)
579
580     actual_cl = FileToText(TEST_CONFIG["CHANGELOG_ENTRY_FILE"])
581
582     expected_cl = """1999-07-31: Version 3.22.5
583
584         Title text 1.
585
586         Title text 3 (Chromium issue 321).
587
588         Performance and stability improvements on all platforms.
589 #
590 # The change log above is auto-generated. Please review if all relevant
591 # commit messages from the list below are included.
592 # All lines starting with # will be stripped.
593 #
594 #       Title text 1.
595 #       (author1@chromium.org)
596 #
597 #       Title text 2 (Chromium issue 123).
598 #       (author2@chromium.org)
599 #
600 #       Title text 3 (Chromium issue 321).
601 #       (author3@chromium.org)
602 #
603 #       Title text 4 (Chromium issue 456).
604 #       (author4@chromium.org)
605 #
606 #"""
607
608     self.assertEquals(expected_cl, actual_cl)
609
610   def testEditChangeLog(self):
611     TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
612     TextToFile("  New  \n\tLines  \n", TEST_CONFIG["CHANGELOG_ENTRY_FILE"])
613     os.environ["EDITOR"] = "vi"
614     self.Expect([
615       RL(""),  # Open editor.
616       Cmd("vi %s" % TEST_CONFIG["CHANGELOG_ENTRY_FILE"], ""),
617     ])
618
619     self.RunStep(PushToTrunk, EditChangeLog)
620
621     self.assertEquals("New\n        Lines",
622                       FileToText(TEST_CONFIG["CHANGELOG_ENTRY_FILE"]))
623
624   # Version on trunk: 3.22.4.0. Version on master (bleeding_edge): 3.22.6.
625   # Make sure that the increment is 3.22.7.0.
626   def testIncrementVersion(self):
627     self.WriteFakeVersionFile()
628     self._state["last_push_trunk"] = "hash1"
629     self._state["latest_build"] = "6"
630     self._state["latest_version"] = "3.22.6.0"
631
632     self.Expect([
633       Cmd("git checkout -f hash1 -- src/version.cc", ""),
634       Cmd("git checkout -f origin/master -- src/version.cc",
635           "", cb=lambda: self.WriteFakeVersionFile(22, 6)),
636       RL("Y"),  # Increment build number.
637     ])
638
639     self.RunStep(PushToTrunk, IncrementVersion)
640
641     self.assertEquals("3", self._state["new_major"])
642     self.assertEquals("22", self._state["new_minor"])
643     self.assertEquals("7", self._state["new_build"])
644     self.assertEquals("0", self._state["new_patch"])
645
646   def _TestSquashCommits(self, change_log, expected_msg):
647     TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
648     with open(TEST_CONFIG["CHANGELOG_ENTRY_FILE"], "w") as f:
649       f.write(change_log)
650
651     self.Expect([
652       Cmd("git diff origin/candidates hash1", "patch content"),
653     ])
654
655     self._state["push_hash"] = "hash1"
656     self._state["date"] = "1999-11-11"
657
658     self.RunStep(PushToTrunk, SquashCommits)
659     self.assertEquals(FileToText(TEST_CONFIG["COMMITMSG_FILE"]), expected_msg)
660
661     patch = FileToText(TEST_CONFIG["PATCH_FILE"])
662     self.assertTrue(re.search(r"patch content", patch))
663
664   def testSquashCommitsUnformatted(self):
665     change_log = """1999-11-11: Version 3.22.5
666
667         Log text 1.
668         Chromium issue 12345
669
670         Performance and stability improvements on all platforms.\n"""
671     commit_msg = """Version 3.22.5 (based on hash1)
672
673 Log text 1. Chromium issue 12345
674
675 Performance and stability improvements on all platforms."""
676     self._TestSquashCommits(change_log, commit_msg)
677
678   def testSquashCommitsFormatted(self):
679     change_log = """1999-11-11: Version 3.22.5
680
681         Long commit message that fills more than 80 characters (Chromium issue
682         12345).
683
684         Performance and stability improvements on all platforms.\n"""
685     commit_msg = """Version 3.22.5 (based on hash1)
686
687 Long commit message that fills more than 80 characters (Chromium issue 12345).
688
689 Performance and stability improvements on all platforms."""
690     self._TestSquashCommits(change_log, commit_msg)
691
692   def testSquashCommitsQuotationMarks(self):
693     change_log = """Line with "quotation marks".\n"""
694     commit_msg = """Line with "quotation marks"."""
695     self._TestSquashCommits(change_log, commit_msg)
696
697   def testBootstrapper(self):
698     work_dir = self.MakeEmptyTempDirectory()
699     class FakeScript(ScriptsBase):
700       def _Steps(self):
701         return []
702
703     # Use the test configuration without the fake testing default work dir.
704     fake_config = dict(TEST_CONFIG)
705     del(fake_config["DEFAULT_CWD"])
706
707     self.Expect([
708       Cmd("fetch v8", "", cwd=work_dir),
709     ])
710     FakeScript(fake_config, self).Run(["--work-dir", work_dir])
711
712   def _PushToTrunk(self, force=False, manual=False):
713     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
714
715     # The version file on bleeding edge has build level 5, while the version
716     # file from trunk has build level 4.
717     self.WriteFakeVersionFile(build=5)
718
719     TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
720     TEST_CONFIG["CHANGELOG_FILE"] = self.MakeEmptyTempFile()
721     bleeding_edge_change_log = "2014-03-17: Sentinel\n"
722     TextToFile(bleeding_edge_change_log, TEST_CONFIG["CHANGELOG_FILE"])
723     os.environ["EDITOR"] = "vi"
724
725     def ResetChangeLog():
726       """On 'git co -b new_branch svn/trunk', and 'git checkout -- ChangeLog',
727       the ChangLog will be reset to its content on trunk."""
728       trunk_change_log = """1999-04-05: Version 3.22.4
729
730         Performance and stability improvements on all platforms.\n"""
731       TextToFile(trunk_change_log, TEST_CONFIG["CHANGELOG_FILE"])
732
733     def ResetToTrunk():
734       ResetChangeLog()
735       self.WriteFakeVersionFile()
736
737     def CheckSVNCommit():
738       commit = FileToText(TEST_CONFIG["COMMITMSG_FILE"])
739       self.assertEquals(
740 """Version 3.22.5 (based on push_hash)
741
742 Log text 1 (issue 321).
743
744 Performance and stability improvements on all platforms.""", commit)
745       version = FileToText(
746           os.path.join(TEST_CONFIG["DEFAULT_CWD"], VERSION_FILE))
747       self.assertTrue(re.search(r"#define MINOR_VERSION\s+22", version))
748       self.assertTrue(re.search(r"#define BUILD_NUMBER\s+5", version))
749       self.assertFalse(re.search(r"#define BUILD_NUMBER\s+6", version))
750       self.assertTrue(re.search(r"#define PATCH_LEVEL\s+0", version))
751       self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version))
752
753       # Check that the change log on the trunk branch got correctly modified.
754       change_log = FileToText(TEST_CONFIG["CHANGELOG_FILE"])
755       self.assertEquals(
756 """1999-07-31: Version 3.22.5
757
758         Log text 1 (issue 321).
759
760         Performance and stability improvements on all platforms.
761
762
763 1999-04-05: Version 3.22.4
764
765         Performance and stability improvements on all platforms.\n""",
766           change_log)
767
768     force_flag = " -f" if not manual else ""
769     expectations = []
770     if not force:
771       expectations.append(Cmd("which vi", "/usr/bin/vi"))
772     expectations += [
773       Cmd("git status -s -uno", ""),
774       Cmd("git status -s -b -uno", "## some_branch\n"),
775       Cmd("git fetch", ""),
776       Cmd("git svn fetch", ""),
777       Cmd("git branch", "  branch1\n* branch2\n"),
778       Cmd("git branch", "  branch1\n* branch2\n"),
779       Cmd(("git new-branch %s --upstream origin/master" %
780            TEST_CONFIG["BRANCHNAME"]),
781           ""),
782       Cmd(("git log -1 --format=%H --grep="
783            "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\" "
784            "origin/candidates"), "hash2\n"),
785       Cmd("git log -1 hash2", "Log message\n"),
786     ]
787     if manual:
788       expectations.append(RL("Y"))  # Confirm last push.
789     expectations += [
790       Cmd("git log -1 --format=%s hash2",
791        "Version 3.4.5 (based on abc3)\n"),
792       Cmd("git checkout -f origin/master -- src/version.cc",
793           "", cb=self.WriteFakeVersionFile),
794       Cmd("git checkout -f hash2 -- src/version.cc", "",
795           cb=self.WriteFakeVersionFile),
796     ]
797     if manual:
798       expectations.append(RL(""))  # Increment build number.
799     expectations += [
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 svn fetch", "fetch result\n"),
813       Cmd("git checkout -f origin/master", ""),
814       Cmd("git diff origin/candidates push_hash", "patch content\n"),
815       Cmd(("git new-branch %s --upstream origin/candidates" %
816            TEST_CONFIG["TRUNKBRANCH"]), "", cb=ResetToTrunk),
817       Cmd("git apply --index --reject \"%s\"" % TEST_CONFIG["PATCH_FILE"], ""),
818       Cmd(("git checkout -f origin/candidates -- %s" %
819            TEST_CONFIG["CHANGELOG_FILE"]), "",
820           cb=ResetChangeLog),
821       Cmd("git checkout -f origin/candidates -- src/version.cc", "",
822           cb=self.WriteFakeVersionFile),
823       Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], "",
824           cb=CheckSVNCommit),
825     ]
826     if manual:
827       expectations.append(RL("Y"))  # Sanity check.
828     expectations += [
829       Cmd("git svn dcommit 2>&1", ""),
830       Cmd("git fetch", ""),
831       Cmd("git log -1 --format=%H --grep="
832           "\"Version 3.22.5 (based on push_hash)\""
833           " origin/candidates", "hsh_to_tag"),
834       Cmd("git tag 3.22.5 hsh_to_tag", ""),
835       Cmd("git push origin 3.22.5", ""),
836       Cmd("git checkout -f some_branch", ""),
837       Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
838       Cmd("git branch -D %s" % TEST_CONFIG["TRUNKBRANCH"], ""),
839     ]
840     self.Expect(expectations)
841
842     args = ["-a", "author@chromium.org", "--revision", "push_hash",
843             "--vc-interface", "git_read_svn_write",]
844     if force: args.append("-f")
845     if manual: args.append("-m")
846     else: args += ["-r", "reviewer@chromium.org"]
847     PushToTrunk(TEST_CONFIG, self).Run(args)
848
849     cl = FileToText(TEST_CONFIG["CHANGELOG_FILE"])
850     self.assertTrue(re.search(r"^\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl))
851     self.assertTrue(re.search(r"        Log text 1 \(issue 321\).", cl))
852     self.assertTrue(re.search(r"1999\-04\-05: Version 3\.22\.4", cl))
853
854     # Note: The version file is on build number 5 again in the end of this test
855     # since the git command that merges to the bleeding edge branch is mocked
856     # out.
857
858   def testPushToTrunkManual(self):
859     self._PushToTrunk(manual=True)
860
861   def testPushToTrunkSemiAutomatic(self):
862     self._PushToTrunk()
863
864   def testPushToTrunkForced(self):
865     self._PushToTrunk(force=True)
866
867   def testPushToTrunkGit(self):
868     svn_root = self.MakeEmptyTempDirectory()
869     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
870
871     # The version file on bleeding edge has build level 5, while the version
872     # file from trunk has build level 4.
873     self.WriteFakeVersionFile(build=5)
874
875     TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile()
876     TEST_CONFIG["CHANGELOG_FILE"] = self.MakeEmptyTempFile()
877     bleeding_edge_change_log = "2014-03-17: Sentinel\n"
878     TextToFile(bleeding_edge_change_log, TEST_CONFIG["CHANGELOG_FILE"])
879
880     def ResetChangeLog():
881       """On 'git co -b new_branch svn/trunk', and 'git checkout -- ChangeLog',
882       the ChangLog will be reset to its content on trunk."""
883       trunk_change_log = """1999-04-05: Version 3.22.4
884
885         Performance and stability improvements on all platforms.\n"""
886       TextToFile(trunk_change_log, TEST_CONFIG["CHANGELOG_FILE"])
887
888     def ResetToTrunk():
889       ResetChangeLog()
890       self.WriteFakeVersionFile()
891
892     def CheckSVNCommit():
893       commit = FileToText(TEST_CONFIG["COMMITMSG_FILE"])
894       self.assertEquals(
895 """Version 3.22.5 (based on push_hash)
896
897 Log text 1 (issue 321).
898
899 Performance and stability improvements on all platforms.""", commit)
900       version = FileToText(
901           os.path.join(TEST_CONFIG["DEFAULT_CWD"], VERSION_FILE))
902       self.assertTrue(re.search(r"#define MINOR_VERSION\s+22", version))
903       self.assertTrue(re.search(r"#define BUILD_NUMBER\s+5", version))
904       self.assertFalse(re.search(r"#define BUILD_NUMBER\s+6", version))
905       self.assertTrue(re.search(r"#define PATCH_LEVEL\s+0", version))
906       self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version))
907
908       # Check that the change log on the trunk branch got correctly modified.
909       change_log = FileToText(TEST_CONFIG["CHANGELOG_FILE"])
910       self.assertEquals(
911 """1999-07-31: Version 3.22.5
912
913         Log text 1 (issue 321).
914
915         Performance and stability improvements on all platforms.
916
917
918 1999-04-05: Version 3.22.4
919
920         Performance and stability improvements on all platforms.\n""",
921           change_log)
922
923     expectations = [
924       Cmd("git status -s -uno", ""),
925       Cmd("git status -s -b -uno", "## some_branch\n"),
926       Cmd("git fetch", ""),
927       Cmd("git branch", "  branch1\n* branch2\n"),
928       Cmd("git branch", "  branch1\n* branch2\n"),
929       Cmd(("git new-branch %s --upstream origin/master" %
930            TEST_CONFIG["BRANCHNAME"]),
931           ""),
932       Cmd(("git log -1 --format=%H --grep="
933            "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\" "
934            "origin/candidates"), "hash2\n"),
935       Cmd("git log -1 hash2", "Log message\n"),
936       Cmd("git log -1 --format=%s hash2",
937        "Version 3.4.5 (based on abc3)\n"),
938       Cmd("git checkout -f origin/master -- src/version.cc",
939           "", cb=self.WriteFakeVersionFile),
940       Cmd("git checkout -f hash2 -- src/version.cc", "",
941           cb=self.WriteFakeVersionFile),
942       Cmd("git log --format=%H abc3..push_hash", "rev1\n"),
943       Cmd("git log -1 --format=%s rev1", "Log text 1.\n"),
944       Cmd("git log -1 --format=%B rev1", "Text\nLOG=YES\nBUG=v8:321\nText\n"),
945       Cmd("git log -1 --format=%an rev1", "author1@chromium.org\n"),
946       Cmd("git fetch", ""),
947       Cmd("git checkout -f origin/master", ""),
948       Cmd("git diff origin/candidates push_hash", "patch content\n"),
949       Cmd(("git new-branch %s --upstream origin/candidates" %
950            TEST_CONFIG["TRUNKBRANCH"]), "", cb=ResetToTrunk),
951       Cmd("git apply --index --reject \"%s\"" % TEST_CONFIG["PATCH_FILE"], ""),
952       Cmd(("git checkout -f origin/candidates -- %s" %
953            TEST_CONFIG["CHANGELOG_FILE"]), "",
954           cb=ResetChangeLog),
955       Cmd("git checkout -f origin/candidates -- src/version.cc", "",
956           cb=self.WriteFakeVersionFile),
957       Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], "",
958           cb=CheckSVNCommit),
959       # TODO(machenbach): Change test to pure git after flag day.
960       # Cmd("git push origin", ""),
961       Cmd("git diff HEAD^ HEAD", "patch content"),
962       Cmd("svn update", "", cwd=svn_root),
963       Cmd("svn status", "", cwd=svn_root),
964       Cmd("patch -d trunk -p1 -i %s" %
965           TEST_CONFIG["PATCH_FILE"], "Applied patch...", cwd=svn_root),
966       Cmd("svn status", "M       OWNERS\n?       new_file\n!       AUTHORS",
967           cwd=svn_root),
968       Cmd("svn add --force new_file", "", cwd=svn_root),
969       Cmd("svn delete --force AUTHORS", "", cwd=svn_root),
970       Cmd("svn commit --non-interactive --username=author@chromium.org "
971           "--config-dir=[CONFIG_DIR] "
972           "-m \"Version 3.22.5 (based on push_hash)\"",
973           "", cwd=svn_root),
974       Cmd("git fetch", ""),
975       Cmd("git log -1 --format=%H --grep="
976           "\"Version 3.22.5 (based on push_hash)\""
977           " origin/candidates", "hsh_to_tag"),
978       Cmd("git tag 3.22.5 hsh_to_tag", ""),
979       Cmd("git push https://chromium.googlesource.com/v8/v8 3.22.5", ""),
980       Cmd("git checkout -f some_branch", ""),
981       Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
982       Cmd("git branch -D %s" % TEST_CONFIG["TRUNKBRANCH"], ""),
983     ]
984     self.Expect(expectations)
985
986     args = ["-a", "author@chromium.org", "--revision", "push_hash",
987             "--vc-interface", "git", "-f", "-r", "reviewer@chromium.org",
988             "--svn", svn_root, "--svn-config", "[CONFIG_DIR]",
989             "--work-dir", TEST_CONFIG["DEFAULT_CWD"]]
990     PushToTrunk(TEST_CONFIG, self).Run(args)
991
992     cl = FileToText(TEST_CONFIG["CHANGELOG_FILE"])
993     self.assertTrue(re.search(r"^\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl))
994     self.assertTrue(re.search(r"        Log text 1 \(issue 321\).", cl))
995     self.assertTrue(re.search(r"1999\-04\-05: Version 3\.22\.4", cl))
996
997     # Note: The version file is on build number 5 again in the end of this test
998     # since the git command that merges to the bleeding edge branch is mocked
999     # out.
1000
1001   C_V8_22624_LOG = """V8 CL.
1002
1003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22624 123
1004
1005 """
1006
1007   C_V8_123455_LOG = """V8 CL.
1008
1009 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@123455 123
1010
1011 """
1012
1013   C_V8_123456_LOG = """V8 CL.
1014
1015 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@123456 123
1016
1017 """
1018
1019   def testChromiumRoll(self):
1020     googlers_mapping_py = "%s-mapping.py" % TEST_CONFIG["PERSISTFILE_BASENAME"]
1021     with open(googlers_mapping_py, "w") as f:
1022       f.write("""
1023 def list_to_dict(entries):
1024   return {"g_name@google.com": "c_name@chromium.org"}
1025 def get_list():
1026   pass""")
1027
1028     # Setup fake directory structures.
1029     TEST_CONFIG["CHROMIUM"] = self.MakeEmptyTempDirectory()
1030     TextToFile("", os.path.join(TEST_CONFIG["CHROMIUM"], ".git"))
1031     chrome_dir = TEST_CONFIG["CHROMIUM"]
1032     os.makedirs(os.path.join(chrome_dir, "v8"))
1033
1034     # Write fake deps file.
1035     TextToFile("Some line\n   \"v8_revision\": \"123444\",\n  some line",
1036                os.path.join(chrome_dir, "DEPS"))
1037     def WriteDeps():
1038       TextToFile("Some line\n   \"v8_revision\": \"22624\",\n  some line",
1039                  os.path.join(chrome_dir, "DEPS"))
1040
1041     expectations = [
1042       Cmd("git fetch origin", ""),
1043       Cmd(("git log -1 --format=%H --grep="
1044            "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\" "
1045            "origin/candidates"), "push_hash\n"),
1046       Cmd("git log -1 --format=%s push_hash",
1047           "Version 3.22.5 (based on bleeding_edge revision r22622)\n"),
1048       URL("https://chromium-build.appspot.com/p/chromium/sheriff_v8.js",
1049           "document.write('g_name')"),
1050       Cmd("git status -s -uno", "", cwd=chrome_dir),
1051       Cmd("git checkout -f master", "", cwd=chrome_dir),
1052       Cmd("gclient sync --nohooks", "syncing...", cwd=chrome_dir),
1053       Cmd("git pull", "", cwd=chrome_dir),
1054       Cmd("git fetch origin", ""),
1055       Cmd("git new-branch v8-roll-push_hash", "", cwd=chrome_dir),
1056       Cmd("roll-dep v8 push_hash", "rolled", cb=WriteDeps, cwd=chrome_dir),
1057       Cmd(("git commit -am \"Update V8 to version 3.22.5 "
1058            "(based on bleeding_edge revision r22622).\n\n"
1059            "Please reply to the V8 sheriff c_name@chromium.org in "
1060            "case of problems.\n\nTBR=c_name@chromium.org\" "
1061            "--author \"author@chromium.org <author@chromium.org>\""),
1062           "", cwd=chrome_dir),
1063       Cmd("git cl upload --send-mail --email \"author@chromium.org\" -f", "",
1064           cwd=chrome_dir),
1065     ]
1066     self.Expect(expectations)
1067
1068     args = ["-a", "author@chromium.org", "-c", chrome_dir,
1069             "--sheriff", "--googlers-mapping", googlers_mapping_py,
1070             "-r", "reviewer@chromium.org"]
1071     ChromiumRoll(TEST_CONFIG, self).Run(args)
1072
1073     deps = FileToText(os.path.join(chrome_dir, "DEPS"))
1074     self.assertTrue(re.search("\"v8_revision\": \"22624\"", deps))
1075
1076   def testCheckLastPushRecently(self):
1077     self.Expect([
1078       Cmd(("git log -1 --format=%H --grep="
1079            "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\" "
1080            "origin/candidates"), "hash2\n"),
1081       Cmd("git log -1 --format=%s hash2",
1082           "Version 3.4.5 (based on abc123)\n"),
1083     ])
1084
1085     self._state["lkgr"] = "abc123"
1086     self.assertEquals(0, self.RunStep(
1087         auto_push.AutoPush, CheckLastPush, AUTO_PUSH_ARGS))
1088
1089   def testAutoPush(self):
1090     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
1091     TEST_CONFIG["SETTINGS_LOCATION"] = "~/.doesnotexist"
1092
1093     self.Expect([
1094       Cmd("git status -s -uno", ""),
1095       Cmd("git status -s -b -uno", "## some_branch\n"),
1096       Cmd("git fetch", ""),
1097       URL("https://v8-status.appspot.com/current?format=json",
1098           "{\"message\": \"Tree is throttled\"}"),
1099       URL("https://v8-status.appspot.com/lkgr", Exception("Network problem")),
1100       URL("https://v8-status.appspot.com/lkgr", "abc123"),
1101       Cmd(("git log -1 --format=%H --grep=\""
1102            "^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based\""
1103            " origin/candidates"), "push_hash\n"),
1104       Cmd("git log -1 --format=%s push_hash",
1105           "Version 3.4.5 (based on abc101)\n"),
1106     ])
1107
1108     auto_push.AutoPush(TEST_CONFIG, self).Run(
1109         AUTO_PUSH_ARGS + ["--push", "--vc-interface", "git"])
1110
1111     state = json.loads(FileToText("%s-state.json"
1112                                   % TEST_CONFIG["PERSISTFILE_BASENAME"]))
1113
1114     self.assertEquals("abc123", state["lkgr"])
1115
1116   def testAutoPushStoppedBySettings(self):
1117     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
1118     TEST_CONFIG["SETTINGS_LOCATION"] = self.MakeEmptyTempFile()
1119     TextToFile("{\"enable_auto_push\": false}",
1120                TEST_CONFIG["SETTINGS_LOCATION"])
1121
1122     self.Expect([
1123       Cmd("git status -s -uno", ""),
1124       Cmd("git status -s -b -uno", "## some_branch\n"),
1125       Cmd("git fetch", ""),
1126       Cmd("git svn fetch", ""),
1127     ])
1128
1129     def RunAutoPush():
1130       auto_push.AutoPush(TEST_CONFIG, self).Run(AUTO_PUSH_ARGS)
1131     self.assertRaises(Exception, RunAutoPush)
1132
1133   def testAutoPushStoppedByTreeStatus(self):
1134     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
1135     TEST_CONFIG["SETTINGS_LOCATION"] = "~/.doesnotexist"
1136
1137     self.Expect([
1138       Cmd("git status -s -uno", ""),
1139       Cmd("git status -s -b -uno", "## some_branch\n"),
1140       Cmd("git fetch", ""),
1141       Cmd("git svn fetch", ""),
1142       URL("https://v8-status.appspot.com/current?format=json",
1143           "{\"message\": \"Tree is throttled (no push)\"}"),
1144     ])
1145
1146     def RunAutoPush():
1147       auto_push.AutoPush(TEST_CONFIG, self).Run(AUTO_PUSH_ARGS)
1148     self.assertRaises(Exception, RunAutoPush)
1149
1150   def testAutoRollExistingRoll(self):
1151     self.Expect([
1152       URL("https://codereview.chromium.org/search",
1153           "owner=author%40chromium.org&limit=30&closed=3&format=json",
1154           ("{\"results\": [{\"subject\": \"different\"},"
1155            "{\"subject\": \"Update V8 to Version...\"}]}")),
1156     ])
1157
1158     result = auto_roll.AutoRoll(TEST_CONFIG, self).Run(
1159         AUTO_PUSH_ARGS + ["-c", TEST_CONFIG["CHROMIUM"]])
1160     self.assertEquals(0, result)
1161
1162   # Snippet from the original DEPS file.
1163   FAKE_DEPS = """
1164 vars = {
1165   "v8_revision": "abcd123455",
1166 }
1167 deps = {
1168   "src/v8":
1169     (Var("googlecode_url") % "v8") + "/" + Var("v8_branch") + "@" +
1170     Var("v8_revision"),
1171 }
1172 """
1173
1174   def testAutoRollUpToDate(self):
1175     TEST_CONFIG["CHROMIUM"] = self.MakeEmptyTempDirectory()
1176     TextToFile(self.FAKE_DEPS, os.path.join(TEST_CONFIG["CHROMIUM"], "DEPS"))
1177     self.Expect([
1178       URL("https://codereview.chromium.org/search",
1179           "owner=author%40chromium.org&limit=30&closed=3&format=json",
1180           ("{\"results\": [{\"subject\": \"different\"}]}")),
1181       Cmd("git fetch", ""),
1182       Cmd("git svn fetch", ""),
1183       Cmd(("git log -1 --format=%H --grep="
1184            "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\" "
1185            "origin/candidates"), "push_hash\n"),
1186       Cmd("git log -1 --format=%B push_hash", self.C_V8_22624_LOG),
1187       Cmd("git log -1 --format=%B abcd123455", self.C_V8_123455_LOG),
1188     ])
1189
1190     result = auto_roll.AutoRoll(TEST_CONFIG, self).Run(
1191         AUTO_PUSH_ARGS + ["-c", TEST_CONFIG["CHROMIUM"]])
1192     self.assertEquals(0, result)
1193
1194   def testAutoRoll(self):
1195     TEST_CONFIG["CHROMIUM"] = self.MakeEmptyTempDirectory()
1196     TextToFile(self.FAKE_DEPS, os.path.join(TEST_CONFIG["CHROMIUM"], "DEPS"))
1197     TEST_CONFIG["CLUSTERFUZZ_API_KEY_FILE"]  = self.MakeEmptyTempFile()
1198     TextToFile("fake key", TEST_CONFIG["CLUSTERFUZZ_API_KEY_FILE"])
1199
1200     self.Expect([
1201       URL("https://codereview.chromium.org/search",
1202           "owner=author%40chromium.org&limit=30&closed=3&format=json",
1203           ("{\"results\": [{\"subject\": \"different\"}]}")),
1204       Cmd("git fetch", ""),
1205       Cmd("git svn fetch", ""),
1206       Cmd(("git log -1 --format=%H --grep="
1207            "\"^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\" "
1208            "origin/candidates"), "push_hash\n"),
1209       Cmd("git log -1 --format=%B push_hash", self.C_V8_123456_LOG),
1210       Cmd("git log -1 --format=%B abcd123455", self.C_V8_123455_LOG),
1211     ])
1212
1213     result = auto_roll.AutoRoll(TEST_CONFIG, self).Run(
1214         AUTO_PUSH_ARGS + ["-c", TEST_CONFIG["CHROMIUM"], "--roll"])
1215     self.assertEquals(0, result)
1216
1217   def testMergeToBranch(self):
1218     TEST_CONFIG["ALREADY_MERGING_SENTINEL_FILE"] = self.MakeEmptyTempFile()
1219     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
1220     self.WriteFakeVersionFile(build=5)
1221     os.environ["EDITOR"] = "vi"
1222     extra_patch = self.MakeEmptyTempFile()
1223
1224     def VerifyPatch(patch):
1225       return lambda: self.assertEquals(patch,
1226           FileToText(TEST_CONFIG["TEMPORARY_PATCH_FILE"]))
1227
1228     msg = """Version 3.22.5.1 (merged r12345, r23456, r34567, r45678, r56789)
1229
1230 Title4
1231
1232 Title2
1233
1234 Title3
1235
1236 Title1
1237
1238 Revert "Something"
1239
1240 BUG=123,234,345,456,567,v8:123
1241 LOG=N
1242 """
1243
1244     def VerifySVNCommit():
1245       commit = FileToText(TEST_CONFIG["COMMITMSG_FILE"])
1246       self.assertEquals(msg, commit)
1247       version = FileToText(
1248           os.path.join(TEST_CONFIG["DEFAULT_CWD"], VERSION_FILE))
1249       self.assertTrue(re.search(r"#define MINOR_VERSION\s+22", version))
1250       self.assertTrue(re.search(r"#define BUILD_NUMBER\s+5", version))
1251       self.assertTrue(re.search(r"#define PATCH_LEVEL\s+1", version))
1252       self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version))
1253
1254     self.Expect([
1255       Cmd("git status -s -uno", ""),
1256       Cmd("git status -s -b -uno", "## some_branch\n"),
1257       Cmd("git svn fetch", ""),
1258       Cmd("git branch", "  branch1\n* branch2\n"),
1259       Cmd("git new-branch %s --upstream svn/trunk" % TEST_CONFIG["BRANCHNAME"],
1260           ""),
1261       Cmd(("git log --format=%H --grep=\"Port r12345\" "
1262            "--reverse svn/bleeding_edge"),
1263           "hash1\nhash2"),
1264       Cmd("git svn find-rev hash1 svn/bleeding_edge", "45678"),
1265       Cmd("git log -1 --format=%s hash1", "Title1"),
1266       Cmd("git svn find-rev hash2 svn/bleeding_edge", "23456"),
1267       Cmd("git log -1 --format=%s hash2", "Title2"),
1268       Cmd(("git log --format=%H --grep=\"Port r23456\" "
1269            "--reverse svn/bleeding_edge"),
1270           ""),
1271       Cmd(("git log --format=%H --grep=\"Port r34567\" "
1272            "--reverse svn/bleeding_edge"),
1273           "hash3"),
1274       Cmd("git svn find-rev hash3 svn/bleeding_edge", "56789"),
1275       Cmd("git log -1 --format=%s hash3", "Title3"),
1276       RL("Y"),  # Automatically add corresponding ports (34567, 56789)?
1277       Cmd("git svn find-rev r12345 svn/bleeding_edge", "hash4"),
1278       # Simulate svn being down which stops the script.
1279       Cmd("git svn find-rev r23456 svn/bleeding_edge", None),
1280       # Restart script in the failing step.
1281       Cmd("git svn find-rev r12345 svn/bleeding_edge", "hash4"),
1282       Cmd("git svn find-rev r23456 svn/bleeding_edge", "hash2"),
1283       Cmd("git svn find-rev r34567 svn/bleeding_edge", "hash3"),
1284       Cmd("git svn find-rev r45678 svn/bleeding_edge", "hash1"),
1285       Cmd("git svn find-rev r56789 svn/bleeding_edge", "hash5"),
1286       Cmd("git log -1 --format=%s hash4", "Title4"),
1287       Cmd("git log -1 --format=%s hash2", "Title2"),
1288       Cmd("git log -1 --format=%s hash3", "Title3"),
1289       Cmd("git log -1 --format=%s hash1", "Title1"),
1290       Cmd("git log -1 --format=%s hash5", "Revert \"Something\""),
1291       Cmd("git log -1 hash4", "Title4\nBUG=123\nBUG=234"),
1292       Cmd("git log -1 hash2", "Title2\n BUG = v8:123,345"),
1293       Cmd("git log -1 hash3", "Title3\nLOG=n\nBUG=567, 456"),
1294       Cmd("git log -1 hash1", "Title1\nBUG="),
1295       Cmd("git log -1 hash5", "Revert \"Something\"\nBUG=none"),
1296       Cmd("git log -1 -p hash4", "patch4"),
1297       Cmd(("git apply --index --reject \"%s\"" %
1298            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1299           "", cb=VerifyPatch("patch4")),
1300       Cmd("git log -1 -p hash2", "patch2"),
1301       Cmd(("git apply --index --reject \"%s\"" %
1302            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1303           "", cb=VerifyPatch("patch2")),
1304       Cmd("git log -1 -p hash3", "patch3"),
1305       Cmd(("git apply --index --reject \"%s\"" %
1306            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1307           "", cb=VerifyPatch("patch3")),
1308       Cmd("git log -1 -p hash1", "patch1"),
1309       Cmd(("git apply --index --reject \"%s\"" %
1310            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1311           "", cb=VerifyPatch("patch1")),
1312       Cmd("git log -1 -p hash5", "patch5\n"),
1313       Cmd(("git apply --index --reject \"%s\"" %
1314            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1315           "", cb=VerifyPatch("patch5\n")),
1316       Cmd("git apply --index --reject \"%s\"" % extra_patch, ""),
1317       RL("Y"),  # Automatically increment patch level?
1318       Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], ""),
1319       RL("reviewer@chromium.org"),  # V8 reviewer.
1320       Cmd("git cl upload --send-mail -r \"reviewer@chromium.org\" "
1321           "--bypass-hooks --cc \"ulan@chromium.org\"", ""),
1322       Cmd("git checkout -f %s" % TEST_CONFIG["BRANCHNAME"], ""),
1323       RL("LGTM"),  # Enter LGTM for V8 CL.
1324       Cmd("git cl presubmit", "Presubmit successfull\n"),
1325       Cmd("git cl dcommit -f --bypass-hooks", "Closing issue\n",
1326           cb=VerifySVNCommit),
1327       Cmd("git svn fetch", ""),
1328       Cmd("git rebase svn/trunk", ""),
1329       Cmd("git svn tag 3.22.5.1 -m \"Tagging version 3.22.5.1\"", ""),
1330       Cmd("git checkout -f some_branch", ""),
1331       Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
1332     ])
1333
1334     # r12345 and r34567 are patches. r23456 (included) and r45678 are the MIPS
1335     # ports of r12345. r56789 is the MIPS port of r34567.
1336     args = ["-f", "-p", extra_patch, "--branch", "trunk",
1337             "--vc-interface", "git_svn", "12345", "23456", "34567"]
1338
1339     # The first run of the script stops because of the svn being down.
1340     self.assertRaises(GitFailedException,
1341         lambda: MergeToBranch(TEST_CONFIG, self).Run(args))
1342
1343     # Test that state recovery after restarting the script works.
1344     args += ["-s", "4"]
1345     MergeToBranch(TEST_CONFIG, self).Run(args)
1346
1347   def testMergeToBranchNewGit(self):
1348     TEST_CONFIG["ALREADY_MERGING_SENTINEL_FILE"] = self.MakeEmptyTempFile()
1349     TextToFile("", os.path.join(TEST_CONFIG["DEFAULT_CWD"], ".git"))
1350     self.WriteFakeVersionFile(build=5)
1351     os.environ["EDITOR"] = "vi"
1352     extra_patch = self.MakeEmptyTempFile()
1353
1354     def VerifyPatch(patch):
1355       return lambda: self.assertEquals(patch,
1356           FileToText(TEST_CONFIG["TEMPORARY_PATCH_FILE"]))
1357
1358     msg = """Version 3.22.5.1 (merged r12345, r23456, r34567, r45678, r56789)
1359
1360 Title4
1361
1362 Title2
1363
1364 Title3
1365
1366 Title1
1367
1368 Revert "Something"
1369
1370 BUG=123,234,345,456,567,v8:123
1371 LOG=N
1372 """
1373
1374     def VerifySVNCommit():
1375       commit = FileToText(TEST_CONFIG["COMMITMSG_FILE"])
1376       self.assertEquals(msg, commit)
1377       version = FileToText(
1378           os.path.join(TEST_CONFIG["DEFAULT_CWD"], VERSION_FILE))
1379       self.assertTrue(re.search(r"#define MINOR_VERSION\s+22", version))
1380       self.assertTrue(re.search(r"#define BUILD_NUMBER\s+5", version))
1381       self.assertTrue(re.search(r"#define PATCH_LEVEL\s+1", version))
1382       self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version))
1383
1384     self.Expect([
1385       Cmd("git status -s -uno", ""),
1386       Cmd("git status -s -b -uno", "## some_branch\n"),
1387       Cmd("git fetch", ""),
1388       Cmd("git svn fetch", ""),
1389       Cmd("git branch", "  branch1\n* branch2\n"),
1390       Cmd("git new-branch %s --upstream origin/candidates" %
1391           TEST_CONFIG["BRANCHNAME"], ""),
1392       Cmd(("git log --format=%H --grep=\"Port r12345\" "
1393            "--reverse origin/master"),
1394           "hash1\nhash2"),
1395       Cmd("git svn find-rev hash1 origin/master", "45678"),
1396       Cmd("git log -1 --format=%s hash1", "Title1"),
1397       Cmd("git svn find-rev hash2 origin/master", "23456"),
1398       Cmd("git log -1 --format=%s hash2", "Title2"),
1399       Cmd(("git log --format=%H --grep=\"Port r23456\" "
1400            "--reverse origin/master"),
1401           ""),
1402       Cmd(("git log --format=%H --grep=\"Port r34567\" "
1403            "--reverse origin/master"),
1404           "hash3"),
1405       Cmd("git svn find-rev hash3 origin/master", "56789"),
1406       Cmd("git log -1 --format=%s hash3", "Title3"),
1407       RL("Y"),  # Automatically add corresponding ports (34567, 56789)?
1408       Cmd("git svn find-rev r12345 origin/master",
1409           "Partial-rebuilding bla\nDone rebuilding blub\nhash4"),
1410       # Simulate svn being down which stops the script.
1411       Cmd("git svn find-rev r23456 origin/master", None),
1412       # Restart script in the failing step.
1413       Cmd("git svn find-rev r12345 origin/master", "hash4"),
1414       Cmd("git svn find-rev r23456 origin/master", "hash2"),
1415       Cmd("git svn find-rev r34567 origin/master", "hash3"),
1416       Cmd("git svn find-rev r45678 origin/master", "hash1"),
1417       Cmd("git svn find-rev r56789 origin/master", "hash5"),
1418       Cmd("git log -1 --format=%s hash4", "Title4"),
1419       Cmd("git log -1 --format=%s hash2", "Title2"),
1420       Cmd("git log -1 --format=%s hash3", "Title3"),
1421       Cmd("git log -1 --format=%s hash1", "Title1"),
1422       Cmd("git log -1 --format=%s hash5", "Revert \"Something\""),
1423       Cmd("git log -1 hash4", "Title4\nBUG=123\nBUG=234"),
1424       Cmd("git log -1 hash2", "Title2\n BUG = v8:123,345"),
1425       Cmd("git log -1 hash3", "Title3\nLOG=n\nBUG=567, 456"),
1426       Cmd("git log -1 hash1", "Title1\nBUG="),
1427       Cmd("git log -1 hash5", "Revert \"Something\"\nBUG=none"),
1428       Cmd("git log -1 -p hash4", "patch4"),
1429       Cmd(("git apply --index --reject \"%s\"" %
1430            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1431           "", cb=VerifyPatch("patch4")),
1432       Cmd("git log -1 -p hash2", "patch2"),
1433       Cmd(("git apply --index --reject \"%s\"" %
1434            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1435           "", cb=VerifyPatch("patch2")),
1436       Cmd("git log -1 -p hash3", "patch3"),
1437       Cmd(("git apply --index --reject \"%s\"" %
1438            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1439           "", cb=VerifyPatch("patch3")),
1440       Cmd("git log -1 -p hash1", "patch1"),
1441       Cmd(("git apply --index --reject \"%s\"" %
1442            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1443           "", cb=VerifyPatch("patch1")),
1444       Cmd("git log -1 -p hash5", "patch5\n"),
1445       Cmd(("git apply --index --reject \"%s\"" %
1446            TEST_CONFIG["TEMPORARY_PATCH_FILE"]),
1447           "", cb=VerifyPatch("patch5\n")),
1448       Cmd("git apply --index --reject \"%s\"" % extra_patch, ""),
1449       RL("Y"),  # Automatically increment patch level?
1450       Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], ""),
1451       RL("reviewer@chromium.org"),  # V8 reviewer.
1452       Cmd("git cl upload --send-mail -r \"reviewer@chromium.org\" "
1453           "--bypass-hooks --cc \"ulan@chromium.org\"", ""),
1454       Cmd("git checkout -f %s" % TEST_CONFIG["BRANCHNAME"], ""),
1455       RL("LGTM"),  # Enter LGTM for V8 CL.
1456       Cmd("git cl presubmit", "Presubmit successfull\n"),
1457       Cmd("git cl dcommit -f --bypass-hooks", "Closing issue\n",
1458           cb=VerifySVNCommit),
1459       Cmd("git fetch", ""),
1460       Cmd("git log -1 --format=%H --grep=\""
1461           "Version 3.22.5.1 (merged r12345, r23456, r34567, r45678, r56789)"
1462           "\" origin/candidates",
1463           ""),
1464       Cmd("git fetch", ""),
1465       Cmd("git log -1 --format=%H --grep=\""
1466           "Version 3.22.5.1 (merged r12345, r23456, r34567, r45678, r56789)"
1467           "\" origin/candidates",
1468           "hsh_to_tag"),
1469       Cmd("git tag 3.22.5.1 hsh_to_tag", ""),
1470       Cmd("git push origin 3.22.5.1", ""),
1471       Cmd("git checkout -f some_branch", ""),
1472       Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
1473     ])
1474
1475     # r12345 and r34567 are patches. r23456 (included) and r45678 are the MIPS
1476     # ports of r12345. r56789 is the MIPS port of r34567.
1477     args = ["-f", "-p", extra_patch, "--branch", "candidates",
1478             "--vc-interface", "git_read_svn_write", "12345", "23456", "34567"]
1479
1480     # The first run of the script stops because of the svn being down.
1481     self.assertRaises(GitFailedException,
1482         lambda: MergeToBranch(TEST_CONFIG, self).Run(args))
1483
1484     # Test that state recovery after restarting the script works.
1485     args += ["-s", "4"]
1486     MergeToBranch(TEST_CONFIG, self).Run(args)
1487
1488   def testReleases(self):
1489     tag_response_text = """
1490 ------------------------------------------------------------------------
1491 r22631 | author1@chromium.org | 2014-07-28 02:05:29 +0200 (Mon, 28 Jul 2014)
1492 Changed paths:
1493    A /tags/3.28.43 (from /trunk:22630)
1494
1495 Tagging version 3.28.43
1496 ------------------------------------------------------------------------
1497 r22629 | author2@chromium.org | 2014-07-26 05:09:29 +0200 (Sat, 26 Jul 2014)
1498 Changed paths:
1499    A /tags/3.28.41 (from /branches/bleeding_edge:22626)
1500
1501 Tagging version 3.28.41
1502 ------------------------------------------------------------------------
1503 r22556 | author3@chromium.org | 2014-07-23 13:31:59 +0200 (Wed, 23 Jul 2014)
1504 Changed paths:
1505    A /tags/3.27.34.7 (from /branches/3.27:22555)
1506
1507 Tagging version 3.27.34.7
1508 ------------------------------------------------------------------------
1509 r22627 | author4@chromium.org | 2014-07-26 01:39:15 +0200 (Sat, 26 Jul 2014)
1510 Changed paths:
1511    A /tags/3.28.40 (from /branches/bleeding_edge:22624)
1512
1513 Tagging version 3.28.40
1514 ------------------------------------------------------------------------
1515 """
1516     c_hash2_commit_log = """Revert something.
1517
1518 BUG=12345
1519
1520 Reason:
1521 > Some reason.
1522 > Cr-Commit-Position: refs/heads/master@{#12345}
1523 > git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12345 003-1c4
1524
1525 Review URL: https://codereview.chromium.org/12345
1526
1527 Cr-Commit-Position: refs/heads/master@{#4567}
1528 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4567 0039-1c4b
1529
1530 """
1531     c_hash3_commit_log = """Simple.
1532
1533 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3456 0039-1c4b
1534
1535 """
1536     json_output = self.MakeEmptyTempFile()
1537     csv_output = self.MakeEmptyTempFile()
1538     self.WriteFakeVersionFile()
1539
1540     TEST_CONFIG["CHROMIUM"] = self.MakeEmptyTempDirectory()
1541     chrome_dir = TEST_CONFIG["CHROMIUM"]
1542     chrome_v8_dir = os.path.join(chrome_dir, "v8")
1543     os.makedirs(chrome_v8_dir)
1544     def WriteDEPS(revision):
1545       TextToFile("Line\n   \"v8_revision\": \"%s\",\n  line\n" % revision,
1546                  os.path.join(chrome_dir, "DEPS"))
1547     WriteDEPS(567)
1548
1549     def ResetVersion(minor, build, patch=0):
1550       return lambda: self.WriteFakeVersionFile(minor=minor,
1551                                                build=build,
1552                                                patch=patch)
1553
1554     def ResetDEPS(revision):
1555       return lambda: WriteDEPS(revision)
1556
1557     self.Expect([
1558       Cmd("git status -s -uno", ""),
1559       Cmd("git status -s -b -uno", "## some_branch\n"),
1560       Cmd("git fetch", ""),
1561       Cmd("git svn fetch", ""),
1562       Cmd("git branch", "  branch1\n* branch2\n"),
1563       Cmd("git new-branch %s" % TEST_CONFIG["BRANCHNAME"], ""),
1564       Cmd("git branch -r", "  branch-heads/3.21\n  branch-heads/3.3\n"),
1565       Cmd("git reset --hard branch-heads/3.3", ""),
1566       Cmd("git log --format=%H", "hash1\nhash_234"),
1567       Cmd("git diff --name-only hash1 hash1^", ""),
1568       Cmd("git diff --name-only hash_234 hash_234^", VERSION_FILE),
1569       Cmd("git checkout -f hash_234 -- %s" % VERSION_FILE, "",
1570           cb=ResetVersion(3, 1, 1)),
1571       Cmd("git log -1 --format=%B hash_234",
1572           "Version 3.3.1.1 (merged 12)\n\nReview URL: fake.com\n"),
1573       Cmd("git log -1 --format=%s hash_234", ""),
1574       Cmd("git svn find-rev hash_234", "234"),
1575       Cmd("git log -1 --format=%ci hash_234", "18:15"),
1576       Cmd("git checkout -f HEAD -- %s" % VERSION_FILE, "",
1577           cb=ResetVersion(22, 5)),
1578       Cmd("git reset --hard branch-heads/3.21", ""),
1579       Cmd("git log --format=%H", "hash_123\nhash4\nhash5\n"),
1580       Cmd("git diff --name-only hash_123 hash_123^", VERSION_FILE),
1581       Cmd("git checkout -f hash_123 -- %s" % VERSION_FILE, "",
1582           cb=ResetVersion(21, 2)),
1583       Cmd("git log -1 --format=%B hash_123", ""),
1584       Cmd("git log -1 --format=%s hash_123", ""),
1585       Cmd("git svn find-rev hash_123", "123"),
1586       Cmd("git log -1 --format=%ci hash_123", "03:15"),
1587       Cmd("git checkout -f HEAD -- %s" % VERSION_FILE, "",
1588           cb=ResetVersion(22, 5)),
1589       Cmd("git reset --hard origin/candidates", ""),
1590       Cmd("git log --format=%H", "hash_345\n"),
1591       Cmd("git diff --name-only hash_345 hash_345^", VERSION_FILE),
1592       Cmd("git checkout -f hash_345 -- %s" % VERSION_FILE, "",
1593           cb=ResetVersion(22, 3)),
1594       Cmd("git log -1 --format=%B hash_345", ""),
1595       Cmd("git log -1 --format=%s hash_345", ""),
1596       Cmd("git svn find-rev hash_345", "345"),
1597       Cmd("git log -1 --format=%ci hash_345", ""),
1598       Cmd("git checkout -f HEAD -- %s" % VERSION_FILE, "",
1599           cb=ResetVersion(22, 5)),
1600       Cmd("git reset --hard origin/master", ""),
1601       Cmd("svn log https://v8.googlecode.com/svn/tags -v --limit 20",
1602           tag_response_text),
1603       Cmd("git svn find-rev r22626", "hash_22626"),
1604       Cmd("git svn find-rev hash_22626", "22626"),
1605       Cmd("git log -1 --format=%ci hash_22626", "01:23"),
1606       Cmd("git svn find-rev r22624", "hash_22624"),
1607       Cmd("git svn find-rev hash_22624", "22624"),
1608       Cmd("git log -1 --format=%ci hash_22624", "02:34"),
1609       Cmd("git status -s -uno", "", cwd=chrome_dir),
1610       Cmd("git checkout -f master", "", cwd=chrome_dir),
1611       Cmd("git pull", "", cwd=chrome_dir),
1612       Cmd("git new-branch %s" % TEST_CONFIG["BRANCHNAME"], "",
1613           cwd=chrome_dir),
1614       Cmd("git fetch origin", "", cwd=chrome_v8_dir),
1615       Cmd("git log --format=%H --grep=\"V8\"", "c_hash1\nc_hash2\nc_hash3\n",
1616           cwd=chrome_dir),
1617       Cmd("git diff --name-only c_hash1 c_hash1^", "", cwd=chrome_dir),
1618       Cmd("git diff --name-only c_hash2 c_hash2^", "DEPS", cwd=chrome_dir),
1619       Cmd("git checkout -f c_hash2 -- DEPS", "",
1620           cb=ResetDEPS("0123456789012345678901234567890123456789"),
1621           cwd=chrome_dir),
1622       Cmd("git log -1 --format=%B c_hash2", c_hash2_commit_log,
1623           cwd=chrome_dir),
1624       Cmd("git rev-list -n 1 0123456789012345678901234567890123456789",
1625           "0123456789012345678901234567890123456789", cwd=chrome_v8_dir),
1626       Cmd("git log -1 --format=%B 0123456789012345678901234567890123456789",
1627           self.C_V8_22624_LOG, cwd=chrome_v8_dir),
1628       Cmd("git diff --name-only c_hash3 c_hash3^", "DEPS", cwd=chrome_dir),
1629       Cmd("git checkout -f c_hash3 -- DEPS", "", cb=ResetDEPS(345),
1630           cwd=chrome_dir),
1631       Cmd("git log -1 --format=%B c_hash3", c_hash3_commit_log,
1632           cwd=chrome_dir),
1633       Cmd("git checkout -f HEAD -- DEPS", "", cb=ResetDEPS(567),
1634           cwd=chrome_dir),
1635       Cmd("git branch -r", " weird/123\n  branch-heads/7\n", cwd=chrome_dir),
1636       Cmd("git checkout -f branch-heads/7 -- DEPS", "", cb=ResetDEPS(345),
1637           cwd=chrome_dir),
1638       Cmd("git checkout -f HEAD -- DEPS", "", cb=ResetDEPS(567),
1639           cwd=chrome_dir),
1640       Cmd("git checkout -f master", "", cwd=chrome_dir),
1641       Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], "", cwd=chrome_dir),
1642       Cmd("git checkout -f some_branch", ""),
1643       Cmd("git branch -D %s" % TEST_CONFIG["BRANCHNAME"], ""),
1644     ])
1645
1646     args = ["-c", TEST_CONFIG["CHROMIUM"],
1647             "--vc-interface", "git_read_svn_write",
1648             "--json", json_output,
1649             "--csv", csv_output,
1650             "--max-releases", "1"]
1651     Releases(TEST_CONFIG, self).Run(args)
1652
1653     # Check expected output.
1654     csv = ("3.28.41,master,22626,,\r\n"
1655            "3.28.40,master,22624,4567,\r\n"
1656            "3.22.3,candidates,345,3456:4566,\r\n"
1657            "3.21.2,3.21,123,,\r\n"
1658            "3.3.1.1,3.3,234,,12\r\n")
1659     self.assertEquals(csv, FileToText(csv_output))
1660
1661     expected_json = [
1662       {
1663         "revision": "22626",
1664         "revision_git": "hash_22626",
1665         "bleeding_edge": "22626",
1666         "bleeding_edge_git": "hash_22626",
1667         "patches_merged": "",
1668         "version": "3.28.41",
1669         "chromium_revision": "",
1670         "branch": "master",
1671         "review_link": "",
1672         "date": "01:23",
1673         "chromium_branch": "",
1674         "revision_link": "https://code.google.com/p/v8/source/detail?r=22626",
1675       },
1676       {
1677         "revision": "22624",
1678         "revision_git": "hash_22624",
1679         "bleeding_edge": "22624",
1680         "bleeding_edge_git": "hash_22624",
1681         "patches_merged": "",
1682         "version": "3.28.40",
1683         "chromium_revision": "4567",
1684         "branch": "master",
1685         "review_link": "",
1686         "date": "02:34",
1687         "chromium_branch": "",
1688         "revision_link": "https://code.google.com/p/v8/source/detail?r=22624",
1689       },
1690       {
1691         "revision": "345",
1692         "revision_git": "hash_345",
1693         "bleeding_edge": "",
1694         "bleeding_edge_git": "",
1695         "patches_merged": "",
1696         "version": "3.22.3",
1697         "chromium_revision": "3456:4566",
1698         "branch": "candidates",
1699         "review_link": "",
1700         "date": "",
1701         "chromium_branch": "7",
1702         "revision_link": "https://code.google.com/p/v8/source/detail?r=345",
1703       },
1704       {
1705         "revision": "123",
1706         "revision_git": "hash_123",
1707         "patches_merged": "",
1708         "bleeding_edge": "",
1709         "bleeding_edge_git": "",
1710         "version": "3.21.2",
1711         "chromium_revision": "",
1712         "branch": "3.21",
1713         "review_link": "",
1714         "date": "03:15",
1715         "chromium_branch": "",
1716         "revision_link": "https://code.google.com/p/v8/source/detail?r=123",
1717       },
1718       {
1719         "revision": "234",
1720         "revision_git": "hash_234",
1721         "patches_merged": "12",
1722         "bleeding_edge": "",
1723         "bleeding_edge_git": "",
1724         "version": "3.3.1.1",
1725         "chromium_revision": "",
1726         "branch": "3.3",
1727         "review_link": "fake.com",
1728         "date": "18:15",
1729         "chromium_branch": "",
1730         "revision_link": "https://code.google.com/p/v8/source/detail?r=234",
1731       },
1732     ]
1733     self.assertEquals(expected_json, json.loads(FileToText(json_output)))
1734
1735
1736   def _bumpUpVersion(self):
1737     self.WriteFakeVersionFile()
1738
1739     def ResetVersion(minor, build, patch=0):
1740       return lambda: self.WriteFakeVersionFile(minor=minor,
1741                                                build=build,
1742                                                patch=patch)
1743
1744     return [
1745       Cmd("git status -s -uno", ""),
1746       Cmd("git checkout -f master", "", cb=ResetVersion(11, 4)),
1747       Cmd("git pull", ""),
1748       Cmd("git branch", ""),
1749       Cmd("git checkout -f master", ""),
1750       Cmd("git log -1 --format=%H", "latest_hash"),
1751       Cmd("git diff --name-only latest_hash latest_hash^", ""),
1752       URL("https://v8-status.appspot.com/lkgr", "12345"),
1753       Cmd("git checkout -f master", ""),
1754       Cmd(("git log --format=%H --grep="
1755            "\"^git-svn-id: [^@]*@12345 [A-Za-z0-9-]*$\""),
1756           "lkgr_hash"),
1757       Cmd("git new-branch auto-bump-up-version --upstream lkgr_hash", ""),
1758       Cmd("git checkout -f master", ""),
1759       Cmd("git branch", "auto-bump-up-version\n* master"),
1760       Cmd("git branch -D auto-bump-up-version", ""),
1761       Cmd("git diff --name-only lkgr_hash lkgr_hash^", ""),
1762       Cmd("git checkout -f candidates", "", cb=ResetVersion(11, 5)),
1763       Cmd("git pull", ""),
1764       URL("https://v8-status.appspot.com/current?format=json",
1765           "{\"message\": \"Tree is open\"}"),
1766       Cmd("git new-branch auto-bump-up-version --upstream master", "",
1767           cb=ResetVersion(11, 4)),
1768       Cmd("git commit -am \"[Auto-roll] Bump up version to 3.11.6.0\n\n"
1769           "TBR=author@chromium.org\" "
1770           "--author \"author@chromium.org <author@chromium.org>\"", ""),
1771     ]
1772
1773   def testBumpUpVersionGit(self):
1774     expectations = self._bumpUpVersion()
1775     expectations += [
1776       Cmd("git cl upload --send-mail --email \"author@chromium.org\" -f "
1777           "--bypass-hooks", ""),
1778       Cmd("git cl dcommit -f --bypass-hooks", ""),
1779       Cmd("git checkout -f master", ""),
1780       Cmd("git branch", "auto-bump-up-version\n* master"),
1781       Cmd("git branch -D auto-bump-up-version", ""),
1782     ]
1783     self.Expect(expectations)
1784
1785     BumpUpVersion(TEST_CONFIG, self).Run(["-a", "author@chromium.org"])
1786
1787   def testBumpUpVersionSvn(self):
1788     svn_root = self.MakeEmptyTempDirectory()
1789     expectations = self._bumpUpVersion()
1790     expectations += [
1791       Cmd("git diff HEAD^ HEAD", "patch content"),
1792       Cmd("svn update", "", cwd=svn_root),
1793       Cmd("svn status", "", cwd=svn_root),
1794       Cmd("patch -d branches/bleeding_edge -p1 -i %s" %
1795           TEST_CONFIG["PATCH_FILE"], "Applied patch...", cwd=svn_root),
1796      Cmd("svn status", "M       src/version.cc", cwd=svn_root),
1797       Cmd("svn commit --non-interactive --username=author@chromium.org "
1798           "--config-dir=[CONFIG_DIR] "
1799           "-m \"[Auto-roll] Bump up version to 3.11.6.0\"",
1800           "", cwd=svn_root),
1801       Cmd("git checkout -f master", ""),
1802       Cmd("git branch", "auto-bump-up-version\n* master"),
1803       Cmd("git branch -D auto-bump-up-version", ""),
1804     ]
1805     self.Expect(expectations)
1806
1807     BumpUpVersion(TEST_CONFIG, self).Run(
1808         ["-a", "author@chromium.org",
1809          "--svn", svn_root,
1810          "--svn-config", "[CONFIG_DIR]"])
1811
1812   # Test that we bail out if the last change was a version change.
1813   def testBumpUpVersionBailout1(self):
1814     self._state["latest"] = "latest_hash"
1815
1816     self.Expect([
1817       Cmd("git diff --name-only latest_hash latest_hash^", VERSION_FILE),
1818     ])
1819
1820     self.assertEquals(0,
1821         self.RunStep(BumpUpVersion, LastChangeBailout, ["--dry_run"]))
1822
1823   # Test that we bail out if the lkgr was a version change.
1824   def testBumpUpVersionBailout2(self):
1825     self._state["lkgr"] = "lkgr_hash"
1826
1827     self.Expect([
1828       Cmd("git diff --name-only lkgr_hash lkgr_hash^", VERSION_FILE),
1829     ])
1830
1831     self.assertEquals(0,
1832         self.RunStep(BumpUpVersion, LKGRVersionUpToDateBailout, ["--dry_run"]))
1833
1834   # Test that we bail out if the last version is already newer than the lkgr's
1835   # version.
1836   def testBumpUpVersionBailout3(self):
1837     self._state["lkgr"] = "lkgr_hash"
1838     self._state["lkgr_version"] = "3.22.4.0"
1839     self._state["latest_version"] = "3.22.5.0"
1840
1841     self.Expect([
1842       Cmd("git diff --name-only lkgr_hash lkgr_hash^", ""),
1843     ])
1844
1845     self.assertEquals(0,
1846         self.RunStep(BumpUpVersion, LKGRVersionUpToDateBailout, ["--dry_run"]))
1847
1848
1849 class SystemTest(unittest.TestCase):
1850   def testReload(self):
1851     options = ScriptsBase(
1852         TEST_CONFIG, DEFAULT_SIDE_EFFECT_HANDLER, {}).MakeOptions([])
1853     step = MakeStep(step_class=PrepareChangeLog, number=0, state={}, config={},
1854                     options=options,
1855                     side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER)
1856     body = step.Reload(
1857 """------------------------------------------------------------------------
1858 r17997 | machenbach@chromium.org | 2013-11-22 11:04:04 +0100 (...) | 6 lines
1859
1860 Prepare push to trunk.  Now working on version 3.23.11.
1861
1862 R=danno@chromium.org
1863
1864 Review URL: https://codereview.chromium.org/83173002
1865
1866 ------------------------------------------------------------------------""")
1867     self.assertEquals(
1868 """Prepare push to trunk.  Now working on version 3.23.11.
1869
1870 R=danno@chromium.org
1871
1872 Committed: https://code.google.com/p/v8/source/detail?r=17997""", body)