"Fossies" - the Fresh Open Source Software Archive

Member "buildbot-2.5.1/buildbot/test/unit/test_process_builder.py" (24 Nov 2019, 21672 Bytes) of package /linux/misc/buildbot-2.5.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "test_process_builder.py": 2.4.0_vs_2.4.1.

    1 # This file is part of Buildbot.  Buildbot is free software: you can
    2 # redistribute it and/or modify it under the terms of the GNU General Public
    3 # License as published by the Free Software Foundation, version 2.
    4 #
    5 # This program is distributed in the hope that it will be useful, but WITHOUT
    6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    7 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    8 # details.
    9 #
   10 # You should have received a copy of the GNU General Public License along with
   11 # this program; if not, write to the Free Software Foundation, Inc., 51
   12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   13 #
   14 # Copyright Buildbot Team Members
   15 
   16 import random
   17 
   18 import mock
   19 
   20 from twisted.internet import defer
   21 from twisted.trial import unittest
   22 
   23 from buildbot import config
   24 from buildbot.process import builder
   25 from buildbot.process import factory
   26 from buildbot.process.properties import Properties
   27 from buildbot.process.properties import renderer
   28 from buildbot.test.fake import fakedb
   29 from buildbot.test.fake import fakemaster
   30 from buildbot.test.util.misc import TestReactorMixin
   31 from buildbot.test.util.warnings import assertProducesWarning
   32 from buildbot.util import epoch2datetime
   33 from buildbot.worker import AbstractLatentWorker
   34 
   35 
   36 class BuilderMixin:
   37 
   38     def setUpBuilderMixin(self):
   39         self.factory = factory.BuildFactory()
   40         self.master = fakemaster.make_master(self, wantData=True)
   41         self.mq = self.master.mq
   42         self.db = self.master.db
   43 
   44     # returns a Deferred that returns None
   45     def makeBuilder(self, name="bldr", patch_random=False, noReconfig=False,
   46                     **config_kwargs):
   47         """Set up C{self.bldr}"""
   48         # only include the necessary required config, plus user-requested
   49         config_args = dict(name=name, workername="wrk", builddir="bdir",
   50                            workerbuilddir="wbdir", factory=self.factory)
   51         config_args.update(config_kwargs)
   52         self.builder_config = config.BuilderConfig(**config_args)
   53         self.bldr = builder.Builder(
   54             self.builder_config.name)
   55         self.bldr.master = self.master
   56         self.bldr.botmaster = self.master.botmaster
   57 
   58         # patch into the _startBuildsFor method
   59         self.builds_started = []
   60 
   61         def _startBuildFor(workerforbuilder, buildrequests):
   62             self.builds_started.append((workerforbuilder, buildrequests))
   63             return defer.succeed(True)
   64         self.bldr._startBuildFor = _startBuildFor
   65 
   66         if patch_random:
   67             # patch 'random.choice' to always take the worker that sorts
   68             # last, based on its name
   69             self.patch(random, "choice",
   70                        lambda lst: sorted(lst, key=lambda m: m.name)[-1])
   71 
   72         self.bldr.startService()
   73 
   74         mastercfg = config.MasterConfig()
   75         mastercfg.builders = [self.builder_config]
   76         if not noReconfig:
   77             return self.bldr.reconfigServiceWithBuildbotConfig(mastercfg)
   78 
   79 
   80 class FakeWorker:
   81     builds_may_be_incompatible = False
   82 
   83     def __init__(self, workername):
   84         self.workername = workername
   85 
   86 
   87 class TestBuilder(TestReactorMixin, BuilderMixin, unittest.TestCase):
   88 
   89     def setUp(self):
   90         self.setUpTestReactor()
   91         # a collection of rows that would otherwise clutter up every test
   92         self.setUpBuilderMixin()
   93         self.base_rows = [
   94             fakedb.SourceStamp(id=21),
   95             fakedb.Buildset(id=11, reason='because'),
   96             fakedb.BuildsetSourceStamp(buildsetid=11, sourcestampid=21),
   97         ]
   98 
   99     @defer.inlineCallbacks
  100     def makeBuilder(self, patch_random=False, startBuildsForSucceeds=True, **config_kwargs):
  101         yield super().makeBuilder(patch_random=patch_random, **config_kwargs)
  102 
  103         # patch into the _startBuildsFor method
  104         self.builds_started = []
  105 
  106         def _startBuildFor(workerforbuilder, buildrequests):
  107             self.builds_started.append((workerforbuilder, buildrequests))
  108             return defer.succeed(startBuildsForSucceeds)
  109         self.bldr._startBuildFor = _startBuildFor
  110 
  111     def assertBuildsStarted(self, exp):
  112         # munge builds_started into a list of (worker, [brids])
  113         builds_started = [
  114             (wrk.name, [br.id for br in buildreqs])
  115             for (wrk, buildreqs) in self.builds_started]
  116         self.assertEqual(sorted(builds_started), sorted(exp))
  117 
  118     def setWorkerForBuilders(self, workerforbuilders):
  119         """C{workerforbuilders} maps name : available"""
  120         self.bldr.workers = []
  121         for name, avail in workerforbuilders.items():
  122             wfb = mock.Mock(spec=['isAvailable'], name=name)
  123             wfb.name = name
  124             wfb.isAvailable.return_value = avail
  125             self.bldr.workers.append(wfb)
  126 
  127     # services
  128 
  129     @defer.inlineCallbacks
  130     def test_maybeStartBuild_builder_stopped(self):
  131         yield self.makeBuilder()
  132 
  133         # this will cause an exception if maybeStartBuild tries to start
  134         self.bldr.workers = None
  135 
  136         # so we just hope this does not fail
  137         yield self.bldr.stopService()
  138         started = yield self.bldr.maybeStartBuild(None, [])
  139         self.assertEqual(started, False)
  140 
  141     # maybeStartBuild
  142     def _makeMocks(self):
  143         worker = mock.Mock()
  144         worker.name = 'worker'
  145         buildrequest = mock.Mock()
  146         buildrequest.id = 10
  147         buildrequests = [buildrequest]
  148         return worker, buildrequests
  149 
  150     @defer.inlineCallbacks
  151     def test_maybeStartBuild(self):
  152         yield self.makeBuilder()
  153 
  154         worker, buildrequests = self._makeMocks()
  155 
  156         started = yield self.bldr.maybeStartBuild(worker, buildrequests)
  157         self.assertEqual(started, True)
  158         self.assertBuildsStarted([('worker', [10])])
  159 
  160     @defer.inlineCallbacks
  161     def test_maybeStartBuild_failsToStart(self):
  162         yield self.makeBuilder(startBuildsForSucceeds=False)
  163 
  164         worker, buildrequests = self._makeMocks()
  165 
  166         started = yield self.bldr.maybeStartBuild(worker, buildrequests)
  167         self.assertEqual(started, False)
  168         self.assertBuildsStarted([('worker', [10])])
  169 
  170     @defer.inlineCallbacks
  171     def do_test_getCollapseRequestsFn(self, builder_param=None,
  172                                       global_param=None, expected=0):
  173         def cble():
  174             pass
  175 
  176         builder_param = cble if builder_param == 'callable' else builder_param
  177         global_param = cble if global_param == 'callable' else global_param
  178 
  179         # omit the constructor parameter if None was given
  180         if builder_param is None:
  181             yield self.makeBuilder()
  182         else:
  183             yield self.makeBuilder(collapseRequests=builder_param)
  184 
  185         self.master.config.collapseRequests = global_param
  186 
  187         fn = self.bldr.getCollapseRequestsFn()
  188 
  189         if fn == builder.Builder._defaultCollapseRequestFn:
  190             fn = "default"
  191         elif fn is cble:
  192             fn = 'callable'
  193         self.assertEqual(fn, expected)
  194 
  195     def test_getCollapseRequestsFn_defaults(self):
  196         self.do_test_getCollapseRequestsFn(None, None, "default")
  197 
  198     def test_getCollapseRequestsFn_global_True(self):
  199         self.do_test_getCollapseRequestsFn(None, True, "default")
  200 
  201     def test_getCollapseRequestsFn_global_False(self):
  202         self.do_test_getCollapseRequestsFn(None, False, None)
  203 
  204     def test_getCollapseRequestsFn_global_function(self):
  205         self.do_test_getCollapseRequestsFn(None, 'callable', 'callable')
  206 
  207     def test_getCollapseRequestsFn_builder_True(self):
  208         self.do_test_getCollapseRequestsFn(True, False, "default")
  209 
  210     def test_getCollapseRequestsFn_builder_False(self):
  211         self.do_test_getCollapseRequestsFn(False, True, None)
  212 
  213     def test_getCollapseRequestsFn_builder_function(self):
  214         self.do_test_getCollapseRequestsFn('callable', None, 'callable')
  215 
  216     # canStartBuild
  217 
  218     @defer.inlineCallbacks
  219     def test_canStartBuild_no_constraints(self):
  220         yield self.makeBuilder()
  221 
  222         wfb = mock.Mock()
  223         wfb.worker = FakeWorker('worker')
  224 
  225         startable = yield self.bldr.canStartBuild(wfb, 100)
  226         self.assertEqual(startable, True)
  227 
  228         startable = yield self.bldr.canStartBuild(wfb, 101)
  229         self.assertEqual(startable, True)
  230 
  231     @defer.inlineCallbacks
  232     def test_canStartBuild_config_canStartBuild_returns_value(self):
  233         yield self.makeBuilder()
  234 
  235         def canStartBuild(bldr, worker, breq):
  236             return breq == 100
  237         canStartBuild = mock.Mock(side_effect=canStartBuild)
  238 
  239         self.bldr.config.canStartBuild = canStartBuild
  240 
  241         wfb = mock.Mock()
  242         wfb.worker = FakeWorker('worker')
  243 
  244         startable = yield self.bldr.canStartBuild(wfb, 100)
  245         self.assertEqual(startable, True)
  246         canStartBuild.assert_called_with(self.bldr, wfb, 100)
  247         canStartBuild.reset_mock()
  248 
  249         startable = yield self.bldr.canStartBuild(wfb, 101)
  250         self.assertEqual(startable, False)
  251         canStartBuild.assert_called_with(self.bldr, wfb, 101)
  252         canStartBuild.reset_mock()
  253 
  254     @defer.inlineCallbacks
  255     def test_canStartBuild_config_canStartBuild_returns_deferred(self):
  256         yield self.makeBuilder()
  257 
  258         wfb = mock.Mock()
  259         wfb.worker = FakeWorker('worker')
  260 
  261         def canStartBuild(bldr, wfb, breq):
  262             return defer.succeed(breq == 100)
  263         canStartBuild = mock.Mock(side_effect=canStartBuild)
  264 
  265         self.bldr.config.canStartBuild = canStartBuild
  266 
  267         startable = yield self.bldr.canStartBuild(wfb, 100)
  268         self.assertEqual(startable, True)
  269         canStartBuild.assert_called_with(self.bldr, wfb, 100)
  270         canStartBuild.reset_mock()
  271 
  272         startable = yield self.bldr.canStartBuild(wfb, 101)
  273         self.assertEqual(startable, False)
  274         canStartBuild.assert_called_with(self.bldr, wfb, 101)
  275         canStartBuild.reset_mock()
  276 
  277     @defer.inlineCallbacks
  278     def test_canStartBuild_cant_acquire_locks_but_no_locks(self):
  279         yield self.makeBuilder()
  280 
  281         self.bldr.botmaster.getLockFromLockAccesses = mock.Mock(return_value=[])
  282 
  283         wfb = mock.Mock()
  284         wfb.worker = FakeWorker('worker')
  285 
  286         with mock.patch(
  287                 'buildbot.process.build.Build._canAcquireLocks',
  288                 mock.Mock(return_value=False)):
  289             startable = yield self.bldr.canStartBuild(wfb, 100)
  290             self.assertEqual(startable, True)
  291 
  292     @defer.inlineCallbacks
  293     def test_canStartBuild_with_locks(self):
  294         yield self.makeBuilder()
  295 
  296         self.bldr.botmaster.getLockFromLockAccesses = mock.Mock(return_value=[mock.Mock()])
  297 
  298         wfb = mock.Mock()
  299         wfb.worker = FakeWorker('worker')
  300 
  301         with mock.patch(
  302                 'buildbot.process.build.Build._canAcquireLocks',
  303                 mock.Mock(return_value=False)):
  304             startable = yield self.bldr.canStartBuild(wfb, 100)
  305             self.assertEqual(startable, False)
  306 
  307     @defer.inlineCallbacks
  308     def test_canStartBuild_with_renderable_locks(self):
  309         yield self.makeBuilder()
  310 
  311         self.bldr.botmaster.getLockFromLockAccesses = mock.Mock(return_value=[mock.Mock()])
  312 
  313         renderedLocks = [False]
  314 
  315         @renderer
  316         def rendered_locks(props):
  317             renderedLocks[0] = True
  318             return [mock.Mock()]
  319 
  320         self.bldr.config.locks = rendered_locks
  321 
  322         wfb = mock.Mock()
  323         wfb.worker = FakeWorker('worker')
  324 
  325         with mock.patch(
  326                 'buildbot.process.build.Build._canAcquireLocks',
  327                 mock.Mock(return_value=False)):
  328             with mock.patch(
  329                     'buildbot.process.build.Build.setupPropertiesKnownBeforeBuildStarts',
  330                     mock.Mock()):
  331                 startable = yield self.bldr.canStartBuild(wfb, 100)
  332                 self.assertEqual(startable, False)
  333 
  334         self.assertTrue(renderedLocks[0])
  335 
  336     @defer.inlineCallbacks
  337     def test_canStartBuild_with_incompatible_latent_worker(self):
  338         yield self.makeBuilder()
  339 
  340         class FakeLatentWorker(AbstractLatentWorker):
  341             builds_may_be_incompatible = True
  342 
  343             def __init__(self):
  344                 pass
  345 
  346             def isCompatibleWithBuild(self, build_props):
  347                 return defer.succeed(False)
  348 
  349             def checkConfig(self, name, _, **kwargs):
  350                 pass
  351 
  352             def reconfigService(self, name, _, **kwargs):
  353                 pass
  354 
  355         wfb = mock.Mock()
  356         wfb.worker = FakeLatentWorker()
  357 
  358         with mock.patch(
  359                 'buildbot.process.build.Build.setupPropertiesKnownBeforeBuildStarts',
  360                 mock.Mock()):
  361             startable = yield self.bldr.canStartBuild(wfb, 100)
  362         self.assertFalse(startable)
  363 
  364     @defer.inlineCallbacks
  365     def test_canStartBuild_enforceChosenWorker(self):
  366         """enforceChosenWorker rejects and accepts builds"""
  367         yield self.makeBuilder()
  368 
  369         self.bldr.config.canStartBuild = builder.enforceChosenWorker
  370 
  371         workerforbuilder = mock.Mock()
  372         workerforbuilder.worker = FakeWorker('worker5')
  373 
  374         breq = mock.Mock()
  375 
  376         # no worker requested
  377         breq.properties = {}
  378         result = yield self.bldr.canStartBuild(workerforbuilder, breq)
  379         self.assertIdentical(True, result)
  380 
  381         # worker requested as the right one
  382         breq.properties = {'workername': 'worker5'}
  383         result = yield self.bldr.canStartBuild(workerforbuilder, breq)
  384         self.assertIdentical(True, result)
  385 
  386         # worker requested as the wrong one
  387         breq.properties = {'workername': 'worker4'}
  388         result = yield self.bldr.canStartBuild(workerforbuilder, breq)
  389         self.assertIdentical(False, result)
  390 
  391         # worker set to non string value gets skipped
  392         breq.properties = {'workername': 0}
  393         result = yield self.bldr.canStartBuild(workerforbuilder, breq)
  394         self.assertIdentical(True, result)
  395 
  396     # other methods
  397 
  398     @defer.inlineCallbacks
  399     def test_getBuilderId(self):
  400         self.factory = factory.BuildFactory()
  401         self.master = fakemaster.make_master(self, wantData=True)
  402         # only include the necessary required config, plus user-requested
  403         self.bldr = builder.Builder('bldr')
  404         self.bldr.master = self.master
  405         self.master.data.updates.findBuilderId = fbi = mock.Mock()
  406         fbi.return_value = defer.succeed(13)
  407 
  408         builderid = yield self.bldr.getBuilderId()
  409         self.assertEqual(builderid, 13)
  410         fbi.assert_called_with('bldr')
  411         fbi.reset_mock()
  412 
  413         builderid = yield self.bldr.getBuilderId()
  414         self.assertEqual(builderid, 13)
  415         fbi.assert_not_called()
  416 
  417     def test_expectations_deprecated(self):
  418         self.successResultOf(self.makeBuilder())
  419 
  420         with assertProducesWarning(
  421                 Warning,
  422                 message_pattern="'Builder.expectations' is deprecated."):
  423             deprecated = self.bldr.expectations
  424 
  425         self.assertIdentical(deprecated, None)
  426 
  427     @defer.inlineCallbacks
  428     def test_defaultProperties(self):
  429         props = Properties()
  430         props.setProperty('foo', 1, 'Scheduler')
  431         props.setProperty('bar', 'bleh', 'Change')
  432 
  433         yield self.makeBuilder(defaultProperties={'bar': 'onoes', 'cuckoo': 42})
  434 
  435         self.bldr.setupProperties(props)
  436 
  437         self.assertEquals(props.getProperty('bar'), 'bleh')
  438         self.assertEquals(props.getProperty('cuckoo'), 42)
  439 
  440 
  441 class TestGetBuilderId(TestReactorMixin, BuilderMixin, unittest.TestCase):
  442 
  443     def setUp(self):
  444         self.setUpTestReactor()
  445         self.setUpBuilderMixin()
  446 
  447     @defer.inlineCallbacks
  448     def test_getBuilderId(self):
  449         # noReconfig because reconfigService calls getBuilderId, and we haven't
  450         # set up the mock findBuilderId yet.
  451         yield self.makeBuilder(name='b1', noReconfig=True)
  452         fbi = self.master.data.updates.findBuilderId = mock.Mock(name='fbi')
  453         fbi.side_effect = lambda name: defer.succeed(13)
  454         # call twice..
  455         self.assertEqual((yield self.bldr.getBuilderId()), 13)
  456         self.assertEqual((yield self.bldr.getBuilderId()), 13)
  457         # and see that fbi was only called once
  458         fbi.assert_called_once_with('b1')
  459         # check that the name was unicodified
  460         arg = fbi.mock_calls[0][1][0]
  461         self.assertIsInstance(arg, str)
  462 
  463 
  464 class TestGetOldestRequestTime(TestReactorMixin, BuilderMixin,
  465                                unittest.TestCase):
  466 
  467     @defer.inlineCallbacks
  468     def setUp(self):
  469         self.setUpTestReactor()
  470         self.setUpBuilderMixin()
  471 
  472         # a collection of rows that would otherwise clutter up every test
  473         master_id = fakedb.FakeBuildRequestsComponent.MASTER_ID
  474         self.base_rows = [
  475             fakedb.SourceStamp(id=21),
  476             fakedb.Buildset(id=11, reason='because'),
  477             fakedb.BuildsetSourceStamp(buildsetid=11, sourcestampid=21),
  478             fakedb.Builder(id=77, name='bldr1'),
  479             fakedb.Builder(id=78, name='bldr2'),
  480             fakedb.Builder(id=182, name='foo@bar'),
  481             fakedb.BuildRequest(id=111, submitted_at=1000,
  482                                 builderid=77, buildsetid=11),
  483             fakedb.BuildRequest(id=222, submitted_at=2000,
  484                                 builderid=77, buildsetid=11),
  485             fakedb.BuildRequestClaim(brid=222, masterid=master_id,
  486                                      claimed_at=2001),
  487             fakedb.BuildRequest(id=333, submitted_at=3000,
  488                                 builderid=77, buildsetid=11),
  489             fakedb.BuildRequest(id=444, submitted_at=2500,
  490                                 builderid=78, buildsetid=11),
  491             fakedb.BuildRequestClaim(brid=444, masterid=master_id,
  492                                      claimed_at=2501),
  493             fakedb.BuildRequest(id=555, submitted_at=2800,
  494                                 builderid=182, buildsetid=11),
  495         ]
  496         yield self.db.insertTestData(self.base_rows)
  497 
  498     @defer.inlineCallbacks
  499     def test_gort_unclaimed(self):
  500         yield self.makeBuilder(name='bldr1')
  501         rqtime = yield self.bldr.getOldestRequestTime()
  502         self.assertEqual(rqtime, epoch2datetime(1000))
  503 
  504     @defer.inlineCallbacks
  505     def test_gort_bldr_name_not_identifier(self):
  506         # this is a regression test for #2940
  507         yield self.makeBuilder(name='foo@bar')
  508         rqtime = yield self.bldr.getOldestRequestTime()
  509         self.assertEqual(rqtime, epoch2datetime(2800))
  510 
  511     @defer.inlineCallbacks
  512     def test_gort_all_claimed(self):
  513         yield self.makeBuilder(name='bldr2')
  514         rqtime = yield self.bldr.getOldestRequestTime()
  515         self.assertEqual(rqtime, None)
  516 
  517 
  518 class TestGetNewestCompleteTime(TestReactorMixin, BuilderMixin, unittest.TestCase):
  519 
  520     @defer.inlineCallbacks
  521     def setUp(self):
  522         self.setUpTestReactor()
  523         self.setUpBuilderMixin()
  524 
  525         # a collection of rows that would otherwise clutter up every test
  526         master_id = fakedb.FakeBuildRequestsComponent.MASTER_ID
  527         self.base_rows = [
  528             fakedb.SourceStamp(id=21),
  529             fakedb.Buildset(id=11, reason='because'),
  530             fakedb.BuildsetSourceStamp(buildsetid=11, sourcestampid=21),
  531             fakedb.Builder(id=77, name='bldr1'),
  532             fakedb.Builder(id=78, name='bldr2'),
  533             fakedb.BuildRequest(id=111, submitted_at=1000, complete_at=1000,
  534                                 builderid=77, buildsetid=11),
  535             fakedb.BuildRequest(id=222, submitted_at=2000, complete_at=4000,
  536                                 builderid=77, buildsetid=11),
  537             fakedb.BuildRequest(id=333, submitted_at=3000, complete_at=3000,
  538                                 builderid=77, buildsetid=11),
  539             fakedb.BuildRequest(id=444, submitted_at=2500,
  540                                 builderid=78, buildsetid=11),
  541             fakedb.BuildRequestClaim(brid=444, masterid=master_id,
  542                                      claimed_at=2501),
  543         ]
  544         yield self.db.insertTestData(self.base_rows)
  545 
  546     @defer.inlineCallbacks
  547     def test_gnct_completed(self):
  548         yield self.makeBuilder(name='bldr1')
  549         rqtime = yield self.bldr.getNewestCompleteTime()
  550         self.assertEqual(rqtime, epoch2datetime(4000))
  551 
  552     @defer.inlineCallbacks
  553     def test_gnct_no_completed(self):
  554         yield self.makeBuilder(name='bldr2')
  555         rqtime = yield self.bldr.getNewestCompleteTime()
  556         self.assertEqual(rqtime, None)
  557 
  558 
  559 class TestReconfig(TestReactorMixin, BuilderMixin, unittest.TestCase):
  560 
  561     """Tests that a reconfig properly updates all attributes"""
  562 
  563     def setUp(self):
  564         self.setUpTestReactor()
  565         self.setUpBuilderMixin()
  566 
  567     @defer.inlineCallbacks
  568     def test_reconfig(self):
  569         yield self.makeBuilder(description="Old", tags=["OldTag"])
  570         config_args = dict(name='bldr', workername="wrk", builddir="bdir",
  571                            workerbuilddir="wbdir", factory=self.factory,
  572                            description='Noe', tags=['NewTag'])
  573         new_builder_config = config.BuilderConfig(**config_args)
  574         new_builder_config.description = "New"
  575         new_builder_config.tags = ["NewTag"]
  576 
  577         mastercfg = config.MasterConfig()
  578         mastercfg.builders = [new_builder_config]
  579         yield self.bldr.reconfigServiceWithBuildbotConfig(mastercfg)
  580         self.assertEqual(
  581             dict(description=self.bldr.builder_status.getDescription(),
  582                  tags=self.bldr.builder_status.getTags()),
  583             dict(description="New",
  584                  tags=["NewTag"]))
  585         self.assertIdentical(self.bldr.config, new_builder_config)
  586 
  587         # check that the reconfig grabbed a buliderid
  588         self.assertNotEqual(self.bldr._builderid, None)