add max_builds= to BuildSlave, thanks to Dustin Mitchell. Closes #48.
[buildbot.git] / buildbot / test / test_dependencies.py
blob624efc4b84011127bbb577f58a77dfff184fe061
1 # -*- test-case-name: buildbot.test.test_dependencies -*-
3 from twisted.trial import unittest
5 from twisted.internet import reactor, defer
7 from buildbot.test.runutils import RunMixin
8 from buildbot.status import base
10 config_1 = """
11 from buildbot import scheduler
12 from buildbot.process import factory
13 from buildbot.steps import dummy
14 from buildbot.buildslave import BuildSlave
15 s = factory.s
16 from buildbot.test.test_locks import LockStep
18 BuildmasterConfig = c = {}
19 c['slaves'] = [BuildSlave('bot1', 'sekrit'), BuildSlave('bot2', 'sekrit')]
20 c['schedulers'] = []
21 c['slavePortnum'] = 0
23 # upstream1 (fastfail, slowpass)
24 # -> downstream2 (b3, b4)
25 # upstream3 (slowfail, slowpass)
26 # -> downstream4 (b3, b4)
27 # -> downstream5 (b5)
29 s1 = scheduler.Scheduler('upstream1', None, 10, ['slowpass', 'fastfail'])
30 s2 = scheduler.Dependent('downstream2', s1, ['b3', 'b4'])
31 s3 = scheduler.Scheduler('upstream3', None, 10, ['fastpass', 'slowpass'])
32 s4 = scheduler.Dependent('downstream4', s3, ['b3', 'b4'])
33 s5 = scheduler.Dependent('downstream5', s4, ['b5'])
34 c['schedulers'] = [s1, s2, s3, s4, s5]
36 f_fastpass = factory.BuildFactory([s(dummy.Dummy, timeout=1)])
37 f_slowpass = factory.BuildFactory([s(dummy.Dummy, timeout=2)])
38 f_fastfail = factory.BuildFactory([s(dummy.FailingDummy, timeout=1)])
40 def builder(name, f):
41 d = {'name': name, 'slavename': 'bot1', 'builddir': name, 'factory': f}
42 return d
44 c['builders'] = [builder('slowpass', f_slowpass),
45 builder('fastfail', f_fastfail),
46 builder('fastpass', f_fastpass),
47 builder('b3', f_fastpass),
48 builder('b4', f_fastpass),
49 builder('b5', f_fastpass),
51 """
53 class Logger(base.StatusReceiverMultiService):
54 def __init__(self, master):
55 base.StatusReceiverMultiService.__init__(self)
56 self.builds = []
57 for bn in master.status.getBuilderNames():
58 master.status.getBuilder(bn).subscribe(self)
60 def buildStarted(self, builderName, build):
61 self.builds.append(builderName)
63 class Dependencies(RunMixin, unittest.TestCase):
64 def setUp(self):
65 RunMixin.setUp(self)
66 self.master.loadConfig(config_1)
67 self.master.startService()
68 d = self.connectSlave(["slowpass", "fastfail", "fastpass",
69 "b3", "b4", "b5"])
70 return d
72 def findScheduler(self, name):
73 for s in self.master.allSchedulers():
74 if s.name == name:
75 return s
76 raise KeyError("No Scheduler named '%s'" % name)
78 def testParse(self):
79 self.master.loadConfig(config_1)
80 # that's it, just make sure this config file is loaded successfully
82 def testRun_Fail(self):
83 # add an extra status target to make pay attention to which builds
84 # start and which don't.
85 self.logger = Logger(self.master)
87 # kick off upstream1, which has a failing Builder and thus will not
88 # trigger downstream3
89 s = self.findScheduler("upstream1")
90 # this is an internal function of the Scheduler class
91 s.fireTimer() # fires a build
92 # t=0: two builders start: 'slowpass' and 'fastfail'
93 # t=1: builder 'fastfail' finishes
94 # t=2: builder 'slowpass' finishes
95 d = defer.Deferred()
96 d.addCallback(self._testRun_Fail_1)
97 reactor.callLater(5, d.callback, None)
98 return d
100 def _testRun_Fail_1(self, res):
101 # 'slowpass' and 'fastfail' should have run one build each
102 b = self.status.getBuilder('slowpass').getLastFinishedBuild()
103 self.failUnless(b)
104 self.failUnlessEqual(b.getNumber(), 0)
105 b = self.status.getBuilder('fastfail').getLastFinishedBuild()
106 self.failUnless(b)
107 self.failUnlessEqual(b.getNumber(), 0)
109 # none of the other builders should have run
110 self.failIf(self.status.getBuilder('b3').getLastFinishedBuild())
111 self.failIf(self.status.getBuilder('b4').getLastFinishedBuild())
112 self.failIf(self.status.getBuilder('b5').getLastFinishedBuild())
114 # in fact, none of them should have even started
115 self.failUnlessEqual(len(self.logger.builds), 2)
116 self.failUnless("slowpass" in self.logger.builds)
117 self.failUnless("fastfail" in self.logger.builds)
118 self.failIf("b3" in self.logger.builds)
119 self.failIf("b4" in self.logger.builds)
120 self.failIf("b5" in self.logger.builds)
122 def testRun_Pass(self):
123 # kick off upstream3, which will fire downstream4 and then
124 # downstream5
125 s = self.findScheduler("upstream3")
126 # this is an internal function of the Scheduler class
127 s.fireTimer() # fires a build
128 # t=0: slowpass and fastpass start
129 # t=1: builder 'fastpass' finishes
130 # t=2: builder 'slowpass' finishes
131 # scheduler 'downstream4' fires
132 # builds b3 and b4 are started
133 # t=3: builds b3 and b4 finish
134 # scheduler 'downstream5' fires
135 # build b5 is started
136 # t=4: build b5 is finished
137 d = defer.Deferred()
138 d.addCallback(self._testRun_Pass_1)
139 reactor.callLater(5, d.callback, None)
140 return d
142 def _testRun_Pass_1(self, res):
143 # 'fastpass' and 'slowpass' should have run one build each
144 b = self.status.getBuilder('fastpass').getLastFinishedBuild()
145 self.failUnless(b)
146 self.failUnlessEqual(b.getNumber(), 0)
148 b = self.status.getBuilder('slowpass').getLastFinishedBuild()
149 self.failUnless(b)
150 self.failUnlessEqual(b.getNumber(), 0)
152 self.failIf(self.status.getBuilder('fastfail').getLastFinishedBuild())
154 b = self.status.getBuilder('b3').getLastFinishedBuild()
155 self.failUnless(b)
156 self.failUnlessEqual(b.getNumber(), 0)
158 b = self.status.getBuilder('b4').getLastFinishedBuild()
159 self.failUnless(b)
160 self.failUnlessEqual(b.getNumber(), 0)
162 b = self.status.getBuilder('b4').getLastFinishedBuild()
163 self.failUnless(b)
164 self.failUnlessEqual(b.getNumber(), 0)