def test_stabletimer(self): m, cm, sm = self.build_harness("db/scheduler/stabletimer") s = Scheduler("one", branch=None, treeStableTimer=30, builderNames=["builder-one"]) d = sm.updateSchedulers([s]) # there are no changes in the database, so the scheduler should want # to keep sleeping. d.addCallback(lambda ign: s.run()) def _sleep_forever_not_build(res): self.failUnlessEqual(res, None) pending = self.get_buildrequests(m, cm) self.failIf(pending) d.addCallback(_sleep_forever_not_build) # now add one change. The scheduler should want to wait for the # tree-stable timer to fire. c1 = Change(who="brian", files=["foo.c"], comments="first change", revision="1234") d.addCallback(lambda ign: cm.addChange(c1)) d.addCallback(lambda ign: s.run()) def _sleep_not_build(res): # the scheduler should tell us that they want to be woken up in # 30 seconds. This test would be much too fragile if we actually # asserted anything about its value, though. self.failUnlessEqual(type(res), float) pending = self.get_buildrequests(m, cm) self.failIf(pending) d.addCallback(_sleep_not_build) # running it again should tell us roughly the same thing d.addCallback(lambda ign: s.run()) d.addCallback(_sleep_not_build) def _reduce_timer(res): # artificially lower the tree-stable-timer value s.treeStableTimer = 0 d.addCallback(_reduce_timer) d.addCallback(lambda ign: s.run()) def _build_not_sleep(res): # a BuildRequest should be pushed, and the Scheduler should go # back to sleep self.failUnlessEqual(res, None) pending = self.get_buildrequests(m, cm) self.failUnlessEqual(len(pending), 1) changes = pending[0][1].changes self.failUnlessEqual(len(changes), 1) self.failUnlessEqual(changes[0].revision, "1234") self.failUnlessEqual(changes[0].files, ["foo.c"]) d.addCallback(_build_not_sleep) return d
def test_many_changes(self): m, cm, sm = self.build_harness("db/scheduler/many_changes") s = Scheduler("one", branch=None, treeStableTimer=0.01, builderNames=["builder-one"]) d = sm.updateSchedulers([s]) # add ten changes, then process them all at once. Sometimes the # database connector has problems with lots of queries happening # simultaneously. for i in range(10): c = Change(who="brian", files=["foo%d.txt" % i], comments="change %d" % i, revision="%d" % (i+10)) d.addCallback(lambda ign, c=c: cm.addChange(c)) d.addCallback(self.stall, 1.0) d.addCallback(lambda ign: s.run()) def _build_not_sleep(res): # a BuildRequest should be pushed, and the Scheduler should go # back to sleep self.failUnlessEqual(res, None) pending = self.get_buildrequests(m, cm) self.failUnlessEqual(len(pending), 1) changes = pending[0][1].changes self.failUnlessEqual(len(changes), 10) d.addCallback(_build_not_sleep) return d
class TestTestOrder(unittest.TestCase): """Tests that tests are run according to their corresponding build's start time""" basedir = "test_test_order" def setUp(self): if os.path.exists(self.basedir): shutil.rmtree(self.basedir) os.makedirs(self.basedir) spec = dbspec.DBSpec.from_url("sqlite:///state.sqlite", self.basedir) manager = DBSchemaManager(spec, self.basedir) manager.upgrade() self.dbc = connector.DBConnector(spec) self.dbc.start() parent = mock.Mock() parent.db = self.dbc change_manager = ChangeManager() change_manager.parent = parent parent.change_svc = change_manager self.s = Scheduler(name="s", builderNames=["b1"]) self.s.parent = parent return self.dbc.addSchedulers([self.s]) def makeBuilder(self, klass): dummy_factory = klass([Dummy()]) builder = { 'name': 'b1', 'slavenames': ['s1'], 'builddir': 'b1', 'slavebuilddir': 'b1', 'factory': dummy_factory, } builder_status = mock.Mock() builder = Builder(builder, builder_status) builder.running = True builder.db = self.dbc builder.master_name = 'test_master' builder.master_incarnation = '12345' builder.botmaster = mock.Mock() builder.botmaster.shouldMergeRequests.return_value = True return builder def tearDown(self): self.dbc.stop() shutil.rmtree(self.basedir) def test_singleRequest(self): # Easy peasy c1 = Change(who='me!', branch='b1', revision='1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}) self.dbc.addChangeToDatabase(c1) builder = self.makeBuilder(BuildFactory) # Run the scheduler d = self.s.run() # Check that we have a build request def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 1) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 1) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, '1') changes = build.source.changes self.assertEquals(changes[0].revision, '1') return d.addCallback(startBuild) return d def test_threeRequests(self): # Three changes, r1, r2, r3 # They start in order, and finish in reverse order # We want the to be testing r3 in the end c1 = Change(who='me!', branch='b1', revision='r3', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000003'}, when=4) c2 = Change(who='me!', branch='b1', revision='r2', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000002'}, when=5) c3 = Change(who='me!', branch='b1', revision='r1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}, when=6) self.dbc.addChangeToDatabase(c1) self.dbc.addChangeToDatabase(c2) self.dbc.addChangeToDatabase(c3) # Run the scheduler d = self.s.run() builder = self.makeBuilder(RequestSortingBuildFactory) # Check that we have three build requests def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 3) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 3) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, 'r3') changes = build.source.changes # The last revision should be r3, since it started latest self.assertEquals(changes[0].revision, 'r1') self.assertEquals(changes[1].revision, 'r2') self.assertEquals(changes[2].revision, 'r3') return d.addCallback(startBuild) return d def test_threeRequestsUnsorted(self): # Three changes, r1, r2, r3 # They start in order, and finish in reverse order # We want the to be testing r3 in the end c1 = Change(who='me!', branch='b1', revision='r3', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000003'}, when=4) c2 = Change(who='me!', branch='b1', revision='r2', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000002'}, when=5) c3 = Change(who='me!', branch='b1', revision='r1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}, when=6) self.dbc.addChangeToDatabase(c1) self.dbc.addChangeToDatabase(c2) self.dbc.addChangeToDatabase(c3) # Run the scheduler d = self.s.run() builder = self.makeBuilder(BuildFactory) # Check that we have three build requests def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 3) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 3) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, 'r1') changes = build.source.changes # The last revision should be r1, since it was submitted latest self.assertEquals(changes[0].revision, 'r3') self.assertEquals(changes[1].revision, 'r2') self.assertEquals(changes[2].revision, 'r1') return d.addCallback(startBuild) return d def test_threeRequestsManual(self): # Three changes, r1, r2, r3 # r2, and r3 have buildids # r1 is manually triggered, and is submitted later # we want to be testing r1 in the end c1 = Change(who='me!', branch='b1', revision='r3', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000003'}, when=4) c2 = Change(who='me!', branch='b1', revision='r2', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000002'}, when=5) c3 = Change(who='me!', branch='b1', revision='r1', files=['http://path/to/build'], comments='really important', when=6) self.dbc.addChangeToDatabase(c1) self.dbc.addChangeToDatabase(c2) self.dbc.addChangeToDatabase(c3) # Run the scheduler d = self.s.run() builder = self.makeBuilder(RequestSortingBuildFactory) # Check that we have three build requests def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 3) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 3) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, 'r1') changes = build.source.changes # The last revision should be r1, since it was manually triggered later self.assertEquals(changes[0].revision, 'r2') self.assertEquals(changes[1].revision, 'r3') self.assertEquals(changes[2].revision, 'r1') return d.addCallback(startBuild) return d def test_Rebuilds(self): # Two changes, r2, r3 # They start in order, and finish in reverse order # We also have a pending request to re-build r1 that happens after r2, r3 have started # We want to end up re-building r1 c1 = Change(who='me!', branch='b1', revision='r3', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000003'}, when=4) c2 = Change(who='me!', branch='b1', revision='r2', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000002'}, when=5) self.dbc.addChangeToDatabase(c1) self.dbc.addChangeToDatabase(c2) # Run the scheduler d = self.s.run() # Rebuild r1 def addRebuild(t): c3 = Change(who='me!', branch='b1', revision='r1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}, when=6) self.dbc.addChangeToDatabase(c3) ss = SourceStamp(branch='b1', changes=[c3], revision='r1') ss1 = ss.getAbsoluteSourceStamp('r1') ssid = self.dbc.get_sourcestampid(ss, t) bsid = self.dbc.create_buildset(ssid, "rebuild", Properties(), ["b1"], t) d.addCallback(lambda ign: self.dbc.runInteractionNow(addRebuild)) builder = self.makeBuilder(RequestSortingBuildFactory) # Check that we have three build requests def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 3) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 3) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, 'r1') changes = build.source.changes # The last revision should be r1, since it was manually triggered later self.assertEquals(changes[0].revision, 'r2') self.assertEquals(changes[1].revision, 'r3') self.assertEquals(changes[2].revision, 'r1') return d.addCallback(startBuild) return d def test_brokenRequest(self): c1 = Change(who='me!', branch='b1', revision='1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}) self.dbc.addChangeToDatabase(c1) builder = self.makeBuilder(RequestSortingBuildFactory) # Run the scheduler d = self.s.run() # Check that we have a build request def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 1) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] # Hack the request to break the sorting requests[0].submittedAt = "asdf" requests[0].reason = "rebuild" self.assertEquals(len(requests), 1) build = builder.buildFactory.newBuild(requests) # This should have generated an error self.failUnless(len(self.flushLoggedErrors()) == 1) self.assertEquals(build.source.revision, '1') changes = build.source.changes self.assertEquals(changes[0].revision, '1') return d.addCallback(startBuild) return d
def test_immediate(self): m, cm, sm = self.build_harness("db/scheduler/immediate") def fileIsImportant(c): for fn in c.files: if not fn.endswith(".txt"): return True return False # we set the treeStableTimer to something tiny, since "None" has a # special meaning ("do not merge Changes") s = Scheduler("one", branch=None, treeStableTimer=0.01, builderNames=["builder-one"], fileIsImportant=fileIsImportant) d = sm.updateSchedulers([s]) # there are no changes in the database, so the scheduler should want # to keep sleeping. d.addCallback(lambda ign: s.run()) def _sleep_forever_not_build(res): self.failUnlessEqual(res, None) pending = self.get_buildrequests(m, cm) self.failIf(pending) d.addCallback(_sleep_forever_not_build) # now add one change. The change is "unimportant", so no build will # be run. c1 = Change(who="brian", files=["docs.txt"], comments="doc change", revision="1234") d.addCallback(lambda ign: cm.addChange(c1)) d.addCallback(lambda ign: s.run()) d.addCallback(_sleep_forever_not_build) # running it again should tell us the same thing d.addCallback(lambda ign: s.run()) d.addCallback(_sleep_forever_not_build) # now add a second change which evaluates as "important", which # should trigger a build with both changes after the treeStableTimer # has passed, which should be quickly c2 = Change(who="brian", files=["foo.c", "subdir/bar.c"], comments="second change", revision="1235") d.addCallback(lambda ign: cm.addChange(c2)) # stall here to let the treeStableTimer expire d.addCallback(self.stall, 1.0) d.addCallback(lambda ign: s.run()) def _build_not_sleep(res): # a BuildRequest should be pushed, and the Scheduler should go # back to sleep self.failUnlessEqual(res, None) pending = self.get_buildrequests(m, cm) self.failUnlessEqual(len(pending), 1) changes = pending[0][1].changes self.failUnlessEqual(len(changes), 2) self.failUnlessEqual(changes[0].revision, "1234") self.failUnlessEqual(changes[0].files, ["docs.txt"]) self.failUnlessEqual(changes[1].revision, "1235") self.failUnlessIn("foo.c", changes[1].files) self.failUnlessIn("subdir/bar.c", changes[1].files) d.addCallback(_build_not_sleep) # running it again should not do anything d.addCallback(lambda ign: s.run()) def _build_and_sleep(res): self.failUnlessEqual(res, None) pending = self.get_buildrequests(m, cm) self.failUnlessEqual(len(pending), 1) d.addCallback(_build_and_sleep) return d
class TestTestOrder(unittest.TestCase): """Tests that tests are run according to their corresponding build's start time""" basedir = "test_test_order" def setUp(self): if os.path.exists(self.basedir): shutil.rmtree(self.basedir) os.makedirs(self.basedir) spec = dbspec.DBSpec.from_url("sqlite:///state.sqlite", self.basedir) manager = DBSchemaManager(spec, self.basedir) manager.upgrade() self.dbc = connector.DBConnector(spec) self.dbc.start() parent = mock.Mock() parent.db = self.dbc change_manager = ChangeManager() change_manager.parent = parent parent.change_svc = change_manager self.s = Scheduler(name="s", builderNames=["b1"]) self.s.parent = parent return self.dbc.addSchedulers([self.s]) def makeBuilder(self, klass): dummy_factory = klass([Dummy()]) builder = { 'name': 'b1', 'slavenames': ['s1'], 'builddir': 'b1', 'slavebuilddir': 'b1', 'factory': dummy_factory, } builder_status = mock.Mock() builder = Builder(builder, builder_status) builder.running = True builder.db = self.dbc builder.master_name = 'test_master' builder.master_incarnation = '12345' builder.botmaster = mock.Mock() builder.botmaster.shouldMergeRequests.return_value = True return builder def tearDown(self): self.dbc.stop() shutil.rmtree(self.basedir) def test_singleRequest(self): # Easy peasy c1 = Change(who='me!', branch='b1', revision='1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}) self.dbc.addChangeToDatabase(c1) builder = self.makeBuilder(BuildFactory) # Run the scheduler d = self.s.run() # Check that we have a build request def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 1) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 1) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, '1') changes = build.source.changes self.assertEquals(changes[0].revision, '1') return d.addCallback(startBuild) return d def test_threeRequests(self): # Three changes, r1, r2, r3 # They start in order, and finish in reverse order # We want the to be testing r3 in the end c1 = Change(who='me!', branch='b1', revision='r3', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000003'}, when=4) c2 = Change(who='me!', branch='b1', revision='r2', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000002'}, when=5) c3 = Change(who='me!', branch='b1', revision='r1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}, when=6) self.dbc.addChangeToDatabase(c1) self.dbc.addChangeToDatabase(c2) self.dbc.addChangeToDatabase(c3) # Run the scheduler d = self.s.run() builder = self.makeBuilder(RequestSortingBuildFactory) # Check that we have three build requests def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 3) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 3) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, 'r3') changes = build.source.changes # The last revision should be r3, since it started latest self.assertEquals(changes[0].revision, 'r1') self.assertEquals(changes[1].revision, 'r2') self.assertEquals(changes[2].revision, 'r3') return d.addCallback(startBuild) return d def test_threeRequestsUnsorted(self): # Three changes, r1, r2, r3 # They start in order, and finish in reverse order # We want the to be testing r3 in the end c1 = Change(who='me!', branch='b1', revision='r3', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000003'}, when=4) c2 = Change(who='me!', branch='b1', revision='r2', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000002'}, when=5) c3 = Change(who='me!', branch='b1', revision='r1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}, when=6) self.dbc.addChangeToDatabase(c1) self.dbc.addChangeToDatabase(c2) self.dbc.addChangeToDatabase(c3) # Run the scheduler d = self.s.run() builder = self.makeBuilder(BuildFactory) # Check that we have three build requests def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 3) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 3) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, 'r1') changes = build.source.changes # The last revision should be r1, since it was submitted latest self.assertEquals(changes[0].revision, 'r3') self.assertEquals(changes[1].revision, 'r2') self.assertEquals(changes[2].revision, 'r1') return d.addCallback(startBuild) return d def test_threeRequestsManual(self): # Three changes, r1, r2, r3 # r2, and r3 have buildids # r1 is manually triggered, and is submitted later # we want to be testing r1 in the end c1 = Change(who='me!', branch='b1', revision='r3', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000003'}, when=4) c2 = Change(who='me!', branch='b1', revision='r2', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000002'}, when=5) c3 = Change(who='me!', branch='b1', revision='r1', files=['http://path/to/build'], comments='really important', when=6) self.dbc.addChangeToDatabase(c1) self.dbc.addChangeToDatabase(c2) self.dbc.addChangeToDatabase(c3) # Run the scheduler d = self.s.run() builder = self.makeBuilder(RequestSortingBuildFactory) # Check that we have three build requests def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 3) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 3) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, 'r1') changes = build.source.changes # The last revision should be r1, since it was manually triggered # later self.assertEquals(changes[0].revision, 'r2') self.assertEquals(changes[1].revision, 'r3') self.assertEquals(changes[2].revision, 'r1') return d.addCallback(startBuild) return d def test_Rebuilds(self): # Two changes, r2, r3 # They start in order, and finish in reverse order # We also have a pending request to re-build r1 that happens after r2, r3 have started # We want to end up re-building r1 c1 = Change(who='me!', branch='b1', revision='r3', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000003'}, when=4) c2 = Change(who='me!', branch='b1', revision='r2', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000002'}, when=5) self.dbc.addChangeToDatabase(c1) self.dbc.addChangeToDatabase(c2) # Run the scheduler d = self.s.run() # Rebuild r1 def addRebuild(t): c3 = Change(who='me!', branch='b1', revision='r1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}, when=6) self.dbc.addChangeToDatabase(c3) ss = SourceStamp(branch='b1', changes=[c3], revision='r1') ssid = self.dbc.get_sourcestampid(ss, t) self.dbc.create_buildset(ssid, "rebuild", Properties(), ["b1"], t) d.addCallback(lambda ign: self.dbc.runInteractionNow(addRebuild)) builder = self.makeBuilder(RequestSortingBuildFactory) # Check that we have three build requests def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 3) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] self.assertEquals(len(requests), 3) build = builder.buildFactory.newBuild(requests) self.assertEquals(build.source.revision, 'r1') changes = build.source.changes # The last revision should be r1, since it was manually triggered # later self.assertEquals(changes[0].revision, 'r2') self.assertEquals(changes[1].revision, 'r3') self.assertEquals(changes[2].revision, 'r1') return d.addCallback(startBuild) return d def test_brokenRequest(self): c1 = Change(who='me!', branch='b1', revision='1', files=['http://path/to/build'], comments='really important', properties={'buildid': '20110214000001'}) self.dbc.addChangeToDatabase(c1) builder = self.makeBuilder(RequestSortingBuildFactory) # Run the scheduler d = self.s.run() # Check that we have a build request def checkRequests(ign): req = self.dbc.runQueryNow("select count(*) from buildrequests") self.assertEquals(req[0][0], 1) d.addCallback(checkRequests) # Claim the request def claimRequest(ign): d = self.dbc.runInteraction(builder._claim_buildreqs, ["slave!"]) return d d.addCallback(claimRequest) # Start the build! def startBuild(assignments): self.assertEquals(len(assignments.keys()), 1) requests = assignments.values()[0] # Hack the request to break the sorting requests[0].submittedAt = "asdf" requests[0].reason = "rebuild" self.assertEquals(len(requests), 1) build = builder.buildFactory.newBuild(requests) # This should have generated an error self.failUnless(len(self.flushLoggedErrors()) == 1) self.assertEquals(build.source.revision, '1') changes = build.source.changes self.assertEquals(changes[0].revision, '1') return d.addCallback(startBuild) return d