Пример #1
0
 def test_canBeMergedWith_where_sourcestamp_do_not_both_have_changes(self):
     c1 = mock.Mock()
     c1.codebase = 'cb'
     ss1 = sourcestamp.SourceStamp(branch='dev', revision='xyz',
             project='p', repository='r', codebase='cb', changes=[c1])
     ss2 = sourcestamp.SourceStamp(branch='dev', revision='xyz',
             project='p', repository='r', codebase='cb', changes=[])
     self.assertFalse(ss1.canBeMergedWith(ss2))
Пример #2
0
 def test_canBeMergedWith_where_sourcestamp_have_different_codebases(self):
     ss1 = sourcestamp.SourceStamp(branch='dev',
                                   revision='xyz',
                                   project='p',
                                   repository='r',
                                   codebase='cbA',
                                   changes=[])
     ss2 = sourcestamp.SourceStamp(branch='dev',
                                   revision='xyz',
                                   project='p',
                                   repository='r',
                                   codebase='cbB',
                                   changes=[])
     self.assertFalse(ss1.canBeMergedWith(ss2))
Пример #3
0
    def testSuccess(self):
        S = buildset.BuildSet
        a,b = FakeBuilder(), FakeBuilder()
        # this time, both builds succeed

        source = sourcestamp.SourceStamp()
        s = S(["a","b"], source, "forced build")
        s.start([a,b])

        st = s.status
        self.failUnlessEqual(st.getSourceStamp(), source)
        self.failUnlessEqual(st.getReason(), "forced build")
        self.failUnlessEqual(st.getBuilderNames(), ["a","b"])
        self.failIf(st.isFinished())

        builderstatus_a = builder.BuilderStatus("a")
        bsa = builder.BuildStatus(builderstatus_a, 1)
        bsa.setResults(builder.SUCCESS)
        a.requests[0].finished(bsa)

        builderstatus_b = builder.BuilderStatus("b")
        bsb = builder.BuildStatus(builderstatus_b, 1)
        bsb.setResults(builder.SUCCESS)
        b.requests[0].finished(bsb)

        self.failUnless(st.isFinished())
        self.failUnlessEqual(st.getResults(), builder.SUCCESS)
 def test_getAbsoluteSourceStamp_from_relative(self):
     ss = sourcestamp.SourceStamp(branch='dev', revision=None,
             project='p', repository='r')
     abs_ss = ss.getAbsoluteSourceStamp('abcdef')
     self.assertEqual(abs_ss.branch, 'dev')
     self.assertEqual(abs_ss.revision, 'abcdef')
     self.assertEqual(abs_ss.project, 'p')
     self.assertEqual(abs_ss.repository, 'r')
Пример #5
0
 def test_canBeMergedWith_with_self_patched_sourcestamps(self):
     ss = sourcestamp.SourceStamp(branch='dev',
                                  revision='xyz',
                                  project='p',
                                  repository='r',
                                  codebase='cbA',
                                  changes=[],
                                  patch=(1, ''))
     self.assertTrue(ss.canBeMergedWith(ss))
 def test_getAbsoluteSourceStamp_from_absolute(self):
     ss = sourcestamp.SourceStamp(branch='dev', revision='xyz',
             project='p', repository='r')
     abs_ss = ss.getAbsoluteSourceStamp('abcdef')
     self.assertEqual(abs_ss.branch, 'dev')
     # revision gets overridden
     self.assertEqual(abs_ss.revision, 'abcdef')
     self.assertEqual(abs_ss.project, 'p')
     self.assertEqual(abs_ss.repository, 'r')
Пример #7
0
    def setUp(self):
        config = """
from buildbot.status import html
from buildbot.process.factory import BasicBuildFactory
from buildbot.buildslave import BuildSlave
f1 = BasicBuildFactory('cvsroot', 'cvsmodule')
BuildmasterConfig = {
    'slaves': [BuildSlave('bot1', 'passwd1')],
    'schedulers': [],
    'builders': [{'name': 'builder1', 'slavename': 'bot1',
                  'builddir':'workdir', 'factory':f1}],
    'slavePortnum': 0,
    'status': [html.WebStatus(http_port=0)],
    }
"""
        if os.path.exists("test_logfile"):
            shutil.rmtree("test_logfile")
        os.mkdir("test_logfile")
        self.master = m = ConfiguredMaster("test_logfile", config)
        m.startService()
        # hack to find out what randomly-assigned port it is listening on
        port = self.find_webstatus(m).getPortnum()
        self.port = port
        # insert an event

        req = base.BuildRequest("reason", sourcestamp.SourceStamp())
        build1 = base.Build([req])
        bs = m.status.getBuilder("builder1").newBuild()
        bs.setReason("reason")
        bs.buildStarted(build1)

        step1 = BuildStep(name="setup")
        step1.setBuild(build1)
        bss = bs.addStepWithName("setup")
        step1.setStepStatus(bss)
        bss.stepStarted()

        log1 = step1.addLog("output")
        log1.addStdout("some stdout\n")
        log1.finish()

        log2 = step1.addHTMLLog("error", "<html>ouch</html>")

        log3 = step1.addLog("big")
        log3.addStdout("big log\n")
        for i in range(1000):
            log3.addStdout("a" * 500)
            log3.addStderr("b" * 500)
        log3.finish()

        log4 = step1.addCompleteLog("bigcomplete",
                                    "big2 log\n" + "a" * 1 * 1000 * 1000)

        step1.step_status.stepFinished(builder.SUCCESS)
        bs.buildFinished()
Пример #8
0
 def testGetBuildSets(self):
     # validate IStatus.getBuildSets
     s = status.builder.Status(None, ".")
     bs1 = buildset.BuildSet(["a", "b"],
                             sourcestamp.SourceStamp(),
                             reason="one",
                             bsid="1")
     s.buildsetSubmitted(bs1.status)
     self.failUnlessEqual(s.getBuildSets(), [bs1.status])
     bs1.status.notifyFinishedWatchers()
     self.failUnlessEqual(s.getBuildSets(), [])
Пример #9
0
 def test_constructor_most_recent_change(self):
     chgs = [
         changes.Change('author', [], 'comments', branch='branch',
                        revision='2'),
         changes.Change('author', [], 'comments', branch='branch',
                        revision='3'),
         changes.Change('author', [], 'comments', branch='branch',
                        revision='1'),
         ]
     for ch in chgs:  # mock the DB changeid (aka build number) to match rev
         ch.number = int(ch.revision)
     ss = sourcestamp.SourceStamp(changes=chgs)
     self.assertEquals(ss.revision, '3')
Пример #10
0
 def _then(ign):
     port = s.getPort()
     config = {
         'connect': 'pb',
         'username': '******',
         'passwd': 'pw1',
         'master': "localhost:%d" % port,
         'builders': ["a", "b"],
     }
     self.tryclient = t = tryclient.Try(config)
     ss = sourcestamp.SourceStamp("branch1", "123", (1, "diff"))
     t.sourcestamp = ss
     return t.deliverJob()
Пример #11
0
 def upgradeToVersion1(self):
     if hasattr(self, "sourceStamp"):
         # the old .sourceStamp attribute wasn't actually very useful
         maxChangeNumber, patch = self.sourceStamp
         changes = getattr(self, 'changes', [])
         source = sourcestamp.SourceStamp(branch=None,
                                          revision=None,
                                          patch=patch,
                                          changes=changes)
         self.source = source
         self.changes = source.changes
         del self.sourceStamp
     self.wasUpgraded = True
 def test_getAbsoluteSourceStamp_from_absolute_with_changes(self):
     c1 = mock.Mock()
     c1.branch = 'dev'
     c1.revision = 'xyz'
     c1.project = 'p'
     c1.repository = 'r'
     ss = sourcestamp.SourceStamp(branch='dev', revision='xyz',
             project='p', repository='r', changes=[c1])
     abs_ss = ss.getAbsoluteSourceStamp('abcdef')
     self.assertEqual(abs_ss.branch, 'dev')
     # revision changes, even though changes say different - this is
     # useful for CVS, for example
     self.assertEqual(abs_ss.revision, 'abcdef')
     self.assertEqual(abs_ss.project, 'p')
     self.assertEqual(abs_ss.repository, 'r')
Пример #13
0
        def _started(ign):
            # hack to find out what randomly-assigned port it is listening on
            port = self.find_webstatus(m).getPortnum()
            self.port = port
            # insert an event

            req = BuildRequest("reason", sourcestamp.SourceStamp(), 'test_builder')
            build1 = base.Build([req])
            bs = m.status.getBuilder("builder1").newBuild()
            bs.setReason("reason")
            bs.buildStarted(build1)

            step1 = BuildStep(name="setup")
            step1.setBuild(build1)
            bss = bs.addStepWithName("setup")
            step1.setStepStatus(bss)
            bss.stepStarted()

            log1 = step1.addLog("output")
            log1.addStdout(u"s\N{LATIN CAPITAL LETTER O WITH GRAVE}me stdout\n".encode("utf-8"))
            log1.finish()

            log2 = step1.addHTMLLog("error", "<html>ouch</html>")
            del log2

            log3 = step1.addLog("big")
            log3.addStdout("big log\n")
            for i in range(1000):
                log3.addStdout("a" * 500)
                log3.addStderr("b" * 500)
            log3.finish()

            log4 = step1.addCompleteLog("bigcomplete",
                                        "big2 log\n" + "a" * 1*1000*1000)
            del log4

            log5 = step1.addLog("mixed")
            log5.addHeader("header content")
            log5.addStdout("this is stdout content")
            log5.addStderr("errors go here")
            log5.addEntry(5, "non-standard content on channel 5")
            log5.addStderr(" and some trailing stderr")

            d1 = defer.maybeDeferred(step1.step_status.stepFinished,
                                     builder.SUCCESS)
            bs.buildFinished()
            return d1
Пример #14
0
    def test_subscribe(self):
        self.basedir = "buildset/BuildSet/subscribe"
        self.create_master()
        db = self.master.db
        run = db.runInteractionNow

        ss = sourcestamp.SourceStamp(branch="branchy")
        ssid = run(lambda t: db.get_sourcestampid(ss, t))

        d = defer.succeed(None)
        d.addCallback(self._setup_subscribe, ssid)
        d.addCallback(self._subscribe_test1)
        d.addCallback(self._setup_subscribe, ssid)
        d.addCallback(self._subscribe_test2)
        d.addCallback(self._setup_subscribe, ssid)
        d.addCallback(self._subscribe_test3)
        return d
Пример #15
0
 def testTryUserpass(self):
     up = [("alice", "pw1"), ("bob", "pw2")]
     s = scheduler.Try_Userpass("try2", ["a", "b"], 0, userpass=up)
     self.addScheduler(s)
     port = s.getPort()
     config = {
         'connect': 'pb',
         'username': '******',
         'passwd': 'pw1',
         'master': "localhost:%d" % port,
         'builders': ["a", "b"],
     }
     t = tryclient.Try(config)
     ss = sourcestamp.SourceStamp("branch1", "123", (1, "diff"))
     t.sourcestamp = ss
     d2 = self.master.d = defer.Deferred()
     d = t.deliverJob()
     d.addCallback(self._testTryUserpass_1, t, d2)
     return d
Пример #16
0
    def testBuildSet(self):
        S = buildset.BuildSet
        a,b = FakeBuilder(), FakeBuilder()

        # two builds, the first one fails, the second one succeeds. The
        # waitUntilSuccess watcher fires as soon as the first one fails,
        # while the waitUntilFinished watcher doesn't fire until all builds
        # are complete.

        source = sourcestamp.SourceStamp()
        s = S(["a","b"], source, "forced build")
        s.start([a,b])
        self.failUnlessEqual(len(a.requests), 1)
        self.failUnlessEqual(len(b.requests), 1)
        r1 = a.requests[0]
        self.failUnlessEqual(r1.reason, s.reason)
        self.failUnlessEqual(r1.source, s.source)

        st = s.status
        self.failUnlessEqual(st.getSourceStamp(), source)
        self.failUnlessEqual(st.getReason(), "forced build")
        self.failUnlessEqual(st.getBuilderNames(), ["a","b"])
        self.failIf(st.isFinished())
        brs = st.getBuildRequests()
        self.failUnlessEqual(len(brs), 2)

        res = []
        d1 = s.waitUntilSuccess()
        d1.addCallback(lambda r: res.append(("success", r)))
        d2 = s.waitUntilFinished()
        d2.addCallback(lambda r: res.append(("finished", r)))

        self.failUnlessEqual(res, [])

        # the first build finishes here, with FAILURE
        builderstatus_a = builder.BuilderStatus("a")
        bsa = builder.BuildStatus(builderstatus_a, 1)
        bsa.setResults(builder.FAILURE)
        a.requests[0].finished(bsa)

        # any FAILURE flunks the BuildSet immediately, so the
        # waitUntilSuccess deferred fires right away. However, the
        # waitUntilFinished deferred must wait until all builds have
        # completed.
        self.failUnlessEqual(len(res), 1)
        self.failUnlessEqual(res[0][0], "success")
        bss = res[0][1]
        self.failUnless(interfaces.IBuildSetStatus(bss, None))
        self.failUnlessEqual(bss.getResults(), builder.FAILURE)

        # here we finish the second build
        builderstatus_b = builder.BuilderStatus("b")
        bsb = builder.BuildStatus(builderstatus_b, 1)
        bsb.setResults(builder.SUCCESS)
        b.requests[0].finished(bsb)

        # .. which ought to fire the waitUntilFinished deferred
        self.failUnlessEqual(len(res), 2)
        self.failUnlessEqual(res[1][0], "finished")
        self.failUnlessEqual(res[1][1], bss)

        # and finish the BuildSet overall
        self.failUnless(st.isFinished())
        self.failUnlessEqual(st.getResults(), builder.FAILURE)
Пример #17
0
 def doBuild(self, buildername):
     brs = self.control.submitBuildSet([buildername],
                                       sourcestamp.SourceStamp(), "forced")
     return brs.waitUntilFinished()
Пример #18
0
    def test_basic(self):
        self.basedir = "buildset/BuildSet/basic"
        self.create_master()
        db = self.master.db
        run = db.runInteractionNow

        # we must create all the things that go into a buildset
        #c1 = Change(who="brian", files=["foo.c", "subdir/bar.c"],
        #            comments="first change",
        #            revision="1234")
        #db.addChangeToDatabase(c1)
        ss = sourcestamp.SourceStamp(branch="branchy")
        ssid = run(lambda t: db.get_sourcestampid(ss, t))
        props = Properties()
        props.setProperty("pname", "pvalue", "psource")

        bsid = run(lambda t: db.create_buildset(ssid, "reason", props,
                                                ["bn1", "bn2"], t))
        mn, mi = "mastername", "incarnation"
        reqs = run(
            lambda t: db.get_unclaimed_buildrequests("bn1", 1, mn, mi, t))
        self.failUnlessEqual(len(reqs), 1)
        self.failUnlessEqual(reqs[0].reason, "reason")
        self.failUnlessEqual(reqs[0].builderName, "bn1")
        #print reqs[0].properties
        #self.failUnlessEqual(reqs[0].properties["pname"], "pvalue") #BROKEN
        brids = db.get_buildrequestids_for_buildset(bsid)
        bn1_brid = brids["bn1"]
        bn2_brid = brids["bn2"]
        self.failUnlessEqual(bn1_brid, reqs[0].id)
        reqs2 = run(
            lambda t: db.get_unclaimed_buildrequests("bn2", 1, mn, mi, t))
        self.failUnlessEqual(bn2_brid, reqs2[0].id)

        (successful, finished) = db.examine_buildset(bsid)
        self.failUnlessEqual(successful, None)
        self.failUnlessEqual(finished, False)

        bs = self.master.status.getBuildSets()
        self.failUnlessEqual(len(bs), 1)
        brs = bs[0].getBuilderNamesAndBuildRequests()
        self.failUnlessEqual(sorted(brs.keys()), ["bn1", "bn2"])
        self.failUnlessEqual(sorted(bs[0].getBuilderNames()), ["bn1", "bn2"])
        self.failUnlessEqual(len(bs[0].getBuildRequests()), 2)
        ss2 = bs[0].getSourceStamp()
        self.failUnlessEqual(ss2.branch, "branchy")
        self.failUnlessEqual(bs[0].getReason(), "reason")
        self.failUnlessEqual(bs[0].isFinished(), False)
        self.failUnlessEqual(bs[0].getResults(), None)

        db.retire_buildrequests([bn1_brid], SUCCESS)
        self.failUnlessEqual(db.examine_buildset(bsid), (None, False))
        db.retire_buildrequests([bn2_brid], SUCCESS)
        self.failUnlessEqual(db.examine_buildset(bsid), (True, True))

        bsid2 = run(lambda t: db.create_buildset(ssid, "reason", props,
                                                 ["bn1", "bn2"], t))
        brids2 = db.get_buildrequestids_for_buildset(bsid2)
        self.failUnlessEqual(db.examine_buildset(bsid2), (None, False))
        db.retire_buildrequests([brids2["bn1"]], SUCCESS)
        self.failUnlessEqual(db.examine_buildset(bsid2), (None, False))
        db.retire_buildrequests([brids2["bn2"]], FAILURE)
        self.failUnlessEqual(db.examine_buildset(bsid2), (False, True))

        bsid3 = run(lambda t: db.create_buildset(ssid, "reason", props,
                                                 ["bn1", "bn2"], t))
        brids3 = db.get_buildrequestids_for_buildset(bsid3)
        self.failUnlessEqual(db.examine_buildset(bsid3), (None, False))
        db.retire_buildrequests([brids3["bn1"]], FAILURE)
        self.failUnlessEqual(db.examine_buildset(bsid3), (False, False))
        db.retire_buildrequests([brids3["bn2"]], SUCCESS)
        self.failUnlessEqual(db.examine_buildset(bsid3), (False, True))
Пример #19
0
    def force(self, req):
        """ Overriden method from builders.StatusResourceBuilder. The only
    change to original behavior is that it sets 'clobber' value on the
    BuildRequest.properties."""

        name = req.args.get("username", ["<unknown>"])[0]
        reason = req.args.get("comments", ["<no reason specified>"])[0]
        branch = req.args.get("branch", [""])[0]
        revision = req.args.get("revision", [""])[0]
        clobber = req.args.get("clobber", [False])[0]
        slavename = req.args.get("slavename", [False])[0]

        if clobber:
            clobber_str = ' (clobbered)'
        else:
            clobber_str = ''
        r = ("The web-page 'force build' button%s was pressed by %s: %s" %
             (clobber_str, name, reason))

        message = ("web forcebuild of builder '%s', branch='%s', revision='%s'"
                   ", clobber='%s'")
        log.msg(
            message %
            (self.builder_status.getName(), branch, revision, str(clobber)))

        if not self.builder_control:
            # TODO: tell the web user that their request was denied
            log.msg("but builder control is disabled")
            return Redirect("..")

        # keep weird stuff out of the branch and revision strings. TODO:
        # centralize this somewhere.
        if not re.match(r'^[\w\.\-\/]*$', branch):
            log.msg("bad branch '%s'" % branch)
            return Redirect("..")
        if not re.match(r'^[\w\.\-\/]*$', revision):
            log.msg("bad revision '%s'" % revision)
            return Redirect("..")
        if branch == "":
            branch = None
        if revision == "":
            revision = None

        # TODO: if we can authenticate that a particular User pushed the
        # button, use their name instead of None, so they'll be informed of
        # the results.
        s = sourcestamp.SourceStamp(branch=branch, revision=revision)
        props = process.properties.Properties()
        if clobber:
            props.setProperty("clobber", True, "Scheduler")
        if slavename:
            props.setProperty("slavename", slavename, "Scheduler")
        req = process.base.BuildRequest(
            r, s, builderName=self.builder_status.getName(), properties=props)
        try:
            self.builder_control.requestBuildSoon(req)
        except interfaces.NoSlaveError:
            # TODO: tell the web user that their request could not be
            # honored
            pass
        # Sends the user back to the waterfall page.
        return Redirect("../..")
Пример #20
0
 def doBuild(self, buildername):
     br = base.BuildRequest("forced", sourcestamp.SourceStamp(),
                            'test_builder')
     d = br.waitUntilFinished()
     self.control.getBuilder(buildername).requestBuild(br)
     return d
Пример #21
0
    def setUp(self):
        config = """
from buildbot.status import html
from buildbot.process.factory import BasicBuildFactory
from buildbot.buildslave import BuildSlave
from buildbot.config import BuilderConfig

f1 = BasicBuildFactory('cvsroot', 'cvsmodule')
BuildmasterConfig = c = {
    'slaves': [BuildSlave('bot1', 'passwd1')],
    'schedulers': [],
    'slavePortnum': 0,
    'status': [html.WebStatus(http_port=0)],
    }
c['builders'] = [
    BuilderConfig(name='builder1', slavename='bot1', factory=f1),
]
"""
        if os.path.exists("test_logfile"):
            shutil.rmtree("test_logfile")
        os.mkdir("test_logfile")
        self.master = m = ConfiguredMaster("test_logfile", config)
        m.startService()
        # hack to find out what randomly-assigned port it is listening on
        port = self.find_webstatus(m).getPortnum()
        self.port = port
        # insert an event

        req = base.BuildRequest("reason", sourcestamp.SourceStamp(),
                                'test_builder')
        build1 = base.Build([req])
        bs = m.status.getBuilder("builder1").newBuild()
        bs.setReason("reason")
        bs.buildStarted(build1)

        step1 = BuildStep(name="setup")
        step1.setBuild(build1)
        bss = bs.addStepWithName("setup")
        step1.setStepStatus(bss)
        bss.stepStarted()

        log1 = step1.addLog("output")
        log1.addStdout(u"sÒme stdout\n")
        log1.finish()

        log2 = step1.addHTMLLog("error", "<html>ouch</html>")

        log3 = step1.addLog("big")
        log3.addStdout("big log\n")
        for i in range(1000):
            log3.addStdout("a" * 500)
            log3.addStderr("b" * 500)
        log3.finish()

        log4 = step1.addCompleteLog("bigcomplete",
                                    "big2 log\n" + "a" * 1 * 1000 * 1000)

        log5 = step1.addLog("mixed")
        log5.addHeader("header content")
        log5.addStdout("this is stdout content")
        log5.addStderr("errors go here")
        log5.addEntry(5, "non-standard content on channel 5")
        log5.addStderr(" and some trailing stderr")

        d = defer.maybeDeferred(step1.step_status.stepFinished,
                                builder.SUCCESS)
        bs.buildFinished()
        return d
Пример #22
0
    def create_status(self):
        for i in range(5):
            if i % 2 == 0:
                branch = "release"
            else:
                branch = None
            c = Change("user", ["foo.c"] * i,
                       "see ticket #%i" % i,
                       revision=str(42 + i),
                       when=0.1 * i,
                       branch=branch)
            self.master.change_svc.addChange(c)

        ss = sourcestamp.SourceStamp(revision=42)
        req = BuildRequest("reason", ss, 'test_builder')
        build1 = base.Build([req])
        bs = self.master.status.getBuilder("builder1").newBuild()
        bs.setReason("reason")
        bs.buildStarted(build1)

        bs.setSourceStamp(ss)

        bs.setProperty("revision", "42", "testcase")
        bs.setProperty("got_revision", "47", "testcase")
        bs.setProperty("branch", "release", "testcase")

        step1 = BuildStep(name="setup")
        step1.setBuild(build1)
        bss = bs.addStepWithName("setup")
        step1.setStepStatus(bss)
        bss.stepStarted()

        step2 = BuildStep(name="build")
        step2.setBuild(build1)
        bss = bs.addStepWithName("build")
        step2.setStepStatus(bss)
        bss.stepStarted()

        step1.addURL("url1", "http://logurl.net/1")
        step1.addURL("url2", "http://logurl.net/2")
        step1.addURL("url3", "http://logurl.net/3")

        log1 = step1.addLog("output")
        log1.addStdout(
            u"some stdout\n")  # FIXME: Unicode here fails validation
        log1.finish()

        # this has to validate too for the test to pass
        log2 = step1.addHTMLLog(
            "error", '''
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
              "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html>
                <head><title>Teh Log</title></head>
                <body>Aaaiight</body>
            </html>''')
        del log2

        log3 = step1.addLog("big")
        log3.addStdout("somewhat big log\n")
        for i in range(50):
            log3.addStdout("a" * 50 + "\n")
            log3.addStderr("b" * 50 + "\n")
        log3.finish()

        log5 = step1.addLog("mixed")
        log5.addHeader("header content")
        log5.addStdout("this is stdout content")
        log5.addStderr("errors go here")
        log5.addEntry(5, "non-standard content on channel 5")
        log5.addStderr(" and some trailing stderr")

        d = defer.succeed(None)

        for i in range(1, 3):
            ss = sourcestamp.SourceStamp(revision=42 + i, branch='release')
            req = BuildRequest("reason", ss, 'test_builder')
            build = base.Build([req] * i)
            bs = self.master.status.getBuilder("builder%i" % i).newBuild()
            bs.setReason("reason")
            bs.buildStarted(build)
            bs.setSourceStamp(ss)

            s = BuildStep(name="setup")
            s.setBuild(build1)
            bss = bs.addStepWithName("setup")
            s.setStepStatus(bss)
            bss.stepStarted()
            log = s.addLog("stdio")
            log.finish()

        d.chainDeferred(
            defer.maybeDeferred(step1.step_status.stepFinished,
                                builder.SUCCESS))
        bs.buildFinished()
        return d