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
11 from buildbot import scheduler
12 from buildbot.process import factory
13 from buildbot.steps import dummy
14 from buildbot.buildslave import BuildSlave
16 from buildbot.test.test_locks import LockStep
18 BuildmasterConfig = c = {}
19 c['slaves'] = [BuildSlave('bot1', 'sekrit'), BuildSlave('bot2', 'sekrit')]
23 # upstream1 (fastfail, slowpass)
24 # -> downstream2 (b3, b4)
25 # upstream3 (slowfail, slowpass)
26 # -> downstream4 (b3, b4)
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)])
41 d = {'name': name, 'slavename': 'bot1', 'builddir': name, 'factory': f}
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),
53 class Logger(base
.StatusReceiverMultiService
):
54 def __init__(self
, master
):
55 base
.StatusReceiverMultiService
.__init
__(self
)
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
):
66 self
.master
.loadConfig(config_1
)
67 self
.master
.startService()
68 d
= self
.connectSlave(["slowpass", "fastfail", "fastpass",
72 def findScheduler(self
, name
):
73 for s
in self
.master
.allSchedulers():
76 raise KeyError("No Scheduler named '%s'" % name
)
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
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
96 d
.addCallback(self
._testRun
_Fail
_1)
97 reactor
.callLater(5, d
.callback
, None)
100 def _testRun_Fail_1(self
, res
):
101 # 'slowpass' and 'fastfail' should have run one build each
102 b
= self
.status
.getBuilder('slowpass').getLastFinishedBuild()
104 self
.failUnlessEqual(b
.getNumber(), 0)
105 b
= self
.status
.getBuilder('fastfail').getLastFinishedBuild()
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
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
138 d
.addCallback(self
._testRun
_Pass
_1)
139 reactor
.callLater(5, d
.callback
, None)
142 def _testRun_Pass_1(self
, res
):
143 # 'fastpass' and 'slowpass' should have run one build each
144 b
= self
.status
.getBuilder('fastpass').getLastFinishedBuild()
146 self
.failUnlessEqual(b
.getNumber(), 0)
148 b
= self
.status
.getBuilder('slowpass').getLastFinishedBuild()
150 self
.failUnlessEqual(b
.getNumber(), 0)
152 self
.failIf(self
.status
.getBuilder('fastfail').getLastFinishedBuild())
154 b
= self
.status
.getBuilder('b3').getLastFinishedBuild()
156 self
.failUnlessEqual(b
.getNumber(), 0)
158 b
= self
.status
.getBuilder('b4').getLastFinishedBuild()
160 self
.failUnlessEqual(b
.getNumber(), 0)
162 b
= self
.status
.getBuilder('b4').getLastFinishedBuild()
164 self
.failUnlessEqual(b
.getNumber(), 0)