| Index: third_party/buildbot_7_12/buildbot/test/test_run.py
|
| diff --git a/third_party/buildbot_7_12/buildbot/test/test_run.py b/third_party/buildbot_7_12/buildbot/test/test_run.py
|
| deleted file mode 100644
|
| index b2a74ad04212d367f886eab7af1e6fabe5788c03..0000000000000000000000000000000000000000
|
| --- a/third_party/buildbot_7_12/buildbot/test/test_run.py
|
| +++ /dev/null
|
| @@ -1,1261 +0,0 @@
|
| -# -*- test-case-name: buildbot.test.test_run -*-
|
| -
|
| -from twisted.trial import unittest
|
| -from twisted.internet import reactor, defer
|
| -import os
|
| -
|
| -from buildbot import master, interfaces
|
| -from buildbot.sourcestamp import SourceStamp
|
| -from buildbot.changes import changes
|
| -from buildbot.status import builder
|
| -from buildbot.process.base import BuildRequest
|
| -
|
| -from buildbot.test.runutils import RunMixin, TestFlagMixin, rmtree
|
| -
|
| -config_base = """
|
| -from buildbot.process import factory
|
| -from buildbot.steps import dummy
|
| -from buildbot.buildslave import BuildSlave
|
| -from buildbot.config import BuilderConfig
|
| -s = factory.s
|
| -
|
| -f1 = factory.QuickBuildFactory('fakerep', 'cvsmodule', configure=None)
|
| -
|
| -f2 = factory.BuildFactory([
|
| - dummy.Dummy(timeout=1),
|
| - dummy.RemoteDummy(timeout=2),
|
| - ])
|
| -
|
| -BuildmasterConfig = c = {}
|
| -c['slaves'] = [BuildSlave('bot1', 'sekrit')]
|
| -c['schedulers'] = []
|
| -c['builders'] = [
|
| - BuilderConfig(name='quick', slavename='bot1', factory=f1,
|
| - builddir='quickdir', slavebuilddir='slavequickdir'),
|
| -]
|
| -c['slavePortnum'] = 0
|
| -"""
|
| -
|
| -config_run = config_base + """
|
| -from buildbot.scheduler import Scheduler
|
| -c['schedulers'] = [Scheduler('quick', None, 120, ['quick'])]
|
| -"""
|
| -
|
| -config_can_build = config_base + """
|
| -from buildbot.buildslave import BuildSlave
|
| -c['slaves'] = [ BuildSlave('bot1', 'sekrit') ]
|
| -
|
| -from buildbot.scheduler import Scheduler
|
| -c['schedulers'] = [Scheduler('dummy', None, 0.1, ['dummy'])]
|
| -
|
| -c['builders'] = [
|
| - BuilderConfig(name='dummy', slavename='bot1',
|
| - factory=f2, builddir='dummy1'),
|
| -]
|
| -"""
|
| -
|
| -config_cant_build = config_can_build + """
|
| -class MyBuildSlave(BuildSlave):
|
| - def canStartBuild(self): return False
|
| -c['slaves'] = [ MyBuildSlave('bot1', 'sekrit') ]
|
| -"""
|
| -
|
| -config_concurrency = config_base + """
|
| -from buildbot.buildslave import BuildSlave
|
| -c['slaves'] = [ BuildSlave('bot1', 'sekrit', max_builds=1) ]
|
| -
|
| -from buildbot.scheduler import Scheduler
|
| -c['schedulers'] = [Scheduler('dummy', None, 0.1, ['dummy', 'dummy2'])]
|
| -
|
| -c['builders'] = c['builders'] + [
|
| - BuilderConfig(name='dummy', slavename='bot1', factory=f2),
|
| - BuilderConfig(name='dummy2', slavename='bot1', factory=f2),
|
| -]
|
| -"""
|
| -
|
| -config_2 = config_base + """
|
| -c['builders'] = [
|
| - BuilderConfig(name='dummy', slavename='bot1',
|
| - builddir='dummy1', factory=f2),
|
| - BuilderConfig(name='test dummy', slavename='bot1',
|
| - factory=f2, category='test'),
|
| -]
|
| -"""
|
| -
|
| -config_3 = config_2 + """
|
| -c['builders'] = c['builders'] + [
|
| - BuilderConfig(name='adummy', slavename='bot1',
|
| - builddir='adummy3', factory=f2),
|
| - BuilderConfig(name='bdummy', slavename='bot1',
|
| - builddir='adummy4', factory=f2,
|
| - category='test'),
|
| -]
|
| -"""
|
| -
|
| -config_4 = config_base + """
|
| -c['builders'] = [
|
| - BuilderConfig(name='dummy', slavename='bot1',
|
| - slavebuilddir='sdummy', factory=f2),
|
| -]
|
| -"""
|
| -
|
| -config_4_newbasedir = config_4 + """
|
| -c['builders'] = [
|
| - BuilderConfig(name='dummy', slavename='bot1',
|
| - builddir='dummy2', factory=f2),
|
| -]
|
| -"""
|
| -
|
| -config_4_newbuilder = config_4_newbasedir + """
|
| -c['builders'] = c['builders'] + [
|
| - BuilderConfig(name='dummy2', slavename='bot1',
|
| - builddir='dummy23', factory=f2),
|
| -]
|
| -"""
|
| -
|
| -class Run(unittest.TestCase):
|
| - def rmtree(self, d):
|
| - rmtree(d)
|
| -
|
| - def testMaster(self):
|
| - self.rmtree("basedir")
|
| - os.mkdir("basedir")
|
| - m = master.BuildMaster("basedir")
|
| - m.loadConfig(config_run)
|
| - m.readConfig = True
|
| - m.startService()
|
| - cm = m.change_svc
|
| - c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed stuff")
|
| - cm.addChange(c)
|
| - # verify that the Scheduler is now waiting
|
| - s = m.allSchedulers()[0]
|
| - self.failUnless(s.timer)
|
| - # halting the service will also stop the timer
|
| - d = defer.maybeDeferred(m.stopService)
|
| - return d
|
| -
|
| -class CanStartBuild(RunMixin, unittest.TestCase):
|
| - def rmtree(self, d):
|
| - rmtree(d)
|
| -
|
| - def testCanStartBuild(self):
|
| - return self.do_test(config_can_build, True)
|
| -
|
| - def testCantStartBuild(self):
|
| - return self.do_test(config_cant_build, False)
|
| -
|
| - def do_test(self, config, builder_should_run):
|
| - self.master.loadConfig(config)
|
| - self.master.readConfig = True
|
| - self.master.startService()
|
| - d = self.connectSlave()
|
| -
|
| - # send a change
|
| - cm = self.master.change_svc
|
| - c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed stuff")
|
| - cm.addChange(c)
|
| -
|
| - d.addCallback(self._do_test1, builder_should_run)
|
| -
|
| - return d
|
| -
|
| - def _do_test1(self, res, builder_should_run):
|
| - # delay a little bit. Note that relying upon timers is a bit fragile,
|
| - # in this case we're hoping that our 0.5 second timer will land us
|
| - # somewhere in the middle of the [0.1s, 3.1s] window (after the 0.1
|
| - # second Scheduler fires, then during the 3-second build), so that
|
| - # when we sample BuildSlave.state, we'll see BUILDING (or IDLE if the
|
| - # slave was told to be unavailable). On a heavily loaded system, our
|
| - # 0.5 second timer might not actually fire until after the build has
|
| - # completed. In the long run, it would be good to change this test to
|
| - # pass under those circumstances too.
|
| - d = defer.Deferred()
|
| - reactor.callLater(.5, d.callback, builder_should_run)
|
| - d.addCallback(self._do_test2)
|
| - return d
|
| -
|
| - def _do_test2(self, builder_should_run):
|
| - b = self.master.botmaster.builders['dummy']
|
| - self.failUnless(len(b.slaves) == 1)
|
| -
|
| - bs = b.slaves[0]
|
| - from buildbot.process.builder import IDLE, BUILDING
|
| - if builder_should_run:
|
| - self.failUnlessEqual(bs.state, BUILDING)
|
| - else:
|
| - self.failUnlessEqual(bs.state, IDLE)
|
| -
|
| -
|
| -class ConcurrencyLimit(RunMixin, unittest.TestCase):
|
| -
|
| - def testConcurrencyLimit(self):
|
| - d = self.master.loadConfig(config_concurrency)
|
| - d.addCallback(lambda res: self.master.startService())
|
| - d.addCallback(lambda res: self.connectSlave())
|
| -
|
| - def _send(res):
|
| - # send a change. This will trigger both builders at the same
|
| - # time, but since they share a slave, the max_builds=1 setting
|
| - # will insure that only one of the two builds gets to run.
|
| - cm = self.master.change_svc
|
| - c = changes.Change("bob", ["Makefile", "foo/bar.c"],
|
| - "changed stuff")
|
| - cm.addChange(c)
|
| - d.addCallback(_send)
|
| -
|
| - def _delay(res):
|
| - d1 = defer.Deferred()
|
| - reactor.callLater(1, d1.callback, None)
|
| - # this test depends upon this 1s delay landing us in the middle
|
| - # of one of the builds.
|
| - return d1
|
| - d.addCallback(_delay)
|
| -
|
| - def _check(res):
|
| - builders = [ self.master.botmaster.builders[bn]
|
| - for bn in ('dummy', 'dummy2') ]
|
| - for builder in builders:
|
| - self.failUnless(len(builder.slaves) == 1)
|
| -
|
| - from buildbot.process.builder import BUILDING
|
| - building_bs = [ builder
|
| - for builder in builders
|
| - if builder.slaves[0].state == BUILDING ]
|
| - # assert that only one build is running right now. If the
|
| - # max_builds= weren't in effect, this would be 2.
|
| - self.failUnlessEqual(len(building_bs), 1)
|
| - d.addCallback(_check)
|
| -
|
| - return d
|
| -
|
| -
|
| -class Ping(RunMixin, unittest.TestCase):
|
| - def testPing(self):
|
| - self.master.loadConfig(config_2)
|
| - self.master.readConfig = True
|
| - self.master.startService()
|
| -
|
| - d = self.connectSlave()
|
| - d.addCallback(self._testPing_1)
|
| - return d
|
| -
|
| - def _testPing_1(self, res):
|
| - d = interfaces.IControl(self.master).getBuilder("dummy").ping()
|
| - d.addCallback(self._testPing_2)
|
| - return d
|
| -
|
| - def _testPing_2(self, res):
|
| - pass
|
| -
|
| -class BuilderNames(unittest.TestCase):
|
| -
|
| - def testGetBuilderNames(self):
|
| - os.mkdir("bnames")
|
| - m = master.BuildMaster("bnames")
|
| - s = m.getStatus()
|
| -
|
| - m.loadConfig(config_3)
|
| - m.readConfig = True
|
| -
|
| - self.failUnlessEqual(s.getBuilderNames(),
|
| - ["dummy", "test dummy", "adummy", "bdummy"])
|
| - self.failUnlessEqual(s.getBuilderNames(categories=['test']),
|
| - ["test dummy", "bdummy"])
|
| -
|
| -class Disconnect(RunMixin, unittest.TestCase):
|
| -
|
| - def setUp(self):
|
| - RunMixin.setUp(self)
|
| -
|
| - # verify that disconnecting the slave during a build properly
|
| - # terminates the build
|
| - m = self.master
|
| - s = self.status
|
| - c = self.control
|
| -
|
| - m.loadConfig(config_2)
|
| - m.readConfig = True
|
| - m.startService()
|
| -
|
| - self.failUnlessEqual(s.getBuilderNames(), ["dummy", "test dummy"])
|
| - self.s1 = s1 = s.getBuilder("dummy")
|
| - self.failUnlessEqual(s1.getName(), "dummy")
|
| - self.failUnlessEqual(s1.getState(), ("offline", []))
|
| - self.failUnlessEqual(s1.getCurrentBuilds(), [])
|
| - self.failUnlessEqual(s1.getLastFinishedBuild(), None)
|
| - self.failUnlessEqual(s1.getBuild(-1), None)
|
| -
|
| - d = self.connectSlave()
|
| - d.addCallback(self._disconnectSetup_1)
|
| - return d
|
| -
|
| - def _disconnectSetup_1(self, res):
|
| - self.failUnlessEqual(self.s1.getState(), ("idle", []))
|
| -
|
| -
|
| - def verifyDisconnect(self, bs):
|
| - self.failUnless(bs.isFinished())
|
| -
|
| - step1 = bs.getSteps()[0]
|
| - self.failUnlessEqual(step1.getText(), ["delay", "interrupted"])
|
| - self.failUnlessEqual(step1.getResults()[0], builder.FAILURE)
|
| -
|
| - self.failUnlessEqual(bs.getResults(), builder.FAILURE)
|
| -
|
| - def verifyDisconnect2(self, bs):
|
| - self.failUnless(bs.isFinished())
|
| -
|
| - step1 = bs.getSteps()[1]
|
| - self.failUnlessEqual(step1.getText(), ["remote", "delay", "2 secs",
|
| - "failed", "slave", "lost"])
|
| - self.failUnlessEqual(step1.getResults()[0], builder.EXCEPTION)
|
| -
|
| - self.failUnlessEqual(bs.getResults(), builder.EXCEPTION)
|
| -
|
| - def submitBuild(self):
|
| - ss = SourceStamp()
|
| - br = BuildRequest("forced build", ss, "dummy")
|
| - self.control.getBuilder("dummy").requestBuild(br)
|
| - d = defer.Deferred()
|
| - def _started(bc):
|
| - br.unsubscribe(_started)
|
| - d.callback(bc)
|
| - br.subscribe(_started)
|
| - return d
|
| -
|
| - def testIdle2(self):
|
| - # now suppose the slave goes missing
|
| - self.disappearSlave(allowReconnect=False)
|
| -
|
| - # forcing a build will work: the build detect that the slave is no
|
| - # longer available and will be re-queued. Wait 5 seconds, then check
|
| - # to make sure the build is still in the 'waiting for a slave' queue.
|
| - req = BuildRequest("forced build", SourceStamp(), "test_builder")
|
| - self.failUnlessEqual(req.startCount, 0)
|
| - self.control.getBuilder("dummy").requestBuild(req)
|
| - # this should ping the slave, which doesn't respond (and eventually
|
| - # times out). The BuildRequest will be re-queued, and its .startCount
|
| - # will be incremented.
|
| - self.killSlave()
|
| - d = defer.Deferred()
|
| - d.addCallback(self._testIdle2_1, req)
|
| - reactor.callLater(3, d.callback, None)
|
| - return d
|
| - testIdle2.timeout = 5
|
| -
|
| - def _testIdle2_1(self, res, req):
|
| - self.failUnlessEqual(req.startCount, 1)
|
| - cancelled = req.cancel()
|
| - self.failUnless(cancelled)
|
| -
|
| -
|
| - def testBuild1(self):
|
| - # this next sequence is timing-dependent. The dummy build takes at
|
| - # least 3 seconds to complete, and this batch of commands must
|
| - # complete within that time.
|
| - #
|
| - d = self.submitBuild()
|
| - d.addCallback(self._testBuild1_1)
|
| - return d
|
| -
|
| - def _testBuild1_1(self, bc):
|
| - bs = bc.getStatus()
|
| - # now kill the slave before it gets to start the first step
|
| - d = self.shutdownAllSlaves() # dies before it gets started
|
| - d.addCallback(self._testBuild1_2, bs)
|
| - return d # TODO: this used to have a 5-second timeout
|
| -
|
| - def _testBuild1_2(self, res, bs):
|
| - # now examine the just-stopped build and make sure it is really
|
| - # stopped. This is checking for bugs in which the slave-detach gets
|
| - # missed or causes an exception which prevents the build from being
|
| - # marked as "finished due to an error".
|
| - d = bs.waitUntilFinished()
|
| - d2 = self.master.botmaster.waitUntilBuilderDetached("dummy")
|
| - dl = defer.DeferredList([d, d2])
|
| - dl.addCallback(self._testBuild1_3, bs)
|
| - return dl # TODO: this had a 5-second timeout too
|
| -
|
| - def _testBuild1_3(self, res, bs):
|
| - self.failUnlessEqual(self.s1.getState()[0], "offline")
|
| - self.verifyDisconnect(bs)
|
| -
|
| -
|
| - def testBuild2(self):
|
| - # this next sequence is timing-dependent
|
| - d = self.submitBuild()
|
| - d.addCallback(self._testBuild2_1)
|
| - return d
|
| - testBuild2.timeout = 30
|
| -
|
| - def _testBuild2_1(self, bc):
|
| - bs = bc.getStatus()
|
| - # shutdown the slave while it's running the first step
|
| - reactor.callLater(0.5, self.shutdownAllSlaves)
|
| -
|
| - d = bs.waitUntilFinished()
|
| - d.addCallback(self._testBuild2_2, bs)
|
| - return d
|
| -
|
| - def _testBuild2_2(self, res, bs):
|
| - # we hit here when the build has finished. The builder is still being
|
| - # torn down, however, so spin for another second to allow the
|
| - # callLater(0) in Builder.detached to fire.
|
| - d = defer.Deferred()
|
| - reactor.callLater(1, d.callback, None)
|
| - d.addCallback(self._testBuild2_3, bs)
|
| - return d
|
| -
|
| - def _testBuild2_3(self, res, bs):
|
| - self.failUnlessEqual(self.s1.getState()[0], "offline")
|
| - self.verifyDisconnect(bs)
|
| -
|
| -
|
| - def testBuild3(self):
|
| - # this next sequence is timing-dependent
|
| - d = self.submitBuild()
|
| - d.addCallback(self._testBuild3_1)
|
| - return d
|
| - testBuild3.timeout = 30
|
| -
|
| - def _testBuild3_1(self, bc):
|
| - bs = bc.getStatus()
|
| - # kill the slave while it's running the first step
|
| - reactor.callLater(0.5, self.killSlave)
|
| - d = bs.waitUntilFinished()
|
| - d.addCallback(self._testBuild3_2, bs)
|
| - return d
|
| -
|
| - def _testBuild3_2(self, res, bs):
|
| - # the builder is still being torn down, so give it another second
|
| - d = defer.Deferred()
|
| - reactor.callLater(1, d.callback, None)
|
| - d.addCallback(self._testBuild3_3, bs)
|
| - return d
|
| -
|
| - def _testBuild3_3(self, res, bs):
|
| - self.failUnlessEqual(self.s1.getState()[0], "offline")
|
| - self.verifyDisconnect(bs)
|
| -
|
| -
|
| - def testBuild4(self):
|
| - # this next sequence is timing-dependent
|
| - d = self.submitBuild()
|
| - d.addCallback(self._testBuild4_1)
|
| - return d
|
| - testBuild4.timeout = 30
|
| -
|
| - def _testBuild4_1(self, bc):
|
| - bs = bc.getStatus()
|
| - # kill the slave while it's running the second (remote) step
|
| - reactor.callLater(1.5, self.killSlave)
|
| - d = bs.waitUntilFinished()
|
| - d.addCallback(self._testBuild4_2, bs)
|
| - return d
|
| -
|
| - def _testBuild4_2(self, res, bs):
|
| - # at this point, the slave is in the process of being removed, so it
|
| - # could either be 'idle' or 'offline'. I think there is a
|
| - # reactor.callLater(0) standing between here and the offline state.
|
| - #reactor.iterate() # TODO: remove the need for this
|
| -
|
| - self.failUnlessEqual(self.s1.getState()[0], "offline")
|
| - self.verifyDisconnect2(bs)
|
| -
|
| -
|
| - def testInterrupt(self):
|
| - # this next sequence is timing-dependent
|
| - d = self.submitBuild()
|
| - d.addCallback(self._testInterrupt_1)
|
| - return d
|
| - testInterrupt.timeout = 30
|
| -
|
| - def _testInterrupt_1(self, bc):
|
| - bs = bc.getStatus()
|
| - # halt the build while it's running the first step
|
| - reactor.callLater(0.5, bc.stopBuild, "bang go splat")
|
| - d = bs.waitUntilFinished()
|
| - d.addCallback(self._testInterrupt_2, bs)
|
| - return d
|
| -
|
| - def _testInterrupt_2(self, res, bs):
|
| - self.verifyDisconnect(bs)
|
| -
|
| -
|
| - def testDisappear(self):
|
| - bc = self.control.getBuilder("dummy")
|
| -
|
| - # ping should succeed
|
| - d = bc.ping()
|
| - d.addCallback(self._testDisappear_1, bc)
|
| - return d
|
| -
|
| - def _testDisappear_1(self, res, bc):
|
| - self.failUnlessEqual(res, True)
|
| -
|
| - # now, before any build is run, make the slave disappear
|
| - self.disappearSlave(allowReconnect=False)
|
| -
|
| - # initiate the ping and then kill the slave, to simulate a disconnect.
|
| - d = bc.ping()
|
| - self.killSlave()
|
| - d.addCallback(self. _testDisappear_2)
|
| - return d
|
| - def _testDisappear_2(self, res):
|
| - self.failUnlessEqual(res, False)
|
| -
|
| - def testDuplicate(self):
|
| - bc = self.control.getBuilder("dummy")
|
| - bs = self.status.getBuilder("dummy")
|
| - ss = bs.getSlaves()[0]
|
| -
|
| - self.failUnless(ss.isConnected())
|
| - self.failUnlessEqual(ss.getAdmin(), "one")
|
| -
|
| - # now, before any build is run, make the first slave disappear
|
| - self.disappearSlave(allowReconnect=False)
|
| -
|
| - d = self.master.botmaster.waitUntilBuilderDetached("dummy")
|
| - # now let the new slave take over
|
| - self.connectSlave2()
|
| - d.addCallback(self._testDuplicate_1, ss)
|
| - return d
|
| - testDuplicate.timeout = 5
|
| -
|
| - def _testDuplicate_1(self, res, ss):
|
| - d = self.master.botmaster.waitUntilBuilderAttached("dummy")
|
| - d.addCallback(self._testDuplicate_2, ss)
|
| - return d
|
| -
|
| - def _testDuplicate_2(self, res, ss):
|
| - self.failUnless(ss.isConnected())
|
| - self.failUnlessEqual(ss.getAdmin(), "two")
|
| -
|
| -
|
| -class Disconnect2(RunMixin, unittest.TestCase):
|
| -
|
| - def setUp(self):
|
| - RunMixin.setUp(self)
|
| - # verify that disconnecting the slave during a build properly
|
| - # terminates the build
|
| - m = self.master
|
| - s = self.status
|
| - c = self.control
|
| -
|
| - m.loadConfig(config_2)
|
| - m.readConfig = True
|
| - m.startService()
|
| -
|
| - self.failUnlessEqual(s.getBuilderNames(), ["dummy", "test dummy"])
|
| - self.s1 = s1 = s.getBuilder("dummy")
|
| - self.failUnlessEqual(s1.getName(), "dummy")
|
| - self.failUnlessEqual(s1.getState(), ("offline", []))
|
| - self.failUnlessEqual(s1.getCurrentBuilds(), [])
|
| - self.failUnlessEqual(s1.getLastFinishedBuild(), None)
|
| - self.failUnlessEqual(s1.getBuild(-1), None)
|
| -
|
| - d = self.connectSlaveFastTimeout()
|
| - d.addCallback(self._setup_disconnect2_1)
|
| - return d
|
| -
|
| - def _setup_disconnect2_1(self, res):
|
| - self.failUnlessEqual(self.s1.getState(), ("idle", []))
|
| -
|
| -
|
| - def testSlaveTimeout(self):
|
| - # now suppose the slave goes missing. We want to find out when it
|
| - # creates a new Broker, so we reach inside and mark it with the
|
| - # well-known sigil of impending messy death.
|
| - bd = self.slaves['bot1'].getServiceNamed("bot").builders["dummy"]
|
| - broker = bd.remote.broker
|
| - broker.redshirt = 1
|
| -
|
| - # make sure the keepalives will keep the connection up
|
| - d = defer.Deferred()
|
| - reactor.callLater(5, d.callback, None)
|
| - d.addCallback(self._testSlaveTimeout_1)
|
| - return d
|
| - testSlaveTimeout.timeout = 20
|
| -
|
| - def _testSlaveTimeout_1(self, res):
|
| - bd = self.slaves['bot1'].getServiceNamed("bot").builders["dummy"]
|
| - if not bd.remote or not hasattr(bd.remote.broker, "redshirt"):
|
| - self.fail("slave disconnected when it shouldn't have")
|
| -
|
| - d = self.master.botmaster.waitUntilBuilderDetached("dummy")
|
| - # whoops! how careless of me.
|
| - self.disappearSlave(allowReconnect=True)
|
| - # the slave will realize the connection is lost within 2 seconds, and
|
| - # reconnect.
|
| - d.addCallback(self._testSlaveTimeout_2)
|
| - return d
|
| -
|
| - def _testSlaveTimeout_2(self, res):
|
| - # the ReconnectingPBClientFactory will attempt a reconnect in two
|
| - # seconds.
|
| - d = self.master.botmaster.waitUntilBuilderAttached("dummy")
|
| - d.addCallback(self._testSlaveTimeout_3)
|
| - return d
|
| -
|
| - def _testSlaveTimeout_3(self, res):
|
| - # make sure it is a new connection (i.e. a new Broker)
|
| - bd = self.slaves['bot1'].getServiceNamed("bot").builders["dummy"]
|
| - self.failUnless(bd.remote, "hey, slave isn't really connected")
|
| - self.failIf(hasattr(bd.remote.broker, "redshirt"),
|
| - "hey, slave's Broker is still marked for death")
|
| -
|
| -
|
| -class Basedir(RunMixin, unittest.TestCase):
|
| - def testChangeBuilddir(self):
|
| - m = self.master
|
| - m.loadConfig(config_4)
|
| - m.readConfig = True
|
| - m.startService()
|
| -
|
| - d = self.connectSlave()
|
| - d.addCallback(self._testChangeBuilddir_1)
|
| - return d
|
| -
|
| - def _testChangeBuilddir_1(self, res):
|
| - self.bot = bot = self.slaves['bot1'].bot
|
| - self.builder = builder = bot.builders.get("dummy")
|
| - self.failUnless(builder)
|
| - # slavebuilddir value.
|
| - self.failUnlessEqual(builder.builddir, "sdummy")
|
| - self.failUnlessEqual(builder.basedir,
|
| - os.path.join("slavebase-bot1", "sdummy"))
|
| -
|
| - d = self.master.loadConfig(config_4_newbasedir)
|
| - d.addCallback(self._testChangeBuilddir_2)
|
| - return d
|
| -
|
| - def _testChangeBuilddir_2(self, res):
|
| - bot = self.bot
|
| - # this does NOT cause the builder to be replaced
|
| - builder = bot.builders.get("dummy")
|
| - self.failUnless(builder)
|
| - self.failUnlessIdentical(self.builder, builder)
|
| - # the basedir should be updated
|
| - self.failUnlessEqual(builder.builddir, "dummy2")
|
| - self.failUnlessEqual(builder.basedir,
|
| - os.path.join("slavebase-bot1", "dummy2"))
|
| -
|
| - # add a new builder, which causes the basedir list to be reloaded
|
| - d = self.master.loadConfig(config_4_newbuilder)
|
| - return d
|
| -
|
| -class Triggers(RunMixin, TestFlagMixin, unittest.TestCase):
|
| - config_trigger = config_base + """
|
| -from buildbot.scheduler import Triggerable, Scheduler
|
| -from buildbot.steps.trigger import Trigger
|
| -from buildbot.steps.dummy import Dummy
|
| -from buildbot.test.runutils import SetTestFlagStep
|
| -from buildbot.process.properties import WithProperties
|
| -c['schedulers'] = [
|
| - Scheduler('triggerer', None, 0.1, ['triggerer'], properties={'dyn':'dyn'}),
|
| - Triggerable('triggeree', ['triggeree'])
|
| -]
|
| -triggerer = factory.BuildFactory()
|
| -triggerer.addSteps([
|
| - SetTestFlagStep(flagname='triggerer_started'),
|
| - Trigger(flunkOnFailure=True, @ARGS@),
|
| - SetTestFlagStep(flagname='triggerer_finished'),
|
| - ])
|
| -triggeree = factory.BuildFactory([
|
| - s(SetTestFlagStep, flagname='triggeree_started'),
|
| - s(@DUMMYCLASS@),
|
| - s(SetTestFlagStep, flagname='triggeree_finished'),
|
| - ])
|
| -c['builders'] = [{'name': 'triggerer', 'slavename': 'bot1',
|
| - 'builddir': 'triggerer', 'factory': triggerer},
|
| - {'name': 'triggeree', 'slavename': 'bot1',
|
| - 'builddir': 'triggeree', 'factory': triggeree}]
|
| -"""
|
| -
|
| - def mkConfig(self, args, dummyclass="Dummy"):
|
| - return self.config_trigger.replace("@ARGS@", args).replace("@DUMMYCLASS@", dummyclass)
|
| -
|
| - def setupTest(self, args, dummyclass, checkFn):
|
| - self.clearFlags()
|
| - m = self.master
|
| - m.loadConfig(self.mkConfig(args, dummyclass))
|
| - m.readConfig = True
|
| - m.startService()
|
| -
|
| - c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed stuff")
|
| - m.change_svc.addChange(c)
|
| -
|
| - d = self.connectSlave(builders=['triggerer', 'triggeree'])
|
| - d.addCallback(self.startTimer, 0.5, checkFn)
|
| - return d
|
| -
|
| - def startTimer(self, res, time, next_fn):
|
| - d = defer.Deferred()
|
| - reactor.callLater(time, d.callback, None)
|
| - d.addCallback(next_fn)
|
| - return d
|
| -
|
| - def testTriggerBuild(self):
|
| - return self.setupTest("schedulerNames=['triggeree']",
|
| - "Dummy",
|
| - self._checkTriggerBuild)
|
| -
|
| - def _checkTriggerBuild(self, res):
|
| - self.failIfFlagNotSet('triggerer_started')
|
| - self.failIfFlagNotSet('triggeree_started')
|
| - self.failIfFlagSet('triggeree_finished')
|
| - self.failIfFlagNotSet('triggerer_finished')
|
| -
|
| - def testTriggerBuildWait(self):
|
| - return self.setupTest("schedulerNames=['triggeree'], waitForFinish=1",
|
| - "Dummy",
|
| - self._checkTriggerBuildWait)
|
| -
|
| - def _checkTriggerBuildWait(self, res):
|
| - self.failIfFlagNotSet('triggerer_started')
|
| - self.failIfFlagNotSet('triggeree_started')
|
| - self.failIfFlagSet('triggeree_finished')
|
| - self.failIfFlagSet('triggerer_finished')
|
| -
|
| - def testProperties(self):
|
| - return self.setupTest("""
|
| - schedulerNames=['triggeree'],
|
| - set_properties={'lit' : 'lit'},
|
| - copy_properties=['dyn']
|
| - """, """
|
| - SetTestFlagStep, flagname='props',
|
| - value=WithProperties('%(lit:-MISSING)s:%(dyn:-MISSING)s')
|
| - """,
|
| - self._checkProperties)
|
| -
|
| - def _checkProperties(self, res):
|
| - self.assertEqual(self.getFlag("props"), "lit:dyn")
|
| -
|
| -class PropertyPropagation(RunMixin, TestFlagMixin, unittest.TestCase):
|
| - def setupTest(self, config, builders, checkFn, changeProps={}):
|
| - self.clearFlags()
|
| - m = self.master
|
| - m.loadConfig(config)
|
| - m.readConfig = True
|
| - m.startService()
|
| -
|
| - c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed stuff",
|
| - properties=changeProps)
|
| - m.change_svc.addChange(c)
|
| -
|
| - d = self.connectSlave(builders=builders)
|
| - d.addCallback(self.startTimer, 0.5, checkFn)
|
| - return d
|
| -
|
| - def startTimer(self, res, time, next_fn):
|
| - d = defer.Deferred()
|
| - reactor.callLater(time, d.callback, None)
|
| - d.addCallback(next_fn)
|
| - return d
|
| -
|
| - config_schprop = config_base + """
|
| -from buildbot.scheduler import Scheduler
|
| -from buildbot.steps.dummy import Dummy
|
| -from buildbot.test.runutils import SetTestFlagStep
|
| -from buildbot.process.properties import WithProperties
|
| -c['schedulers'] = [
|
| - Scheduler('mysched', None, 0.1, ['flagcolor'], properties={'color':'red'}),
|
| -]
|
| -factory = factory.BuildFactory([
|
| - s(SetTestFlagStep, flagname='testresult',
|
| - value=WithProperties('color=%(color)s sched=%(scheduler)s')),
|
| - ])
|
| -c['builders'] = [{'name': 'flagcolor', 'slavename': 'bot1',
|
| - 'builddir': 'test', 'factory': factory},
|
| - ]
|
| -"""
|
| -
|
| - def testScheduler(self):
|
| - def _check(res):
|
| - self.failUnlessEqual(self.getFlag('testresult'),
|
| - 'color=red sched=mysched')
|
| - return self.setupTest(self.config_schprop, ['flagcolor'], _check)
|
| -
|
| - config_changeprop = config_base + """
|
| -from buildbot.scheduler import Scheduler
|
| -from buildbot.steps.dummy import Dummy
|
| -from buildbot.test.runutils import SetTestFlagStep
|
| -from buildbot.process.properties import WithProperties
|
| -c['schedulers'] = [
|
| - Scheduler('mysched', None, 0.1, ['flagcolor'], properties={'color':'red'}),
|
| -]
|
| -factory = factory.BuildFactory([
|
| - s(SetTestFlagStep, flagname='testresult',
|
| - value=WithProperties('color=%(color)s sched=%(scheduler)s prop1=%(prop1)s')),
|
| - ])
|
| -c['builders'] = [{'name': 'flagcolor', 'slavename': 'bot1',
|
| - 'builddir': 'test', 'factory': factory},
|
| - ]
|
| -"""
|
| -
|
| - def testChangeProp(self):
|
| - def _check(res):
|
| - self.failUnlessEqual(self.getFlag('testresult'),
|
| - 'color=blue sched=mysched prop1=prop1')
|
| - return self.setupTest(self.config_changeprop, ['flagcolor'], _check,
|
| - changeProps={'color': 'blue', 'prop1': 'prop1'})
|
| -
|
| - config_slaveprop = config_base + """
|
| -from buildbot.scheduler import Scheduler
|
| -from buildbot.steps.dummy import Dummy
|
| -from buildbot.test.runutils import SetTestFlagStep
|
| -from buildbot.process.properties import WithProperties
|
| -c['schedulers'] = [
|
| - Scheduler('mysched', None, 0.1, ['flagcolor'])
|
| -]
|
| -c['slaves'] = [BuildSlave('bot1', 'sekrit', properties={'color':'orange'})]
|
| -factory = factory.BuildFactory([
|
| - s(SetTestFlagStep, flagname='testresult',
|
| - value=WithProperties('color=%(color)s slavename=%(slavename)s')),
|
| - ])
|
| -c['builders'] = [{'name': 'flagcolor', 'slavename': 'bot1',
|
| - 'builddir': 'test', 'factory': factory},
|
| - ]
|
| -"""
|
| - def testSlave(self):
|
| - def _check(res):
|
| - self.failUnlessEqual(self.getFlag('testresult'),
|
| - 'color=orange slavename=bot1')
|
| - return self.setupTest(self.config_slaveprop, ['flagcolor'], _check)
|
| -
|
| - config_trigger = config_base + """
|
| -from buildbot.scheduler import Triggerable, Scheduler
|
| -from buildbot.steps.trigger import Trigger
|
| -from buildbot.steps.dummy import Dummy
|
| -from buildbot.test.runutils import SetTestFlagStep
|
| -from buildbot.process.properties import WithProperties
|
| -c['schedulers'] = [
|
| - Scheduler('triggerer', None, 0.1, ['triggerer'],
|
| - properties={'color':'mauve', 'pls_trigger':'triggeree'}),
|
| - Triggerable('triggeree', ['triggeree'], properties={'color':'invisible'})
|
| -]
|
| -triggerer = factory.BuildFactory([
|
| - s(SetTestFlagStep, flagname='testresult', value='wrongone'),
|
| - s(Trigger, flunkOnFailure=True,
|
| - schedulerNames=[WithProperties('%(pls_trigger)s')],
|
| - set_properties={'color' : WithProperties('%(color)s')}),
|
| - s(SetTestFlagStep, flagname='testresult', value='triggered'),
|
| - ])
|
| -triggeree = factory.BuildFactory([
|
| - s(SetTestFlagStep, flagname='testresult',
|
| - value=WithProperties('sched=%(scheduler)s color=%(color)s')),
|
| - ])
|
| -c['builders'] = [{'name': 'triggerer', 'slavename': 'bot1',
|
| - 'builddir': 'triggerer', 'factory': triggerer},
|
| - {'name': 'triggeree', 'slavename': 'bot1',
|
| - 'builddir': 'triggeree', 'factory': triggeree}]
|
| -"""
|
| - def testTrigger(self):
|
| - def _check(res):
|
| - self.failUnlessEqual(self.getFlag('testresult'),
|
| - 'sched=triggeree color=mauve')
|
| - return self.setupTest(self.config_trigger,
|
| - ['triggerer', 'triggeree'], _check)
|
| -
|
| -
|
| -config_test_flag = config_base + """
|
| -from buildbot.scheduler import Scheduler
|
| -c['schedulers'] = [Scheduler('quick', None, 0.1, ['dummy'])]
|
| -
|
| -from buildbot.test.runutils import SetTestFlagStep
|
| -f3 = factory.BuildFactory([
|
| - s(SetTestFlagStep, flagname='foo', value='bar'),
|
| - ])
|
| -
|
| -c['builders'] = [{'name': 'dummy', 'slavename': 'bot1',
|
| - 'builddir': 'dummy', 'factory': f3}]
|
| -"""
|
| -
|
| -class TestFlag(RunMixin, TestFlagMixin, unittest.TestCase):
|
| - """Test for the TestFlag functionality in runutils"""
|
| - def testTestFlag(self):
|
| - m = self.master
|
| - m.loadConfig(config_test_flag)
|
| - m.readConfig = True
|
| - m.startService()
|
| -
|
| - c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed stuff")
|
| - m.change_svc.addChange(c)
|
| -
|
| - d = self.connectSlave()
|
| - d.addCallback(self._testTestFlag_1)
|
| - return d
|
| -
|
| - def _testTestFlag_1(self, res):
|
| - d = defer.Deferred()
|
| - reactor.callLater(0.5, d.callback, None)
|
| - d.addCallback(self._testTestFlag_2)
|
| - return d
|
| -
|
| - def _testTestFlag_2(self, res):
|
| - self.failUnlessEqual(self.getFlag('foo'), 'bar')
|
| -
|
| -# TODO: test everything, from Change submission to Scheduler to Build to
|
| -# Status. Use all the status types. Specifically I want to catch recurrences
|
| -# of the bug where I forgot to make Waterfall inherit from StatusReceiver
|
| -# such that buildSetSubmitted failed.
|
| -
|
| -config_test_builder = config_base + """
|
| -from buildbot.scheduler import Scheduler
|
| -c['schedulers'] = [Scheduler('quick', 'dummy', 0.1, ['dummy']),
|
| - Scheduler('quick2', 'dummy2', 0.1, ['dummy2']),
|
| - Scheduler('quick3', 'dummy3', 0.1, ['dummy3'])]
|
| -
|
| -from buildbot.steps.shell import ShellCommand
|
| -f3 = factory.BuildFactory([
|
| - s(ShellCommand, command="sleep 3", env={'blah':'blah'})
|
| - ])
|
| -
|
| -c['builders'] = [{'name': 'dummy', 'slavename': 'bot1', 'env': {'foo':'bar'},
|
| - 'builddir': 'dummy', 'factory': f3}]
|
| -
|
| -c['builders'].append({'name': 'dummy2', 'slavename': 'bot1',
|
| - 'env': {'blah':'bar'}, 'builddir': 'dummy2',
|
| - 'factory': f3})
|
| -
|
| -f4 = factory.BuildFactory([
|
| - s(ShellCommand, command="sleep 3")
|
| - ])
|
| -
|
| -c['builders'].append({'name': 'dummy3', 'slavename': 'bot1',
|
| - 'env': {'blah':'bar'}, 'builddir': 'dummy3',
|
| - 'factory': f4})
|
| -"""
|
| -
|
| -class TestBuilder(RunMixin, unittest.TestCase):
|
| - def setUp(self):
|
| - RunMixin.setUp(self)
|
| - self.master.loadConfig(config_test_builder)
|
| - self.master.readConfig = True
|
| - self.master.startService()
|
| - self.connectSlave(builders=["dummy", "dummy2", "dummy3"])
|
| -
|
| - def doBuilderEnvTest(self, branch, cb):
|
| - c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed",
|
| - branch=branch)
|
| - self.master.change_svc.addChange(c)
|
| -
|
| - d = defer.Deferred()
|
| - reactor.callLater(0.5, d.callback, None)
|
| - d.addCallback(cb)
|
| -
|
| - return d
|
| -
|
| - def testBuilderEnv(self):
|
| - return self.doBuilderEnvTest("dummy", self._testBuilderEnv1)
|
| -
|
| - def _testBuilderEnv1(self, res):
|
| - b = self.master.botmaster.builders['dummy']
|
| - build = b.building[0]
|
| - s = build.currentStep
|
| - self.failUnless('foo' in s.cmd.args['env'])
|
| - self.failUnlessEqual('bar', s.cmd.args['env']['foo'])
|
| - self.failUnless('blah' in s.cmd.args['env'])
|
| - self.failUnlessEqual('blah', s.cmd.args['env']['blah'])
|
| -
|
| - def testBuilderEnvOverride(self):
|
| - return self.doBuilderEnvTest("dummy2", self._testBuilderEnvOverride1)
|
| -
|
| - def _testBuilderEnvOverride1(self, res):
|
| - b = self.master.botmaster.builders['dummy2']
|
| - build = b.building[0]
|
| - s = build.currentStep
|
| - self.failUnless('blah' in s.cmd.args['env'])
|
| - self.failUnlessEqual('blah', s.cmd.args['env']['blah'])
|
| -
|
| - def testBuilderNoStepEnv(self):
|
| - return self.doBuilderEnvTest("dummy3", self._testBuilderNoStepEnv1)
|
| -
|
| - def _testBuilderNoStepEnv1(self, res):
|
| - b = self.master.botmaster.builders['dummy3']
|
| - build = b.building[0]
|
| - s = build.currentStep
|
| - self.failUnless('blah' in s.cmd.args['env'])
|
| - self.failUnlessEqual('bar', s.cmd.args['env']['blah'])
|
| -
|
| -class SchedulerWatchers(RunMixin, TestFlagMixin, unittest.TestCase):
|
| - config_watchable = config_base + """
|
| -from buildbot.scheduler import AnyBranchScheduler
|
| -from buildbot.steps.dummy import Dummy
|
| -from buildbot.test.runutils import setTestFlag, SetTestFlagStep
|
| -s = AnyBranchScheduler(
|
| - name='abs',
|
| - branches=None,
|
| - treeStableTimer=0,
|
| - builderNames=['a', 'b'])
|
| -c['schedulers'] = [ s ]
|
| -
|
| -# count the number of times a success watcher is called
|
| -numCalls = [ 0 ]
|
| -def watcher(ss):
|
| - numCalls[0] += 1
|
| - setTestFlag("numCalls", numCalls[0])
|
| -s.subscribeToSuccessfulBuilds(watcher)
|
| -
|
| -f = factory.BuildFactory()
|
| -f.addStep(Dummy(timeout=0))
|
| -c['builders'] = [{'name': 'a', 'slavename': 'bot1',
|
| - 'builddir': 'a', 'factory': f},
|
| - {'name': 'b', 'slavename': 'bot1',
|
| - 'builddir': 'b', 'factory': f}]
|
| -"""
|
| -
|
| - def testWatchers(self):
|
| - self.clearFlags()
|
| - m = self.master
|
| - m.loadConfig(self.config_watchable)
|
| - m.readConfig = True
|
| - m.startService()
|
| -
|
| - c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed stuff")
|
| - m.change_svc.addChange(c)
|
| -
|
| - d = self.connectSlave(builders=['a', 'b'])
|
| -
|
| - def pause(res):
|
| - d = defer.Deferred()
|
| - reactor.callLater(1, d.callback, res)
|
| - return d
|
| - d.addCallback(pause)
|
| -
|
| - def checkFn(res):
|
| - self.failUnlessEqual(self.getFlag('numCalls'), 1)
|
| - d.addCallback(checkFn)
|
| - return d
|
| -
|
| -config_priority = """
|
| -from buildbot.process import factory
|
| -from buildbot.steps import dummy
|
| -from buildbot.buildslave import BuildSlave
|
| -s = factory.s
|
| -
|
| -from buildbot.steps.shell import ShellCommand
|
| -f1 = factory.BuildFactory([
|
| - s(ShellCommand, command="sleep 1", env={'blah':'blah'})
|
| - ])
|
| -
|
| -BuildmasterConfig = c = {}
|
| -slavenames = ['bot%i' % i for i in range(5)]
|
| -c['slaves'] = [BuildSlave(name, 'sekrit', max_builds=1) for name in slavenames]
|
| -c['schedulers'] = []
|
| -c['builders'] = []
|
| -c['builders'].append({'name':'quick1', 'slavenames':slavenames, 'builddir': 'quickdir1', 'factory': f1})
|
| -c['builders'].append({'name':'quick2', 'slavenames':slavenames, 'builddir': 'quickdir2', 'factory': f1})
|
| -c['slavePortnum'] = 0
|
| -"""
|
| -
|
| -class BuildPrioritization(RunMixin, unittest.TestCase):
|
| - def rmtree(self, d):
|
| - rmtree(d)
|
| -
|
| - def testPriority(self):
|
| - self.rmtree("basedir")
|
| - os.mkdir("basedir")
|
| - self.master.loadConfig(config_priority)
|
| - self.master.readConfig = True
|
| - self.master.startService()
|
| -
|
| - # Our fake source stamp
|
| - # we override canBeMergedWith so that our requests don't get merged together
|
| - ss = SourceStamp()
|
| - ss.canBeMergedWith = lambda x: False
|
| -
|
| - # Send 10 requests to alternating builders
|
| - # We fudge the submittedAt field after submitting since they're all
|
| - # getting submitted so close together according to time.time()
|
| - # and all we care about is what order they're run in.
|
| - reqs = []
|
| - self.start_order = []
|
| - for i in range(10):
|
| - req = BuildRequest(str(i), ss, "test_builder")
|
| - j = i % 2 + 1
|
| - self.master.botmaster.builders['quick%i' % j].submitBuildRequest(req)
|
| - req.submittedAt = i
|
| - # Keep track of what order the builds start in
|
| - def append(build):
|
| - self.start_order.append(int(build.reason))
|
| - req.subscribe(append)
|
| - reqs.append(req.waitUntilFinished())
|
| -
|
| - dl = defer.DeferredList(reqs)
|
| - dl.addCallback(self._all_finished)
|
| -
|
| - def _delay(res):
|
| - d1 = defer.Deferred()
|
| - reactor.callLater(0.5, d1.callback, None)
|
| - # this test depends upon this 0.5s delay landing us in the middle
|
| - # of one of the builds.
|
| - return d1
|
| -
|
| - def _connect(res, i):
|
| - return self.connectSlave(slavename="bot%i" % i, builders=["quick1", "quick2"])
|
| -
|
| - # Now add the slaves
|
| - d = self.connectSlave(slavename="bot0", builders=["quick1", "quick2"])
|
| - for i in range(1,5):
|
| - d.addCallback(_delay)
|
| - d.addCallback(_connect, i)
|
| -
|
| - d.addCallback(lambda x: dl)
|
| -
|
| - return d
|
| -
|
| - def _all_finished(self, *args):
|
| - # The builds should have finished in proper order
|
| - self.failUnlessEqual(self.start_order, range(10))
|
| -
|
| -# Test graceful shutdown when no builds are active, as well as
|
| -# canStartBuild after graceful shutdown is initiated
|
| -config_graceful_shutdown_idle = config_base
|
| -class GracefulShutdownIdle(RunMixin, unittest.TestCase):
|
| - def testShutdown(self):
|
| - self.rmtree("basedir")
|
| - os.mkdir("basedir")
|
| - self.master.loadConfig(config_graceful_shutdown_idle)
|
| - self.master.readConfig = True
|
| - self.master.startService()
|
| - d = self.connectSlave(builders=['quick'])
|
| - d.addCallback(self._do_shutdown)
|
| - return d
|
| -
|
| - def _do_shutdown(self, res):
|
| - bs = self.master.botmaster.builders['quick'].slaves[0]
|
| - # Check that the slave is accepting builds once it's connected
|
| - self.assertEquals(bs.slave.canStartBuild(), True)
|
| -
|
| - # Monkeypatch the slave's shutdown routine since the real shutdown
|
| - # interrupts the test harness
|
| - self.did_shutdown = False
|
| - def _shutdown():
|
| - self.did_shutdown = True
|
| - bs.slave.shutdown = _shutdown
|
| -
|
| - # Start a graceful shutdown
|
| - bs.slave.slave_status.setGraceful(True)
|
| - # Check that the slave isn't accepting builds any more
|
| - self.assertEquals(bs.slave.canStartBuild(), False)
|
| -
|
| - # Wait a little bit and then check that we (pretended to) shut down
|
| - d = defer.Deferred()
|
| - d.addCallback(self._check_shutdown)
|
| - reactor.callLater(0.5, d.callback, None)
|
| - return d
|
| -
|
| - def _check_shutdown(self, res):
|
| - self.assertEquals(self.did_shutdown, True)
|
| -
|
| -# Test graceful shutdown when two builds are active
|
| -config_graceful_shutdown_busy = config_base + """
|
| -from buildbot.buildslave import BuildSlave
|
| -c['slaves'] = [ BuildSlave('bot1', 'sekrit', max_builds=2) ]
|
| -
|
| -from buildbot.scheduler import Scheduler
|
| -c['schedulers'] = [Scheduler('dummy', None, 0.1, ['dummy', 'dummy2'])]
|
| -
|
| -c['builders'].append({'name': 'dummy', 'slavename': 'bot1',
|
| - 'builddir': 'dummy', 'factory': f2})
|
| -c['builders'].append({'name': 'dummy2', 'slavename': 'bot1',
|
| - 'builddir': 'dummy2', 'factory': f2})
|
| -"""
|
| -class GracefulShutdownBusy(RunMixin, unittest.TestCase):
|
| - def testShutdown(self):
|
| - self.rmtree("basedir")
|
| - os.mkdir("basedir")
|
| - d = self.master.loadConfig(config_graceful_shutdown_busy)
|
| - d.addCallback(lambda res: self.master.startService())
|
| - d.addCallback(lambda res: self.connectSlave())
|
| -
|
| - def _send(res):
|
| - # send a change. This will trigger both builders at the same
|
| - # time, but since they share a slave, the max_builds=1 setting
|
| - # will insure that only one of the two builds gets to run.
|
| - cm = self.master.change_svc
|
| - c = changes.Change("bob", ["Makefile", "foo/bar.c"],
|
| - "changed stuff")
|
| - cm.addChange(c)
|
| - d.addCallback(_send)
|
| -
|
| - def _delay(res):
|
| - d1 = defer.Deferred()
|
| - reactor.callLater(0.5, d1.callback, None)
|
| - # this test depends upon this 0.5s delay landing us in the middle
|
| - # of one of the builds.
|
| - return d1
|
| - d.addCallback(_delay)
|
| -
|
| - # Start a graceful shutdown. We should be in the middle of two builds
|
| - def _shutdown(res):
|
| - bs = self.master.botmaster.builders['dummy'].slaves[0]
|
| - # Monkeypatch the slave's shutdown routine since the real shutdown
|
| - # interrupts the test harness
|
| - self.did_shutdown = False
|
| - def _shutdown():
|
| - self.did_shutdown = True
|
| - return defer.succeed(None)
|
| - bs.slave.shutdown = _shutdown
|
| - # Start a graceful shutdown
|
| - bs.slave.slave_status.setGraceful(True)
|
| -
|
| - builders = [ self.master.botmaster.builders[bn]
|
| - for bn in ('dummy', 'dummy2') ]
|
| - for builder in builders:
|
| - self.failUnless(len(builder.slaves) == 1)
|
| - from buildbot.process.builder import BUILDING
|
| - building_bs = [ builder
|
| - for builder in builders
|
| - if builder.slaves[0].state == BUILDING ]
|
| - # assert that both builds are running right now.
|
| - self.failUnlessEqual(len(building_bs), 2)
|
| -
|
| - d.addCallback(_shutdown)
|
| -
|
| - # Wait a little bit again, and then make sure that we are still running
|
| - # the two builds, and haven't shutdown yet
|
| - d.addCallback(_delay)
|
| - def _check(res):
|
| - self.assertEquals(self.did_shutdown, False)
|
| - builders = [ self.master.botmaster.builders[bn]
|
| - for bn in ('dummy', 'dummy2') ]
|
| - for builder in builders:
|
| - self.failUnless(len(builder.slaves) == 1)
|
| - from buildbot.process.builder import BUILDING
|
| - building_bs = [ builder
|
| - for builder in builders
|
| - if builder.slaves[0].state == BUILDING ]
|
| - # assert that both builds are running right now.
|
| - self.failUnlessEqual(len(building_bs), 2)
|
| - d.addCallback(_check)
|
| -
|
| - # Wait for all the builds to finish
|
| - def _wait_finish(res):
|
| - builders = [ self.master.botmaster.builders[bn]
|
| - for bn in ('dummy', 'dummy2') ]
|
| - builds = []
|
| - for builder in builders:
|
| - builds.append(builder.builder_status.currentBuilds[0].waitUntilFinished())
|
| - dl = defer.DeferredList(builds)
|
| - return dl
|
| - d.addCallback(_wait_finish)
|
| -
|
| - # Wait a little bit after the builds finish, and then
|
| - # check that the slave has shutdown
|
| - d.addCallback(_delay)
|
| - def _check_shutdown(res):
|
| - # assert that we shutdown the slave
|
| - self.assertEquals(self.did_shutdown, True)
|
| - builders = [ self.master.botmaster.builders[bn]
|
| - for bn in ('dummy', 'dummy2') ]
|
| - from buildbot.process.builder import BUILDING
|
| - building_bs = [ builder
|
| - for builder in builders
|
| - if builder.slaves[0].state == BUILDING ]
|
| - # assert that no builds are running right now.
|
| - self.failUnlessEqual(len(building_bs), 0)
|
| - d.addCallback(_check_shutdown)
|
| -
|
| - return d
|
|
|