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