~launchpad-pqm/launchpad/devel

11150.1.1 by Jeroen Vermeulen
Test cruft in buildmaster.
1
# Copyright 2009-2010 Canonical Ltd.  This software is licensed under the
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
4
"""Test Builder features."""
5
11573.3.4 by Jonathan Lange
Start to make BuilderSlave use composition instead of inheritance.
6
import os
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
7
import signal
11892.6.20 by Julian Edwards
Fix test failures due to jml's TestTools changes
8
import tempfile
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
9
import xmlrpclib
11319.1.1 by Julian Edwards
catch EINTR when polling builders
10
11705.2.23 by Jonathan Lange
Mostly move builder tests.
11
from testtools.deferredruntest import (
12
    assert_fails_with,
13
    AsynchronousDeferredRunTest,
11705.2.41 by Jonathan Lange
Use the new runner that handles Twisted brokenness.
14
    AsynchronousDeferredRunTestForBrokenTwisted,
11705.2.39 by Jonathan Lange
Rewrite the test to be correct, use testtools, have less cruft.
15
    SynchronousDeferredRunTest,
11705.2.23 by Jonathan Lange
Mostly move builder tests.
16
    )
17
11892.6.8 by Julian Edwards
add test for the new getFiles
18
from twisted.internet.defer import (
19
    CancelledError,
20
    DeferredList,
21
    )
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
22
from twisted.internet.task import Clock
23
from twisted.python.failure import Failure
11705.2.27 by Jonathan Lange
Fix the failing test by actually using AsynchronousDeferredRunTest.
24
from twisted.web.client import getPage
11573.3.8 by Jonathan Lange
Give ensurepresent an async API. Only change the unit tests, rest of code still broken.
25
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
26
from zope.component import getUtility
11705.2.31 by Jonathan Lange
Fix a glitch in the tests.
27
from zope.security.proxy import (
28
    isinstance as zope_isinstance,
29
    removeSecurityProxy,
30
    )
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
31
14339.1.1 by mbp at canonical
Delete canonical.buildd again
32
from lpbuildd.slave import BuilderStatus
33
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
34
from canonical.config import config
10888.7.3 by Julian Edwards
Add Builder.failure_count model/interface/test
35
from canonical.database.sqlbase import flush_database_updates
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
36
from canonical.launchpad.webapp.interfaces import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
37
    DEFAULT_FLAVOR,
38
    IStoreSelector,
39
    MAIN_STORE,
40
    )
10888.7.3 by Julian Edwards
Add Builder.failure_count model/interface/test
41
from canonical.testing.layers import (
10888.7.28 by Julian Edwards
merge db-devel
42
    DatabaseFunctionalLayer,
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
43
    LaunchpadZopelessLayer,
10888.7.28 by Julian Edwards
merge db-devel
44
    )
11458.1.1 by Jelmer Vernooij
Move enums of buildmaster.
45
from lp.buildmaster.enums import BuildStatus
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
46
from lp.buildmaster.interfaces.builder import (
47
    CannotFetchFile,
48
    IBuilder,
49
    IBuilderSet,
50
    )
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
51
from lp.buildmaster.interfaces.buildfarmjobbehavior import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
52
    IBuildFarmJobBehavior,
53
    )
10888.6.32 by Julian Edwards
move IBuildQueueSet.getByActiveBuilder to IBuilder.getBuildQueue
54
from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
55
from lp.buildmaster.interfaces.builder import CannotResumeHost
11929.3.3 by Julian Edwards
fix and test tweaks
56
from lp.buildmaster.model.builder import (
57
    BuilderSlave,
58
    ProxyWithConnectionTimeout,
59
    )
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
60
from lp.buildmaster.model.buildfarmjobbehavior import IdleBuildBehavior
7675.509.139 by William Grant
Move (I)BuildQueue(Set) to lp.buildmaster.
61
from lp.buildmaster.model.buildqueue import BuildQueue
11593.2.1 by Julian Edwards
move lib/lp/soyuz/tests/soyuzbuilddhelpers.py => lib/lp/buildmaster/tests/mock_slaves.py
62
from lp.buildmaster.tests.mock_slaves import (
63
    AbortedSlave,
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
64
    AbortingSlave,
65
    BrokenSlave,
66
    BuildingSlave,
67
    CorruptBehavior,
68
    DeadProxy,
69
    LostBuildingBrokenSlave,
11705.2.26 by Jonathan Lange
Factor out SoyuzTestPublisher construction so as to avoid circular imports.
70
    make_publisher,
11593.2.1 by Julian Edwards
move lib/lp/soyuz/tests/soyuzbuilddhelpers.py => lib/lp/buildmaster/tests/mock_slaves.py
71
    MockBuilder,
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
72
    OkSlave,
73
    SlaveTestHelpers,
74
    TrivialBehavior,
75
    WaitingSlave,
11593.2.1 by Julian Edwards
move lib/lp/soyuz/tests/soyuzbuilddhelpers.py => lib/lp/buildmaster/tests/mock_slaves.py
76
    )
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
77
from lp.services.job.interfaces.job import JobStatus
12070.1.4 by Tim Penhey
Move FakeLogger and BufferLogger to lp.services.log.logging and delete the QuietFakeLogger.
78
from lp.services.log.logger import BufferLogger
11411.6.12 by Julian Edwards
Move PackagePublishingStatus/Priority
79
from lp.soyuz.enums import (
80
    ArchivePurpose,
81
    PackagePublishingStatus,
82
    )
10667.2.2 by Michael Nelson
Mass renaming of imports and references to IBuild/Build/IBuildSet
83
from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
84
from lp.soyuz.model.binarypackagebuildbehavior import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
85
    BinaryPackageBuildBehavior,
86
    )
11573.3.4 by Jonathan Lange
Start to make BuilderSlave use composition instead of inheritance.
87
from lp.testing import (
11705.2.23 by Jonathan Lange
Mostly move builder tests.
88
    TestCase,
11573.3.4 by Jonathan Lange
Start to make BuilderSlave use composition instead of inheritance.
89
    TestCaseWithFactory,
90
    )
11319.1.1 by Julian Edwards
catch EINTR when polling builders
91
from lp.testing.fakemethod import FakeMethod
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
92
93
11983.2.2 by Julian Edwards
hide IBuilder.builderok behind another property so we can hook into its changes and reset the failure count
94
class TestBuilderBasics(TestCaseWithFactory):
10888.6.32 by Julian Edwards
move IBuildQueueSet.getByActiveBuilder to IBuilder.getBuildQueue
95
    """Basic unit tests for `Builder`."""
10888.7.3 by Julian Edwards
Add Builder.failure_count model/interface/test
96
97
    layer = DatabaseFunctionalLayer
98
99
    def test_providesInterface(self):
100
        # Builder provides IBuilder
101
        builder = self.factory.makeBuilder()
102
        self.assertProvides(builder, IBuilder)
103
104
    def test_default_values(self):
105
        builder = self.factory.makeBuilder()
10888.7.23 by Julian Edwards
jml's review comments
106
        # Make sure the Storm cache gets the values that the database
13194.2.1 by Gavin Panella
Change all uses of 'initialise' to 'initialize'.
107
        # initializes.
10888.7.3 by Julian Edwards
Add Builder.failure_count model/interface/test
108
        flush_database_updates()
109
        self.assertEqual(0, builder.failure_count)
110
10888.7.23 by Julian Edwards
jml's review comments
111
    def test_getCurrentBuildFarmJob(self):
112
        bq = self.factory.makeSourcePackageRecipeBuildJob(3333)
113
        builder = self.factory.makeBuilder()
114
        bq.markAsBuilding(builder)
115
        self.assertEqual(
116
            bq, builder.getCurrentBuildFarmJob().buildqueue_record)
117
10888.6.32 by Julian Edwards
move IBuildQueueSet.getByActiveBuilder to IBuilder.getBuildQueue
118
    def test_getBuildQueue(self):
119
        buildqueueset = getUtility(IBuildQueueSet)
120
        active_jobs = buildqueueset.getActiveBuildJobs()
121
        [active_job] = active_jobs
122
        builder = active_job.builder
123
124
        bq = builder.getBuildQueue()
125
        self.assertEqual(active_job, bq)
126
127
        active_job.builder = None
128
        bq = builder.getBuildQueue()
129
        self.assertIs(None, bq)
130
11983.2.2 by Julian Edwards
hide IBuilder.builderok behind another property so we can hook into its changes and reset the failure count
131
    def test_setting_builderok_resets_failure_count(self):
132
        builder = removeSecurityProxy(self.factory.makeBuilder())
133
        builder.failure_count = 1
134
        builder.builderok = False
135
        self.assertEqual(1, builder.failure_count)
136
        builder.builderok = True
137
        self.assertEqual(0, builder.failure_count)
138
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
139
11705.2.23 by Jonathan Lange
Mostly move builder tests.
140
class TestBuilder(TestCaseWithFactory):
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
141
11705.2.23 by Jonathan Lange
Mostly move builder tests.
142
    layer = LaunchpadZopelessLayer
11705.2.27 by Jonathan Lange
Fix the failing test by actually using AsynchronousDeferredRunTest.
143
    run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=10)
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
144
145
    def setUp(self):
11705.2.23 by Jonathan Lange
Mostly move builder tests.
146
        super(TestBuilder, self).setUp()
147
        self.slave_helper = self.useFixture(SlaveTestHelpers())
11892.3.1 by Julian Edwards
Refactor tests so they don't get run twice inadvertently
148
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
149
    def test_updateStatus_aborts_lost_and_broken_slave(self):
150
        # A slave that's 'lost' should be aborted; when the slave is
151
        # broken then abort() should also throw a fault.
152
        slave = LostBuildingBrokenSlave()
153
        lostbuilding_builder = MockBuilder(
154
            'Lost Building Broken Slave', slave, behavior=CorruptBehavior())
12070.1.4 by Tim Penhey
Move FakeLogger and BufferLogger to lp.services.log.logging and delete the QuietFakeLogger.
155
        d = lostbuilding_builder.updateStatus(BufferLogger())
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
156
        def check_slave_status(failure):
157
            self.assertIn('abort', slave.call_log)
158
            # 'Fault' comes from the LostBuildingBrokenSlave, this is
159
            # just testing that the value is passed through.
160
            self.assertIsInstance(failure.value, xmlrpclib.Fault)
161
        return d.addBoth(check_slave_status)
162
163
    def test_resumeSlaveHost_nonvirtual(self):
164
        builder = self.factory.makeBuilder(virtualized=False)
165
        d = builder.resumeSlaveHost()
11705.2.23 by Jonathan Lange
Mostly move builder tests.
166
        return assert_fails_with(d, CannotResumeHost)
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
167
168
    def test_resumeSlaveHost_no_vmhost(self):
169
        builder = self.factory.makeBuilder(virtualized=True, vm_host=None)
170
        d = builder.resumeSlaveHost()
11705.2.23 by Jonathan Lange
Mostly move builder tests.
171
        return assert_fails_with(d, CannotResumeHost)
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
172
173
    def test_resumeSlaveHost_success(self):
174
        reset_config = """
175
            [builddmaster]
176
            vm_resume_command: /bin/echo -n parp"""
177
        config.push('reset', reset_config)
178
        self.addCleanup(config.pop, 'reset')
179
180
        builder = self.factory.makeBuilder(virtualized=True, vm_host="pop")
181
        d = builder.resumeSlaveHost()
182
        def got_resume(output):
183
            self.assertEqual(('parp', ''), output)
184
        return d.addCallback(got_resume)
185
186
    def test_resumeSlaveHost_command_failed(self):
187
        reset_fail_config = """
188
            [builddmaster]
189
            vm_resume_command: /bin/false"""
190
        config.push('reset fail', reset_fail_config)
191
        self.addCleanup(config.pop, 'reset fail')
192
        builder = self.factory.makeBuilder(virtualized=True, vm_host="pop")
193
        d = builder.resumeSlaveHost()
11705.2.23 by Jonathan Lange
Mostly move builder tests.
194
        return assert_fails_with(d, CannotResumeHost)
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
195
196
    def test_handleTimeout_resume_failure(self):
197
        reset_fail_config = """
198
            [builddmaster]
199
            vm_resume_command: /bin/false"""
200
        config.push('reset fail', reset_fail_config)
201
        self.addCleanup(config.pop, 'reset fail')
202
        builder = self.factory.makeBuilder(virtualized=True, vm_host="pop")
203
        builder.builderok = True
12070.1.4 by Tim Penhey
Move FakeLogger and BufferLogger to lp.services.log.logging and delete the QuietFakeLogger.
204
        d = builder.handleTimeout(BufferLogger(), 'blah')
11705.2.23 by Jonathan Lange
Mostly move builder tests.
205
        return assert_fails_with(d, CannotResumeHost)
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
206
11892.3.2 by Julian Edwards
failing test added
207
    def _setupBuilder(self):
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
208
        processor = self.factory.makeProcessor(name="i386")
209
        builder = self.factory.makeBuilder(
210
            processor=processor, virtualized=True, vm_host="bladh")
211
        builder.setSlaveForTesting(OkSlave())
212
        distroseries = self.factory.makeDistroSeries()
213
        das = self.factory.makeDistroArchSeries(
214
            distroseries=distroseries, architecturetag="i386",
215
            processorfamily=processor.family)
216
        chroot = self.factory.makeLibraryFileAlias()
217
        das.addOrUpdateChroot(chroot)
218
        distroseries.nominatedarchindep = das
11892.3.2 by Julian Edwards
failing test added
219
        return builder, distroseries, das
220
221
    def _setupRecipeBuildAndBuilder(self):
222
        # Helper function to make a builder capable of building a
223
        # recipe, returning both.
224
        builder, distroseries, distroarchseries = self._setupBuilder()
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
225
        build = self.factory.makeSourcePackageRecipeBuild(
226
            distroseries=distroseries)
227
        return builder, build
228
11892.3.2 by Julian Edwards
failing test added
229
    def _setupBinaryBuildAndBuilder(self):
230
        # Helper function to make a builder capable of building a
231
        # binary package, returning both.
232
        builder, distroseries, distroarchseries = self._setupBuilder()
233
        build = self.factory.makeBinaryPackageBuild(
234
            distroarchseries=distroarchseries, builder=builder)
235
        return builder, build
236
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
237
    def test_findAndStartJob_returns_candidate(self):
238
        # findAndStartJob finds the next queued job using _findBuildCandidate.
239
        # We don't care about the type of build at all.
240
        builder, build = self._setupRecipeBuildAndBuilder()
241
        candidate = build.queueBuild()
242
        # _findBuildCandidate is tested elsewhere, we just make sure that
243
        # findAndStartJob delegates to it.
244
        removeSecurityProxy(builder)._findBuildCandidate = FakeMethod(
245
            result=candidate)
246
        d = builder.findAndStartJob()
247
        return d.addCallback(self.assertEqual, candidate)
248
249
    def test_findAndStartJob_starts_job(self):
250
        # findAndStartJob finds the next queued job using _findBuildCandidate
251
        # and then starts it.
252
        # We don't care about the type of build at all.
253
        builder, build = self._setupRecipeBuildAndBuilder()
254
        candidate = build.queueBuild()
255
        removeSecurityProxy(builder)._findBuildCandidate = FakeMethod(
256
            result=candidate)
257
        d = builder.findAndStartJob()
258
        def check_build_started(candidate):
259
            self.assertEqual(candidate.builder, builder)
260
            self.assertEqual(BuildStatus.BUILDING, build.status)
261
        return d.addCallback(check_build_started)
11593.3.21 by Jonathan Lange
Tests for findAndStartJob.
262
11981.1.2 by Julian Edwards
A test
263
    def test_virtual_job_dispatch_pings_before_building(self):
264
        # We need to send a ping to the builder to work around a bug
265
        # where sometimes the first network packet sent is dropped.
266
        builder, build = self._setupBinaryBuildAndBuilder()
267
        candidate = build.queueBuild()
268
        removeSecurityProxy(builder)._findBuildCandidate = FakeMethod(
269
            result=candidate)
270
        d = builder.findAndStartJob()
271
        def check_build_started(candidate):
272
            self.assertIn(
273
                ('echo', 'ping'), removeSecurityProxy(builder.slave).call_log)
274
        return d.addCallback(check_build_started)
275
11583.3.17 by Jonathan Lange
Fix the builder.txt doctest failure by moving the test out of a doctest,
276
    def test_slave(self):
277
        # Builder.slave is a BuilderSlave that points at the actual Builder.
278
        # The Builder is only ever used in scripts that run outside of the
279
        # security context.
280
        builder = removeSecurityProxy(self.factory.makeBuilder())
281
        self.assertEqual(builder.url, builder.slave.url)
282
12287.3.1 by Julian Edwards
Add test
283
    def test_recovery_of_aborted_virtual_slave(self):
284
        # If a virtual_slave is in the ABORTED state,
285
        # rescueBuilderIfLost should clean it if we don't think it's
286
        # currently building anything.
11403.3.2 by Julian Edwards
Ensure that a builder in the ABORTED state is reset properly so it can accept new builds.
287
        # See bug 463046.
11403.3.1 by Julian Edwards
Add a failing test
288
        aborted_slave = AbortedSlave()
289
        builder = MockBuilder("mock_builder", aborted_slave)
11403.3.2 by Julian Edwards
Ensure that a builder in the ABORTED state is reset properly so it can accept new builds.
290
        builder.currentjob = None
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
291
        d = builder.rescueIfLost()
292
        def check_slave_calls(ignored):
293
            self.assertIn('clean', aborted_slave.call_log)
294
        return d.addCallback(check_slave_calls)
295
12287.3.1 by Julian Edwards
Add test
296
    def test_recovery_of_aborted_nonvirtual_slave(self):
297
        # Nonvirtual slaves in the ABORTED state cannot be reliably
298
        # cleaned since the sbuild process doesn't properly kill the
299
        # build job.  We test that the builder is marked failed.
300
        aborted_slave = AbortedSlave()
301
        builder = MockBuilder("mock_builder", aborted_slave)
302
        builder.currentjob = None
303
        builder.virtualized = False
304
        builder.builderok = True
305
        d = builder.rescueIfLost()
306
        def check_failed(ignored):
307
            self.assertFalse(builder.builderok)
308
            self.assertNotIn('clean', aborted_slave.call_log)
309
        return d.addCallback(check_failed)
310
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
311
    def test_recover_ok_slave(self):
312
        # An idle slave is not rescued.
313
        slave = OkSlave()
314
        builder = MockBuilder("mock_builder", slave, TrivialBehavior())
315
        d = builder.rescueIfLost()
316
        def check_slave_calls(ignored):
317
            self.assertNotIn('abort', slave.call_log)
318
            self.assertNotIn('clean', slave.call_log)
319
        return d.addCallback(check_slave_calls)
320
321
    def test_recover_waiting_slave_with_good_id(self):
322
        # rescueIfLost does not attempt to abort or clean a builder that is
323
        # WAITING.
324
        waiting_slave = WaitingSlave()
325
        builder = MockBuilder("mock_builder", waiting_slave, TrivialBehavior())
326
        d = builder.rescueIfLost()
327
        def check_slave_calls(ignored):
328
            self.assertNotIn('abort', waiting_slave.call_log)
329
            self.assertNotIn('clean', waiting_slave.call_log)
330
        return d.addCallback(check_slave_calls)
331
332
    def test_recover_waiting_slave_with_bad_id(self):
333
        # If a slave is WAITING with a build for us to get, and the build
334
        # cookie cannot be verified, which means we don't recognize the build,
335
        # then rescueBuilderIfLost should attempt to abort it, so that the
336
        # builder is reset for a new build, and the corrupt build is
337
        # discarded.
338
        waiting_slave = WaitingSlave()
339
        builder = MockBuilder("mock_builder", waiting_slave, CorruptBehavior())
340
        d = builder.rescueIfLost()
341
        def check_slave_calls(ignored):
342
            self.assertNotIn('abort', waiting_slave.call_log)
343
            self.assertIn('clean', waiting_slave.call_log)
344
        return d.addCallback(check_slave_calls)
345
346
    def test_recover_building_slave_with_good_id(self):
347
        # rescueIfLost does not attempt to abort or clean a builder that is
348
        # BUILDING.
349
        building_slave = BuildingSlave()
350
        builder = MockBuilder("mock_builder", building_slave, TrivialBehavior())
351
        d = builder.rescueIfLost()
352
        def check_slave_calls(ignored):
353
            self.assertNotIn('abort', building_slave.call_log)
354
            self.assertNotIn('clean', building_slave.call_log)
355
        return d.addCallback(check_slave_calls)
356
357
    def test_recover_building_slave_with_bad_id(self):
358
        # If a slave is BUILDING with a build id we don't recognize, then we
359
        # abort the build, thus stopping it in its tracks.
360
        building_slave = BuildingSlave()
361
        builder = MockBuilder("mock_builder", building_slave, CorruptBehavior())
362
        d = builder.rescueIfLost()
363
        def check_slave_calls(ignored):
364
            self.assertIn('abort', building_slave.call_log)
365
            self.assertNotIn('clean', building_slave.call_log)
366
        return d.addCallback(check_slave_calls)
367
11892.3.2 by Julian Edwards
failing test added
368
    def test_recover_building_slave_with_job_that_finished_elsewhere(self):
369
        # See bug 671242
370
        # When a job is destroyed, the builder's behaviour should be reset
371
        # too so that we don't traceback when the wrong behaviour tries
372
        # to access a non-existent job.
373
        builder, build = self._setupBinaryBuildAndBuilder()
374
        candidate = build.queueBuild()
375
        building_slave = BuildingSlave()
376
        builder.setSlaveForTesting(building_slave)
377
        candidate.markAsBuilding(builder)
378
379
        # At this point we should see a valid behaviour on the builder:
11705.2.31 by Jonathan Lange
Fix a glitch in the tests.
380
        self.assertFalse(
381
            zope_isinstance(
382
                builder.current_build_behavior, IdleBuildBehavior))
11892.3.2 by Julian Edwards
failing test added
383
384
        # Now reset the job and try to rescue the builder.
385
        candidate.destroySelf()
386
        self.layer.txn.commit()
387
        builder = getUtility(IBuilderSet)[builder.name]
388
        d = builder.rescueIfLost()
389
        def check_builder(ignored):
11898.1.1 by Jonathan Lange
Upcall correctly, actually test a thing, avoid circular imports
390
            self.assertIsInstance(
391
                removeSecurityProxy(builder.current_build_behavior),
392
                IdleBuildBehavior)
393
        return d.addCallback(check_builder)
11892.3.2 by Julian Edwards
failing test added
394
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
395
11705.2.23 by Jonathan Lange
Mostly move builder tests.
396
class TestBuilderSlaveStatus(TestCaseWithFactory):
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
397
    # Verify what IBuilder.slaveStatus returns with slaves in different
398
    # states.
399
11705.2.23 by Jonathan Lange
Mostly move builder tests.
400
    layer = LaunchpadZopelessLayer
401
    run_tests_with = AsynchronousDeferredRunTest
402
403
    def setUp(self):
404
        super(TestBuilderSlaveStatus, self).setUp()
405
        self.slave_helper = self.useFixture(SlaveTestHelpers())
406
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
407
    def assertStatus(self, slave, builder_status=None,
408
                     build_status=None, logtail=False, filemap=None,
409
                     dependencies=None):
410
        builder = self.factory.makeBuilder()
411
        builder.setSlaveForTesting(slave)
412
        d = builder.slaveStatus()
413
414
        def got_status(status_dict):
415
            expected = {}
416
            if builder_status is not None:
417
                expected["builder_status"] = builder_status
418
            if build_status is not None:
419
                expected["build_status"] = build_status
420
            if dependencies is not None:
421
                expected["dependencies"] = dependencies
422
423
            # We don't care so much about the content of the logtail,
424
            # just that it's there.
425
            if logtail:
426
                tail = status_dict.pop("logtail")
427
                self.assertIsInstance(tail, xmlrpclib.Binary)
428
429
            self.assertEqual(expected, status_dict)
430
431
        return d.addCallback(got_status)
432
433
    def test_slaveStatus_idle_slave(self):
434
        self.assertStatus(
435
            OkSlave(), builder_status='BuilderStatus.IDLE')
436
437
    def test_slaveStatus_building_slave(self):
438
        self.assertStatus(
439
            BuildingSlave(), builder_status='BuilderStatus.BUILDING',
440
            logtail=True)
441
442
    def test_slaveStatus_waiting_slave(self):
443
        self.assertStatus(
444
            WaitingSlave(), builder_status='BuilderStatus.WAITING',
445
            build_status='BuildStatus.OK', filemap={})
446
447
    def test_slaveStatus_aborting_slave(self):
448
        self.assertStatus(
449
            AbortingSlave(), builder_status='BuilderStatus.ABORTING')
450
451
    def test_slaveStatus_aborted_slave(self):
452
        self.assertStatus(
453
            AbortedSlave(), builder_status='BuilderStatus.ABORTED')
454
455
    def test_isAvailable_with_not_builderok(self):
456
        # isAvailable() is a wrapper around slaveStatusSentence()
457
        builder = self.factory.makeBuilder()
458
        builder.builderok = False
459
        d = builder.isAvailable()
460
        return d.addCallback(self.assertFalse)
461
462
    def test_isAvailable_with_slave_fault(self):
463
        builder = self.factory.makeBuilder()
464
        builder.setSlaveForTesting(BrokenSlave())
465
        d = builder.isAvailable()
466
        return d.addCallback(self.assertFalse)
467
468
    def test_isAvailable_with_slave_idle(self):
469
        builder = self.factory.makeBuilder()
470
        builder.setSlaveForTesting(OkSlave())
471
        d = builder.isAvailable()
472
        return d.addCallback(self.assertTrue)
11593.3.79 by Julian Edwards
Add unit test for IBuilder.isAvailable()
473
11403.3.1 by Julian Edwards
Add a failing test
474
9686.2.7 by Michael Nelson
Some test refactoring after allenaps review.
475
class TestFindBuildCandidateBase(TestCaseWithFactory):
476
    """Setup the test publisher and some builders."""
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
477
478
    layer = LaunchpadZopelessLayer
479
480
    def setUp(self):
9686.2.7 by Michael Nelson
Some test refactoring after allenaps review.
481
        super(TestFindBuildCandidateBase, self).setUp()
11705.2.26 by Jonathan Lange
Factor out SoyuzTestPublisher construction so as to avoid circular imports.
482
        self.publisher = make_publisher()
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
483
        self.publisher.prepareBreezyAutotest()
484
9849.1.2 by Julian Edwards
Fix findBuildCandidate so that instead of only allowing one builder per arch for each PPA, it allows up to 80% of the available builders for that arch.
485
        # Create some i386 builders ready to build PPA builds.  Two
486
        # already exist in sampledata so we'll use those first.
487
        self.builder1 = getUtility(IBuilderSet)['bob']
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
488
        self.frog_builder = getUtility(IBuilderSet)['frog']
9849.1.1 by Julian Edwards
Test changed to create new failing tests
489
        self.builder3 = self.factory.makeBuilder(name='builder3')
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
490
        self.builder4 = self.factory.makeBuilder(name='builder4')
9849.1.1 by Julian Edwards
Test changed to create new failing tests
491
        self.builder5 = self.factory.makeBuilder(name='builder5')
492
        self.builders = [
493
            self.builder1,
10133.2.5 by Muharem Hrnjadovic
test_builder.py passes
494
            self.frog_builder,
9849.1.1 by Julian Edwards
Test changed to create new failing tests
495
            self.builder3,
496
            self.builder4,
497
            self.builder5,
498
            ]
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
499
9849.1.6 by Julian Edwards
Make sure the build is still dispatched when there's only one builder available.
500
        # Ensure all builders are operational.
501
        for builder in self.builders:
502
            builder.builderok = True
503
            builder.manual = False
504
505
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
506
class TestFindBuildCandidateGeneralCases(TestFindBuildCandidateBase):
507
    # Test usage of findBuildCandidate not specific to any archive type.
508
509
    def test_findBuildCandidate_supersedes_builds(self):
510
        # IBuilder._findBuildCandidate identifies if there are builds
511
        # for superseded source package releases in the queue and marks
512
        # the corresponding build record as SUPERSEDED.
513
        archive = self.factory.makeArchive()
514
        self.publisher.getPubSource(
515
            sourcename="gedit", status=PackagePublishingStatus.PUBLISHED,
516
            archive=archive).createMissingBuilds()
517
        old_candidate = removeSecurityProxy(
518
            self.frog_builder)._findBuildCandidate()
519
520
        # The candidate starts off as NEEDSBUILD:
521
        build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(
522
            old_candidate)
523
        self.assertEqual(BuildStatus.NEEDSBUILD, build.status)
524
525
        # Now supersede the source package:
526
        publication = build.current_source_publication
527
        publication.status = PackagePublishingStatus.SUPERSEDED
528
529
        # The candidate returned is now a different one:
530
        new_candidate = removeSecurityProxy(
531
            self.frog_builder)._findBuildCandidate()
532
        self.assertNotEqual(new_candidate, old_candidate)
533
534
        # And the old_candidate is superseded:
535
        self.assertEqual(BuildStatus.SUPERSEDED, build.status)
536
537
    def test_acquireBuildCandidate_marks_building(self):
538
        # acquireBuildCandidate() should call _findBuildCandidate and
539
        # mark the build as building.
540
        archive = self.factory.makeArchive()
541
        self.publisher.getPubSource(
542
            sourcename="gedit", status=PackagePublishingStatus.PUBLISHED,
543
            archive=archive).createMissingBuilds()
544
        candidate = removeSecurityProxy(
545
            self.frog_builder).acquireBuildCandidate()
546
        self.assertEqual(JobStatus.RUNNING, candidate.job.status)
547
548
9849.1.6 by Julian Edwards
Make sure the build is still dispatched when there's only one builder available.
549
class TestFindBuildCandidatePPAWithSingleBuilder(TestCaseWithFactory):
550
551
    layer = LaunchpadZopelessLayer
552
553
    def setUp(self):
554
        super(TestFindBuildCandidatePPAWithSingleBuilder, self).setUp()
11705.2.26 by Jonathan Lange
Factor out SoyuzTestPublisher construction so as to avoid circular imports.
555
        self.publisher = make_publisher()
9849.1.6 by Julian Edwards
Make sure the build is still dispatched when there's only one builder available.
556
        self.publisher.prepareBreezyAutotest()
557
558
        self.bob_builder = getUtility(IBuilderSet)['bob']
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
559
        self.frog_builder = getUtility(IBuilderSet)['frog']
9849.1.6 by Julian Edwards
Make sure the build is still dispatched when there's only one builder available.
560
561
        # Disable bob so only frog is available.
562
        self.bob_builder.manual = True
563
        self.bob_builder.builderok = True
564
        self.frog_builder.manual = False
565
        self.frog_builder.builderok = True
566
567
        # Make a new PPA and give it some builds.
568
        self.ppa_joe = self.factory.makeArchive(name="joesppa")
7675.509.141 by William Grant
Fix lint.
569
        self.publisher.getPubSource(
9849.1.6 by Julian Edwards
Make sure the build is still dispatched when there's only one builder available.
570
            sourcename="gedit", status=PackagePublishingStatus.PUBLISHED,
571
            archive=self.ppa_joe).createMissingBuilds()
572
573
    def test_findBuildCandidate_first_build_started(self):
574
        # The allocation rule for PPA dispatching doesn't apply when
575
        # there's only one builder available.
576
577
        # Asking frog to find a candidate should give us the joesppa build.
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
578
        next_job = removeSecurityProxy(
579
            self.frog_builder)._findBuildCandidate()
10667.2.2 by Michael Nelson
Mass renaming of imports and references to IBuild/Build/IBuildSet
580
        build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(next_job)
7675.390.2 by Muharem Hrnjadovic
All build related tests pass.
581
        self.assertEqual('joesppa', build.archive.name)
9849.1.6 by Julian Edwards
Make sure the build is still dispatched when there's only one builder available.
582
583
        # If bob is in a failed state the joesppa build is still
584
        # returned.
585
        self.bob_builder.builderok = False
586
        self.bob_builder.manual = False
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
587
        next_job = removeSecurityProxy(
588
            self.frog_builder)._findBuildCandidate()
10667.2.2 by Michael Nelson
Mass renaming of imports and references to IBuild/Build/IBuildSet
589
        build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(next_job)
7675.390.2 by Muharem Hrnjadovic
All build related tests pass.
590
        self.assertEqual('joesppa', build.archive.name)
9849.1.6 by Julian Edwards
Make sure the build is still dispatched when there's only one builder available.
591
9686.2.7 by Michael Nelson
Some test refactoring after allenaps review.
592
10316.1.18 by Michael Nelson
Fixed broken test.
593
class TestFindBuildCandidatePPABase(TestFindBuildCandidateBase):
594
595
    ppa_joe_private = False
596
    ppa_jim_private = False
9686.2.7 by Michael Nelson
Some test refactoring after allenaps review.
597
9849.1.1 by Julian Edwards
Test changed to create new failing tests
598
    def _setBuildsBuildingForArch(self, builds_list, num_builds,
599
                                  archtag="i386"):
600
        """Helper function.
601
602
        Set the first `num_builds` in `builds_list` with `archtag` as
603
        BUILDING.
604
        """
605
        count = 0
9849.1.5 by Julian Edwards
bac's review improvement to avoid loop breaking. Also remove a redundant comment.
606
        for build in builds_list[:num_builds]:
7675.687.124 by Michael Nelson
Merged current db-devel and resolved conflicts and updated tests slightly where necessary.
607
            if build.distro_arch_series.architecturetag == archtag:
608
                build.status = BuildStatus.BUILDING
9849.1.1 by Julian Edwards
Test changed to create new failing tests
609
                build.builder = self.builders[count]
610
            count += 1
611
10316.1.18 by Michael Nelson
Fixed broken test.
612
    def setUp(self):
613
        """Publish some builds for the test archive."""
614
        super(TestFindBuildCandidatePPABase, self).setUp()
9686.2.7 by Michael Nelson
Some test refactoring after allenaps review.
615
616
        # Create two PPAs and add some builds to each.
10316.1.18 by Michael Nelson
Fixed broken test.
617
        self.ppa_joe = self.factory.makeArchive(
618
            name="joesppa", private=self.ppa_joe_private)
619
        self.ppa_jim = self.factory.makeArchive(
620
            name="jimsppa", private=self.ppa_jim_private)
10316.1.12 by Michael Nelson
Fixed TestFindBuildCandidatePrivatePPA.
621
9849.1.1 by Julian Edwards
Test changed to create new failing tests
622
        self.joe_builds = []
623
        self.joe_builds.extend(
624
            self.publisher.getPubSource(
625
                sourcename="gedit", status=PackagePublishingStatus.PUBLISHED,
626
                archive=self.ppa_joe).createMissingBuilds())
627
        self.joe_builds.extend(
628
            self.publisher.getPubSource(
9849.1.3 by Julian Edwards
fix lint
629
                sourcename="firefox",
630
                status=PackagePublishingStatus.PUBLISHED,
9849.1.1 by Julian Edwards
Test changed to create new failing tests
631
                archive=self.ppa_joe).createMissingBuilds())
632
        self.joe_builds.extend(
633
            self.publisher.getPubSource(
9849.1.3 by Julian Edwards
fix lint
634
                sourcename="cobblers",
635
                status=PackagePublishingStatus.PUBLISHED,
9849.1.1 by Julian Edwards
Test changed to create new failing tests
636
                archive=self.ppa_joe).createMissingBuilds())
637
        self.joe_builds.extend(
638
            self.publisher.getPubSource(
639
                sourcename="thunderpants",
640
                status=PackagePublishingStatus.PUBLISHED,
641
                archive=self.ppa_joe).createMissingBuilds())
642
643
        self.jim_builds = []
644
        self.jim_builds.extend(
645
            self.publisher.getPubSource(
9849.1.3 by Julian Edwards
fix lint
646
                sourcename="gedit",
647
                status=PackagePublishingStatus.PUBLISHED,
648
                archive=self.ppa_jim).createMissingBuilds())
649
        self.jim_builds.extend(
650
            self.publisher.getPubSource(
651
                sourcename="firefox",
652
                status=PackagePublishingStatus.PUBLISHED,
9849.1.1 by Julian Edwards
Test changed to create new failing tests
653
                archive=self.ppa_jim).createMissingBuilds())
654
655
        # Set the first three builds in joe's PPA as building, which
656
        # leaves two builders free.
657
        self._setBuildsBuildingForArch(self.joe_builds, 3)
658
        num_active_builders = len(
659
            [build for build in self.joe_builds if build.builder is not None])
660
        num_free_builders = len(self.builders) - num_active_builders
661
        self.assertEqual(num_free_builders, 2)
9686.2.7 by Michael Nelson
Some test refactoring after allenaps review.
662
10316.1.18 by Michael Nelson
Fixed broken test.
663
664
class TestFindBuildCandidatePPA(TestFindBuildCandidatePPABase):
665
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
666
    def test_findBuildCandidate_first_build_started(self):
9849.1.2 by Julian Edwards
Fix findBuildCandidate so that instead of only allowing one builder per arch for each PPA, it allows up to 80% of the available builders for that arch.
667
        # A PPA cannot start a build if it would use 80% or more of the
668
        # builders.
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
669
        next_job = removeSecurityProxy(self.builder4)._findBuildCandidate()
10667.2.2 by Michael Nelson
Mass renaming of imports and references to IBuild/Build/IBuildSet
670
        build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(next_job)
7675.391.23 by Muharem Hrnjadovic
Fixed more tests.
671
        self.failIfEqual('joesppa', build.archive.name)
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
672
673
    def test_findBuildCandidate_first_build_finished(self):
9849.1.1 by Julian Edwards
Test changed to create new failing tests
674
        # When joe's first ppa build finishes, his fourth i386 build
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
675
        # will be the next build candidate.
7675.687.124 by Michael Nelson
Merged current db-devel and resolved conflicts and updated tests slightly where necessary.
676
        self.joe_builds[0].status = BuildStatus.FAILEDTOBUILD
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
677
        next_job = removeSecurityProxy(self.builder4)._findBuildCandidate()
10667.2.2 by Michael Nelson
Mass renaming of imports and references to IBuild/Build/IBuildSet
678
        build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(next_job)
7675.391.23 by Muharem Hrnjadovic
Fixed more tests.
679
        self.failUnlessEqual('joesppa', build.archive.name)
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
680
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
681
    def test_findBuildCandidate_with_disabled_archive(self):
682
        # Disabled archives should not be considered for dispatching
683
        # builds.
684
        disabled_job = removeSecurityProxy(self.builder4)._findBuildCandidate()
685
        build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(
686
            disabled_job)
687
        build.archive.disable()
688
        next_job = removeSecurityProxy(self.builder4)._findBuildCandidate()
689
        self.assertNotEqual(disabled_job, next_job)
690
11593.3.71 by Julian Edwards
Move disabled archive dispatch checking from buildd-slavescanner.txt to test_builder.py
691
10316.1.18 by Michael Nelson
Fixed broken test.
692
class TestFindBuildCandidatePrivatePPA(TestFindBuildCandidatePPABase):
10316.1.12 by Michael Nelson
Fixed TestFindBuildCandidatePrivatePPA.
693
10316.1.18 by Michael Nelson
Fixed broken test.
694
    ppa_joe_private = True
10316.1.12 by Michael Nelson
Fixed TestFindBuildCandidatePrivatePPA.
695
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
696
    def test_findBuildCandidate_for_private_ppa(self):
697
        # If a ppa is private it will be able to have parallel builds
698
        # for the one architecture.
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
699
        next_job = removeSecurityProxy(self.builder4)._findBuildCandidate()
10667.2.2 by Michael Nelson
Mass renaming of imports and references to IBuild/Build/IBuildSet
700
        build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(next_job)
7675.391.23 by Muharem Hrnjadovic
Fixed more tests.
701
        self.failUnlessEqual('joesppa', build.archive.name)
9686.2.1 by Michael Nelson
Added failing test (and other unit tests) for bug 450124 - ensuring a p3a can have parallel builds for a given arch.
702
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
703
        # If the source for the build is still pending, it won't be
704
        # dispatched because the builder has to fetch the source files
705
        # from the (password protected) repo area, not the librarian.
706
        pub = build.current_source_publication
707
        pub.status = PackagePublishingStatus.PENDING
708
        candidate = removeSecurityProxy(self.builder4)._findBuildCandidate()
709
        self.assertNotEqual(next_job.id, candidate.id)
710
9686.2.7 by Michael Nelson
Some test refactoring after allenaps review.
711
712
class TestFindBuildCandidateDistroArchive(TestFindBuildCandidateBase):
713
714
    def setUp(self):
715
        """Publish some builds for the test archive."""
716
        super(TestFindBuildCandidateDistroArchive, self).setUp()
717
        # Create a primary archive and publish some builds for the
718
        # queue.
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
719
        self.non_ppa = self.factory.makeArchive(
9686.2.6 by Michael Nelson
Added a test for non-ppa builds - ensuring they can happen in parallel.
720
            name="primary", purpose=ArchivePurpose.PRIMARY)
721
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
722
        self.gedit_build = self.publisher.getPubSource(
9686.2.6 by Michael Nelson
Added a test for non-ppa builds - ensuring they can happen in parallel.
723
            sourcename="gedit", status=PackagePublishingStatus.PUBLISHED,
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
724
            archive=self.non_ppa).createMissingBuilds()[0]
725
        self.firefox_build = self.publisher.getPubSource(
9686.2.6 by Michael Nelson
Added a test for non-ppa builds - ensuring they can happen in parallel.
726
            sourcename="firefox", status=PackagePublishingStatus.PUBLISHED,
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
727
            archive=self.non_ppa).createMissingBuilds()[0]
9686.2.6 by Michael Nelson
Added a test for non-ppa builds - ensuring they can happen in parallel.
728
9686.2.7 by Michael Nelson
Some test refactoring after allenaps review.
729
    def test_findBuildCandidate_for_non_ppa(self):
730
        # Normal archives are not restricted to serial builds per
731
        # arch.
9686.2.6 by Michael Nelson
Added a test for non-ppa builds - ensuring they can happen in parallel.
732
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
733
        next_job = removeSecurityProxy(
734
            self.frog_builder)._findBuildCandidate()
10667.2.2 by Michael Nelson
Mass renaming of imports and references to IBuild/Build/IBuildSet
735
        build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(next_job)
7675.391.23 by Muharem Hrnjadovic
Fixed more tests.
736
        self.failUnlessEqual('primary', build.archive.name)
7675.687.124 by Michael Nelson
Merged current db-devel and resolved conflicts and updated tests slightly where necessary.
737
        self.failUnlessEqual('gedit', build.source_package_release.name)
9686.2.6 by Michael Nelson
Added a test for non-ppa builds - ensuring they can happen in parallel.
738
739
        # Now even if we set the build building, we'll still get the
740
        # second non-ppa build for the same archive as the next candidate.
7675.687.124 by Michael Nelson
Merged current db-devel and resolved conflicts and updated tests slightly where necessary.
741
        build.status = BuildStatus.BUILDING
10133.2.5 by Muharem Hrnjadovic
test_builder.py passes
742
        build.builder = self.frog_builder
10133.2.7 by Muharem Hrnjadovic
Björn's review comments
743
        next_job = removeSecurityProxy(
744
            self.frog_builder)._findBuildCandidate()
10667.2.2 by Michael Nelson
Mass renaming of imports and references to IBuild/Build/IBuildSet
745
        build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(next_job)
7675.391.23 by Muharem Hrnjadovic
Fixed more tests.
746
        self.failUnlessEqual('primary', build.archive.name)
7675.687.124 by Michael Nelson
Merged current db-devel and resolved conflicts and updated tests slightly where necessary.
747
        self.failUnlessEqual('firefox', build.source_package_release.name)
9686.2.6 by Michael Nelson
Added a test for non-ppa builds - ensuring they can happen in parallel.
748
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
749
    def test_findBuildCandidate_for_recipe_build(self):
750
        # Recipe builds with a higher score are selected first.
751
        # This test is run in a context with mixed recipe and binary builds.
752
7675.464.2 by Muharem Hrnjadovic
Jono's review comments
753
        self.assertIsNot(self.frog_builder.processor, None)
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
754
        self.assertEqual(self.frog_builder.virtualized, True)
755
756
        self.assertEqual(self.gedit_build.buildqueue_record.lastscore, 2505)
757
        self.assertEqual(self.firefox_build.buildqueue_record.lastscore, 2505)
758
11070.2.15 by Paul Hummer
Unclogging the pipe
759
        recipe_build_job = self.factory.makeSourcePackageRecipeBuildJob(9999)
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
760
761
        self.assertEqual(recipe_build_job.lastscore, 9999)
762
763
        next_job = removeSecurityProxy(
764
            self.frog_builder)._findBuildCandidate()
765
766
        self.failUnlessEqual(recipe_build_job, next_job)
767
768
769
class TestFindRecipeBuildCandidates(TestFindBuildCandidateBase):
770
    # These tests operate in a "recipe builds only" setting.
771
    # Please see also bug #507782.
772
7675.464.2 by Muharem Hrnjadovic
Jono's review comments
773
    def clearBuildQueue(self):
774
        """Delete all `BuildQueue`, XXXJOb and `Job` instances."""
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
775
        store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
7675.464.2 by Muharem Hrnjadovic
Jono's review comments
776
        for bq in store.find(BuildQueue):
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
777
            bq.destroySelf()
778
779
    def setUp(self):
780
        """Publish some builds for the test archive."""
781
        super(TestFindRecipeBuildCandidates, self).setUp()
782
        # Create a primary archive and publish some builds for the
783
        # queue.
784
        self.non_ppa = self.factory.makeArchive(
785
            name="primary", purpose=ArchivePurpose.PRIMARY)
786
7675.464.2 by Muharem Hrnjadovic
Jono's review comments
787
        self.clearBuildQueue()
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
788
        self.bq1 = self.factory.makeSourcePackageRecipeBuildJob(3333)
789
        self.bq2 = self.factory.makeSourcePackageRecipeBuildJob(4333)
790
791
    def test_findBuildCandidate_with_highest_score(self):
792
        # The recipe build with the highest score is selected first.
793
        # This test is run in a "recipe builds only" context.
794
7675.464.2 by Muharem Hrnjadovic
Jono's review comments
795
        self.assertIsNot(self.frog_builder.processor, None)
7675.464.1 by Muharem Hrnjadovic
imported fix for candidate job selection
796
        self.assertEqual(self.frog_builder.virtualized, True)
797
798
        next_job = removeSecurityProxy(
799
            self.frog_builder)._findBuildCandidate()
800
801
        self.failUnlessEqual(self.bq2, next_job)
802
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
803
804
class TestCurrentBuildBehavior(TestCaseWithFactory):
7675.421.1 by Michael Nelson
Style changes and whitespace removal after gmb's review.
805
    """This test ensures the get/set behavior of IBuilder's
806
    current_build_behavior property.
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
807
    """
808
809
    layer = LaunchpadZopelessLayer
810
811
    def setUp(self):
812
        """Create a new builder ready for testing."""
813
        super(TestCurrentBuildBehavior, self).setUp()
814
        self.builder = self.factory.makeBuilder(name='builder')
7675.421.1 by Michael Nelson
Style changes and whitespace removal after gmb's review.
815
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
816
        # Have a publisher and a ppa handy for some of the tests below.
11705.2.26 by Jonathan Lange
Factor out SoyuzTestPublisher construction so as to avoid circular imports.
817
        self.publisher = make_publisher()
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
818
        self.publisher.prepareBreezyAutotest()
819
        self.ppa_joe = self.factory.makeArchive(name="joesppa")
820
821
        self.build = self.publisher.getPubSource(
822
            sourcename="gedit", status=PackagePublishingStatus.PUBLISHED,
823
            archive=self.ppa_joe).createMissingBuilds()[0]
824
825
        self.buildfarmjob = self.build.buildqueue_record.specific_job
826
827
    def test_idle_behavior_when_no_current_build(self):
7675.421.1 by Michael Nelson
Style changes and whitespace removal after gmb's review.
828
        """We return an idle behavior when there is no behavior specified
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
829
        nor a current build.
830
        """
831
        self.assertIsInstance(
832
            self.builder.current_build_behavior, IdleBuildBehavior)
833
7675.420.28 by Michael Nelson
Relaxed the IBuilder.current_build_behavior setter to match previous policy - and allow buildd-slavescanner.txt to pass.
834
    def test_set_behavior_sets_builder(self):
835
        """Setting a builder's behavior also associates the behavior with the
836
        builder."""
837
        behavior = IBuildFarmJobBehavior(self.buildfarmjob)
838
        self.builder.current_build_behavior = behavior
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
839
7675.420.28 by Michael Nelson
Relaxed the IBuilder.current_build_behavior setter to match previous policy - and allow buildd-slavescanner.txt to pass.
840
        self.assertEqual(behavior, self.builder.current_build_behavior)
841
        self.assertEqual(behavior._builder, self.builder)
7675.420.16 by Michael Nelson
Refactored to adapt on the job rather than the job type and added tests.
842
843
    def test_current_job_behavior(self):
844
        """The current behavior is set automatically from the current job."""
845
        # Set the builder attribute on the buildqueue record so that our
846
        # builder will think it has a current build.
847
        self.build.buildqueue_record.builder = self.builder
848
849
        self.assertIsInstance(
850
            self.builder.current_build_behavior, BinaryPackageBuildBehavior)
11573.3.4 by Jonathan Lange
Start to make BuilderSlave use composition instead of inheritance.
851
852
11705.2.23 by Jonathan Lange
Mostly move builder tests.
853
class TestSlave(TestCase):
11573.3.10 by Jonathan Lange
Move tests for ensurepresent out of buildd-slave.txt and into test_builder
854
    """
855
    Integration tests for BuilderSlave that verify how it works against a
856
    real slave server.
857
    """
858
11705.2.23 by Jonathan Lange
Mostly move builder tests.
859
    run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=10)
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
860
861
    def setUp(self):
862
        super(TestSlave, self).setUp()
11705.2.23 by Jonathan Lange
Mostly move builder tests.
863
        self.slave_helper = self.useFixture(SlaveTestHelpers())
11573.3.10 by Jonathan Lange
Move tests for ensurepresent out of buildd-slave.txt and into test_builder
864
11680.1.1 by Julian Edwards
disabled a test that's failing on the prod_lp buildbot.
865
    # XXX 2010-10-06 Julian bug=655559
866
    # This is failing on buildbot but not locally; it's trying to abort
867
    # before the build has started.
868
    def disabled_test_abort(self):
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
869
        slave = self.slave_helper.getClientSlave()
11573.3.5 by Jonathan Lange
Documentation and clarity improvements to the tests.
870
        # We need to be in a BUILDING state before we can abort.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
871
        d = self.slave_helper.triggerGoodBuild(slave)
872
        d.addCallback(lambda ignored: slave.abort())
873
        d.addCallback(self.assertEqual, BuilderStatus.ABORTING)
874
        return d
11573.3.5 by Jonathan Lange
Documentation and clarity improvements to the tests.
875
11573.3.4 by Jonathan Lange
Start to make BuilderSlave use composition instead of inheritance.
876
    def test_build(self):
877
        # Calling 'build' with an expected builder type, a good build id,
878
        # valid chroot & filemaps works and returns a BuilderStatus of
879
        # BUILDING.
880
        build_id = 'some-id'
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
881
        slave = self.slave_helper.getClientSlave()
882
        d = self.slave_helper.triggerGoodBuild(slave, build_id)
883
        return d.addCallback(
884
            self.assertEqual, [BuilderStatus.BUILDING, build_id])
11573.3.4 by Jonathan Lange
Start to make BuilderSlave use composition instead of inheritance.
885
11583.1.1 by Jonathan Lange
Add clean to builder slave
886
    def test_clean(self):
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
887
        slave = self.slave_helper.getClientSlave()
11587.1.1 by Jonathan Lange
Replace the broken-but-good test with a crappy-but-working test.
888
        # XXX: JonathanLange 2010-09-21: Calling clean() on the slave requires
889
        # it to be in either the WAITING or ABORTED states, and both of these
890
        # states are very difficult to achieve in a test environment. For the
891
        # time being, we'll just assert that a clean attribute exists.
892
        self.assertNotEqual(getattr(slave, 'clean', None), None)
11583.1.1 by Jonathan Lange
Add clean to builder slave
893
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
894
    def test_echo(self):
895
        # Calling 'echo' contacts the server which returns the arguments we
896
        # gave it.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
897
        self.slave_helper.getServerSlave()
898
        slave = self.slave_helper.getClientSlave()
899
        d = slave.echo('foo', 'bar', 42)
900
        return d.addCallback(self.assertEqual, ['foo', 'bar', 42])
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
901
902
    def test_info(self):
903
        # Calling 'info' gets some information about the slave.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
904
        self.slave_helper.getServerSlave()
905
        slave = self.slave_helper.getClientSlave()
906
        d = slave.info()
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
907
        # We're testing the hard-coded values, since the version is hard-coded
908
        # into the remote slave, the supported build managers are hard-coded
909
        # into the tac file for the remote slave and config is returned from
910
        # the configuration file.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
911
        return d.addCallback(
912
            self.assertEqual,
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
913
            ['1.0',
914
             'i386',
915
             ['sourcepackagerecipe',
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
916
              'translation-templates', 'binarypackage', 'debian']])
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
917
918
    def test_initial_status(self):
919
        # Calling 'status' returns the current status of the slave. The
920
        # initial status is IDLE.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
921
        self.slave_helper.getServerSlave()
922
        slave = self.slave_helper.getClientSlave()
923
        d = slave.status()
924
        return d.addCallback(self.assertEqual, [BuilderStatus.IDLE, ''])
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
925
926
    def test_status_after_build(self):
927
        # Calling 'status' returns the current status of the slave. After a
928
        # build has been triggered, the status is BUILDING.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
929
        slave = self.slave_helper.getClientSlave()
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
930
        build_id = 'status-build-id'
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
931
        d = self.slave_helper.triggerGoodBuild(slave, build_id)
932
        d.addCallback(lambda ignored: slave.status())
933
        def check_status(status):
934
            self.assertEqual([BuilderStatus.BUILDING, build_id], status[:2])
935
            [log_file] = status[2:]
936
            self.assertIsInstance(log_file, xmlrpclib.Binary)
937
        return d.addCallback(check_status)
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
938
939
    def test_ensurepresent_not_there(self):
940
        # ensurepresent checks to see if a file is there.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
941
        self.slave_helper.getServerSlave()
942
        slave = self.slave_helper.getClientSlave()
943
        d = slave.ensurepresent('blahblah', None, None, None)
944
        d.addCallback(self.assertEqual, [False, 'No URL'])
945
        return d
11573.3.6 by Jonathan Lange
Complete tests for all of the new bits we've added.
946
947
    def test_ensurepresent_actually_there(self):
948
        # ensurepresent checks to see if a file is there.
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
949
        tachandler = self.slave_helper.getServerSlave()
950
        slave = self.slave_helper.getClientSlave()
951
        self.slave_helper.makeCacheFile(tachandler, 'blahblah')
952
        d = slave.ensurepresent('blahblah', None, None, None)
953
        d.addCallback(self.assertEqual, [True, 'No URL'])
954
        return d
955
956
    def test_sendFileToSlave_not_there(self):
957
        self.slave_helper.getServerSlave()
958
        slave = self.slave_helper.getClientSlave()
959
        d = slave.sendFileToSlave('blahblah', None, None, None)
11705.2.23 by Jonathan Lange
Mostly move builder tests.
960
        return assert_fails_with(d, CannotFetchFile)
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
961
962
    def test_sendFileToSlave_actually_there(self):
963
        tachandler = self.slave_helper.getServerSlave()
964
        slave = self.slave_helper.getClientSlave()
965
        self.slave_helper.makeCacheFile(tachandler, 'blahblah')
966
        d = slave.sendFileToSlave('blahblah', None, None, None)
967
        def check_present(ignored):
968
            d = slave.ensurepresent('blahblah', None, None, None)
969
            return d.addCallback(self.assertEqual, [True, 'No URL'])
970
        d.addCallback(check_present)
971
        return d
972
973
    def test_resumeHost_success(self):
974
        # On a successful resume resume() fires the returned deferred
975
        # callback with 'None'.
976
        self.slave_helper.getServerSlave()
977
        slave = self.slave_helper.getClientSlave()
978
979
        # The configuration testing command-line.
980
        self.assertEqual(
981
            'echo %(vm_host)s', config.builddmaster.vm_resume_command)
982
983
        # On success the response is None.
984
        def check_resume_success(response):
985
            out, err, code = response
986
            self.assertEqual(os.EX_OK, code)
987
            # XXX: JonathanLange 2010-09-23: We should instead pass the
988
            # expected vm_host into the client slave. Not doing this now,
989
            # since the SlaveHelper is being moved around.
990
            self.assertEqual("%s\n" % slave._vm_host, out)
991
        d = slave.resume()
992
        d.addBoth(check_resume_success)
993
        return d
994
995
    def test_resumeHost_failure(self):
996
        # On a failed resume, 'resumeHost' fires the returned deferred
997
        # errorback with the `ProcessTerminated` failure.
998
        self.slave_helper.getServerSlave()
999
        slave = self.slave_helper.getClientSlave()
1000
1001
        # Override the configuration command-line with one that will fail.
1002
        failed_config = """
1003
        [builddmaster]
1004
        vm_resume_command: test "%(vm_host)s = 'no-sir'"
1005
        """
1006
        config.push('failed_resume_command', failed_config)
1007
        self.addCleanup(config.pop, 'failed_resume_command')
1008
1009
        # On failures, the response is a twisted `Failure` object containing
1010
        # a tuple.
1011
        def check_resume_failure(failure):
1012
            out, err, code = failure.value
1013
            # The process will exit with a return code of "1".
1014
            self.assertEqual(code, 1)
1015
        d = slave.resume()
1016
        d.addBoth(check_resume_failure)
1017
        return d
1018
1019
    def test_resumeHost_timeout(self):
1020
        # On a resume timeouts, 'resumeHost' fires the returned deferred
1021
        # errorback with the `TimeoutError` failure.
1022
        self.slave_helper.getServerSlave()
1023
        slave = self.slave_helper.getClientSlave()
1024
1025
        # Override the configuration command-line with one that will timeout.
1026
        timeout_config = """
1027
        [builddmaster]
1028
        vm_resume_command: sleep 5
1029
        socket_timeout: 1
1030
        """
1031
        config.push('timeout_resume_command', timeout_config)
1032
        self.addCleanup(config.pop, 'timeout_resume_command')
1033
1034
        # On timeouts, the response is a twisted `Failure` object containing
1035
        # a `TimeoutError` error.
1036
        def check_resume_timeout(failure):
1037
            self.assertIsInstance(failure, Failure)
1038
            out, err, code = failure.value
1039
            self.assertEqual(code, signal.SIGKILL)
1040
        clock = Clock()
1041
        d = slave.resume(clock=clock)
1042
        # Move the clock beyond the socket_timeout but earlier than the
1043
        # sleep 5.  This stops the test having to wait for the timeout.
1044
        # Fast tests FTW!
1045
        clock.advance(2)
1046
        d.addBoth(check_resume_timeout)
1047
        return d
1048
1049
11705.2.23 by Jonathan Lange
Mostly move builder tests.
1050
class TestSlaveTimeouts(TestCase):
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
1051
    # Testing that the methods that call callRemote() all time out
1052
    # as required.
1053
11705.2.41 by Jonathan Lange
Use the new runner that handles Twisted brokenness.
1054
    run_tests_with = AsynchronousDeferredRunTestForBrokenTwisted
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
1055
1056
    def setUp(self):
1057
        super(TestSlaveTimeouts, self).setUp()
11705.2.23 by Jonathan Lange
Mostly move builder tests.
1058
        self.slave_helper = self.useFixture(SlaveTestHelpers())
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
1059
        self.clock = Clock()
1060
        self.proxy = DeadProxy("url")
1061
        self.slave = self.slave_helper.getClientSlave(
1062
            reactor=self.clock, proxy=self.proxy)
1063
1064
    def assertCancelled(self, d):
1065
        self.clock.advance(config.builddmaster.socket_timeout + 1)
11705.2.23 by Jonathan Lange
Mostly move builder tests.
1066
        return assert_fails_with(d, CancelledError)
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
1067
1068
    def test_timeout_abort(self):
1069
        return self.assertCancelled(self.slave.abort())
1070
1071
    def test_timeout_clean(self):
1072
        return self.assertCancelled(self.slave.clean())
1073
1074
    def test_timeout_echo(self):
1075
        return self.assertCancelled(self.slave.echo())
1076
1077
    def test_timeout_info(self):
1078
        return self.assertCancelled(self.slave.info())
1079
1080
    def test_timeout_status(self):
1081
        return self.assertCancelled(self.slave.status())
1082
1083
    def test_timeout_ensurepresent(self):
1084
        return self.assertCancelled(
1085
            self.slave.ensurepresent(None, None, None, None))
1086
1087
    def test_timeout_build(self):
1088
        return self.assertCancelled(
1089
            self.slave.build(None, None, None, None, None))
1090
1091
11705.2.39 by Jonathan Lange
Rewrite the test to be correct, use testtools, have less cruft.
1092
class TestSlaveConnectionTimeouts(TestCase):
11929.3.2 by Julian Edwards
some sort of failing test, although the IP address being used might fail on different systems. We need a better way of doing no-answer services.
1093
    # Testing that we can override the default 30 second connection
1094
    # timeout.
1095
11705.2.39 by Jonathan Lange
Rewrite the test to be correct, use testtools, have less cruft.
1096
    run_test = SynchronousDeferredRunTest
11929.3.2 by Julian Edwards
some sort of failing test, although the IP address being used might fail on different systems. We need a better way of doing no-answer services.
1097
1098
    def setUp(self):
1099
        super(TestSlaveConnectionTimeouts, self).setUp()
11705.2.39 by Jonathan Lange
Rewrite the test to be correct, use testtools, have less cruft.
1100
        self.slave_helper = self.useFixture(SlaveTestHelpers())
11929.3.2 by Julian Edwards
some sort of failing test, although the IP address being used might fail on different systems. We need a better way of doing no-answer services.
1101
        self.clock = Clock()
11929.3.4 by Julian Edwards
Having realised that connectTCP() never gets a chance to get called, we do not need to worry about the fake IP address.
1102
        self.proxy = ProxyWithConnectionTimeout("fake_url")
11929.3.2 by Julian Edwards
some sort of failing test, although the IP address being used might fail on different systems. We need a better way of doing no-answer services.
1103
        self.slave = self.slave_helper.getClientSlave(
1104
            reactor=self.clock, proxy=self.proxy)
1105
1106
    def test_connection_timeout(self):
11929.3.3 by Julian Edwards
fix and test tweaks
1107
        # The default timeout of 30 seconds should not cause a timeout,
1108
        # only the config value should.
11705.2.39 by Jonathan Lange
Rewrite the test to be correct, use testtools, have less cruft.
1109
        self.pushConfig('builddmaster', socket_timeout=180)
11929.3.3 by Julian Edwards
fix and test tweaks
1110
11929.3.2 by Julian Edwards
some sort of failing test, although the IP address being used might fail on different systems. We need a better way of doing no-answer services.
1111
        d = self.slave.echo()
11929.3.4 by Julian Edwards
Having realised that connectTCP() never gets a chance to get called, we do not need to worry about the fake IP address.
1112
        # Advance past the 30 second timeout.  The real reactor will
1113
        # never call connectTCP() since we're not spinning it up.  This
1114
        # avoids "connection refused" errors and simulates an
1115
        # environment where the endpoint doesn't respond.
11929.3.2 by Julian Edwards
some sort of failing test, although the IP address being used might fail on different systems. We need a better way of doing no-answer services.
1116
        self.clock.advance(31)
1117
        self.assertFalse(d.called)
11929.3.3 by Julian Edwards
fix and test tweaks
1118
11929.3.2 by Julian Edwards
some sort of failing test, although the IP address being used might fail on different systems. We need a better way of doing no-answer services.
1119
        self.clock.advance(config.builddmaster.socket_timeout + 1)
1120
        self.assertTrue(d.called)
11705.2.39 by Jonathan Lange
Rewrite the test to be correct, use testtools, have less cruft.
1121
        return assert_fails_with(d, CancelledError)
11929.3.2 by Julian Edwards
some sort of failing test, although the IP address being used might fail on different systems. We need a better way of doing no-answer services.
1122
11929.3.3 by Julian Edwards
fix and test tweaks
1123
    def test_BuilderSlave_uses_ProxyWithConnectionTimeout(self):
1124
        # Make sure that BuilderSlaves use the custom proxy class.
1125
        slave = BuilderSlave.makeBuilderSlave("url", "host")
1126
        self.assertIsInstance(slave._server, ProxyWithConnectionTimeout)
1127
11929.3.2 by Julian Edwards
some sort of failing test, although the IP address being used might fail on different systems. We need a better way of doing no-answer services.
1128
11705.2.23 by Jonathan Lange
Mostly move builder tests.
1129
class TestSlaveWithLibrarian(TestCaseWithFactory):
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
1130
    """Tests that need more of Launchpad to run."""
1131
11705.2.23 by Jonathan Lange
Mostly move builder tests.
1132
    layer = LaunchpadZopelessLayer
11705.2.41 by Jonathan Lange
Use the new runner that handles Twisted brokenness.
1133
    run_tests_with = AsynchronousDeferredRunTestForBrokenTwisted.make_factory(
1134
        timeout=20)
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
1135
1136
    def setUp(self):
11705.2.23 by Jonathan Lange
Mostly move builder tests.
1137
        super(TestSlaveWithLibrarian, self).setUp()
1138
        self.slave_helper = self.useFixture(SlaveTestHelpers())
11593.3.120 by Julian Edwards
re-add revno 11801 which was backed out in devel due to test failures resulting from a twisted bug
1139
1140
    def test_ensurepresent_librarian(self):
1141
        # ensurepresent, when given an http URL for a file will download the
1142
        # file from that URL and report that the file is present, and it was
1143
        # downloaded.
1144
1145
        # Use the Librarian because it's a "convenient" web server.
1146
        lf = self.factory.makeLibraryFileAlias(
1147
            'HelloWorld.txt', content="Hello World")
1148
        self.layer.txn.commit()
1149
        self.slave_helper.getServerSlave()
1150
        slave = self.slave_helper.getClientSlave()
1151
        d = slave.ensurepresent(
1152
            lf.content.sha1, lf.http_url, "", "")
1153
        d.addCallback(self.assertEqual, [True, 'Download'])
1154
        return d
1155
1156
    def test_retrieve_files_from_filecache(self):
1157
        # Files that are present on the slave can be downloaded with a
1158
        # filename made from the sha1 of the content underneath the
1159
        # 'filecache' directory.
1160
        content = "Hello World"
1161
        lf = self.factory.makeLibraryFileAlias(
1162
            'HelloWorld.txt', content=content)
1163
        self.layer.txn.commit()
1164
        expected_url = '%s/filecache/%s' % (
1165
            self.slave_helper.BASE_URL, lf.content.sha1)
1166
        self.slave_helper.getServerSlave()
1167
        slave = self.slave_helper.getClientSlave()
1168
        d = slave.ensurepresent(
1169
            lf.content.sha1, lf.http_url, "", "")
1170
        def check_file(ignored):
1171
            d = getPage(expected_url.encode('utf8'))
1172
            return d.addCallback(self.assertEqual, content)
1173
        return d.addCallback(check_file)
11892.6.8 by Julian Edwards
add test for the new getFiles
1174
1175
    def test_getFiles(self):
1176
        # Test BuilderSlave.getFiles().
1177
        # It also implicitly tests getFile() - I don't want to test that
1178
        # separately because it increases test run time and it's going
1179
        # away at some point anyway, in favour of getFiles().
1180
        contents = ["content1", "content2", "content3"]
1181
        self.slave_helper.getServerSlave()
1182
        slave = self.slave_helper.getClientSlave()
1183
        filemap = {}
1184
        content_map = {}
1185
1186
        def got_files(ignored):
1187
            # Called back when getFiles finishes.  Make sure all the
1188
            # content is as expected.
1189
            got_contents = []
1190
            for sha1 in filemap:
1191
                local_file = filemap[sha1]
1192
                file = open(local_file)
1193
                self.assertEqual(content_map[sha1], file.read())
1194
                file.close()
1195
1196
        def finished_uploading(ignored):
1197
            d = slave.getFiles(filemap)
1198
            return d.addCallback(got_files)
1199
1200
        # Set up some files on the builder and store details in
1201
        # content_map so we can compare downloads later.
1202
        dl = []
1203
        for content in contents:
1204
            filename = content + '.txt'
1205
            lf = self.factory.makeLibraryFileAlias(filename, content=content)
1206
            content_map[lf.content.sha1] = content
11892.6.20 by Julian Edwards
Fix test failures due to jml's TestTools changes
1207
            fd, filemap[lf.content.sha1] = tempfile.mkstemp()
11892.6.8 by Julian Edwards
add test for the new getFiles
1208
            self.addCleanup(os.remove, filemap[lf.content.sha1])
1209
            self.layer.txn.commit()
1210
            d = slave.ensurepresent(lf.content.sha1, lf.http_url, "", "")
1211
            dl.append(d)
1212
1213
        return DeferredList(dl).addCallback(finished_uploading)