Merge lp:~michael.nelson/launchpad/587113-buildbase-handleStatus into lp:launchpad

Proposed by Michael Nelson
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: 10970
Proposed branch: lp:~michael.nelson/launchpad/587113-buildbase-handleStatus
Merge into: lp:launchpad
Diff against target: 531 lines (+198/-69)
10 files modified
lib/canonical/launchpad/webapp/configure.zcml (+1/-1)
lib/canonical/launchpad/webapp/tales.py (+2/-2)
lib/lp/buildmaster/interfaces/buildbase.py (+27/-12)
lib/lp/buildmaster/model/buildbase.py (+24/-13)
lib/lp/buildmaster/model/packagebuild.py (+2/-2)
lib/lp/buildmaster/tests/test_buildbase.py (+76/-35)
lib/lp/code/model/sourcepackagerecipebuild.py (+7/-1)
lib/lp/code/model/tests/test_sourcepackagerecipebuild.py (+31/-1)
lib/lp/soyuz/tests/test_binarypackagebuild.py (+23/-0)
lib/lp/testing/factory.py (+5/-2)
To merge this branch: bzr merge lp:~michael.nelson/launchpad/587113-buildbase-handleStatus
Reviewer Review Type Date Requested Status
Graham Binns (community) code Approve
Review via email: mp+27022@code.launchpad.net

Description of the change

This branch fixes the core issue of bug 587113.

It refactors the tests so that handleStatus() is called for both BinaryPackageBuilds and SourcePackageRecipeBuilds.

It also adds other tests to ensure log files and other attributes are correctly added for both build types.

To enable the shared implementation to work for both classes (until SourcePackageRecipeBuild is also updated to use the new table structure) I had to alias 3 attributes of IBuildBase.

To test:
bin/test -vv -m test_sourcepackagerecipebuild -m test_binarypackagebuild

To post a comment you must log in.
Revision history for this message
Graham Binns (gmb) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/webapp/configure.zcml'
--- lib/canonical/launchpad/webapp/configure.zcml 2010-06-05 05:05:43 +0000
+++ lib/canonical/launchpad/webapp/configure.zcml 2010-06-08 16:04:27 +0000
@@ -421,7 +421,7 @@
421 <adapter421 <adapter
422 for="lp.buildmaster.interfaces.packagebuild.IPackageBuild"422 for="lp.buildmaster.interfaces.packagebuild.IPackageBuild"
423 provides="zope.traversing.interfaces.IPathAdapter"423 provides="zope.traversing.interfaces.IPathAdapter"
424 factory="canonical.launchpad.webapp.tales.BuildBaseFormatterAPI"424 factory="canonical.launchpad.webapp.tales.PackageBuildFormatterAPI"
425 name="fmt"425 name="fmt"
426 />426 />
427427
428428
=== modified file 'lib/canonical/launchpad/webapp/tales.py'
--- lib/canonical/launchpad/webapp/tales.py 2010-06-05 05:05:43 +0000
+++ lib/canonical/launchpad/webapp/tales.py 2010-06-08 16:04:27 +0000
@@ -1515,8 +1515,8 @@
1515 return url1515 return url
15161516
15171517
1518class BuildBaseFormatterAPI(ObjectFormatterAPI):1518class PackageBuildFormatterAPI(ObjectFormatterAPI):
1519 """Adapter providing fmt support for `IBuildBase` objects."""1519 """Adapter providing fmt support for `IPackageBuild` objects."""
1520 def _composeArchiveReference(self, archive):1520 def _composeArchiveReference(self, archive):
1521 if archive.is_ppa:1521 if archive.is_ppa:
1522 return " [%s/%s]" % (1522 return " [%s/%s]" % (
15231523
=== modified file 'lib/lp/buildmaster/interfaces/buildbase.py'
--- lib/lp/buildmaster/interfaces/buildbase.py 2010-05-19 15:39:52 +0000
+++ lib/lp/buildmaster/interfaces/buildbase.py 2010-06-08 16:04:27 +0000
@@ -116,7 +116,22 @@
116 """Common interface shared by farm jobs that build a package."""116 """Common interface shared by farm jobs that build a package."""
117 # XXX 2010-04-21 michael.nelson bug=567922. This interface117 # XXX 2010-04-21 michael.nelson bug=567922. This interface
118 # can be removed once all *Build classes inherit from118 # can be removed once all *Build classes inherit from
119 # IBuildFarmJob/IPackageBuild.119 # IBuildFarmJob/IPackageBuild. Until that time, to allow the shared
120 # implementation of handling build status, IBuildBase needs to
121 # provide aliases for buildstate, buildlog and datebuilt as follows:
122 # status => buildstate
123 # log => buildlog
124 # date_finished => datebuilt
125 status = Choice(
126 title=_('State'), required=True, vocabulary=BuildStatus,
127 description=_("The current build state."))
128 log = Object(
129 schema=ILibraryFileAlias, required=False,
130 title=_("The LibraryFileAlias containing the entire buildlog."))
131 date_finished = Datetime(
132 title=_('Date built'), required=False,
133 description=_("The time when the build result got collected."))
134
120135
121 build_farm_job_type = Choice(136 build_farm_job_type = Choice(
122 title=_("Job type"), required=True, readonly=True,137 title=_("Job type"), required=True, readonly=True,
@@ -130,10 +145,7 @@
130 title=_('Date created'), required=True, readonly=True,145 title=_('Date created'), required=True, readonly=True,
131 description=_("The time when the build request was created.")))146 description=_("The time when the build request was created.")))
132147
133 buildstate = exported(148 buildstate = exported(status)
134 Choice(
135 title=_('State'), required=True, vocabulary=BuildStatus,
136 description=_("The current build state.")))
137149
138 date_first_dispatched = exported(150 date_first_dispatched = exported(
139 Datetime(151 Datetime(
@@ -146,19 +158,14 @@
146 title=_("Builder"), schema=IBuilder, required=False,158 title=_("Builder"), schema=IBuilder, required=False,
147 description=_("The Builder which address this build request."))159 description=_("The Builder which address this build request."))
148160
149 datebuilt = exported(161 datebuilt = exported(date_finished)
150 Datetime(
151 title=_('Date built'), required=False,
152 description=_("The time when the build result got collected.")))
153162
154 buildduration = Timedelta(163 buildduration = Timedelta(
155 title=_("Build Duration"), required=False,164 title=_("Build Duration"), required=False,
156 description=_("Build duration interval, calculated when the "165 description=_("Build duration interval, calculated when the "
157 "build result gets collected."))166 "build result gets collected."))
158167
159 buildlog = Object(168 buildlog = log
160 schema=ILibraryFileAlias, required=False,
161 title=_("The LibraryFileAlias containing the entire buildlog."))
162169
163 build_log_url = exported(170 build_log_url = exported(
164 TextLine(171 TextLine(
@@ -225,6 +232,14 @@
225 executable.232 executable.
226 """233 """
227234
235 def getUploadLogContent(root, leaf):
236 """Retrieve the upload log contents.
237
238 :param root: Root directory for the uploads
239 :param leaf: Leaf for this particular upload
240 :return: Contents of log file or message saying no log file was found.
241 """
242
228 def handleStatus(build, status, librarian, slave_status):243 def handleStatus(build, status, librarian, slave_status):
229 """Handle a finished build status from a slave.244 """Handle a finished build status from a slave.
230245
231246
=== modified file 'lib/lp/buildmaster/model/buildbase.py'
--- lib/lp/buildmaster/model/buildbase.py 2010-05-21 09:42:21 +0000
+++ lib/lp/buildmaster/model/buildbase.py 2010-06-08 16:04:27 +0000
@@ -9,7 +9,10 @@
99
10__metaclass__ = type10__metaclass__ = type
1111
12__all__ = ['BuildBase']12__all__ = [
13 'handle_status_for_build',
14 'BuildBase',
15 ]
1316
14import datetime17import datetime
15import logging18import logging
@@ -37,6 +40,24 @@
37UPLOAD_LOG_FILENAME = 'uploader.log'40UPLOAD_LOG_FILENAME = 'uploader.log'
3841
3942
43def handle_status_for_build(build, status, librarian, slave_status):
44 """Find and call the correct method for handling the build status.
45
46 This is extracted from build base so that the implementation
47 can be shared by the newer IPackageBuild class.
48 """
49 logger = logging.getLogger(BUILDD_MANAGER_LOG_NAME)
50
51 method = getattr(BuildBase, '_handleStatus_' + status, None)
52
53 if method is None:
54 logger.critical("Unknown BuildStatus '%s' for builder '%s'"
55 % (status, build.buildqueue_record.builder.url))
56 return
57
58 method(build, librarian, slave_status, logger)
59
60
40class BuildBase:61class BuildBase:
41 """A mixin class providing functionality for farm jobs that build a62 """A mixin class providing functionality for farm jobs that build a
42 package.63 package.
@@ -127,19 +148,9 @@
127 return None148 return None
128 return self._getProxiedFileURL(self.upload_log)149 return self._getProxiedFileURL(self.upload_log)
129150
130 @staticmethod151 def handleStatus(self, status, librarian, slave_status):
131 def handleStatus(build, status, librarian, slave_status):
132 """See `IBuildBase`."""152 """See `IBuildBase`."""
133 logger = logging.getLogger(BUILDD_MANAGER_LOG_NAME)153 return handle_status_for_build(self, status, librarian, slave_status)
134
135 method = getattr(build, '_handleStatus_' + status, None)
136
137 if method is None:
138 logger.critical("Unknown BuildStatus '%s' for builder '%s'"
139 % (status, build.buildqueue_record.builder.url))
140 return
141
142 method(librarian, slave_status, logger)
143154
144 @staticmethod155 @staticmethod
145 def _handleStatus_OK(build, librarian, slave_status, logger):156 def _handleStatus_OK(build, librarian, slave_status, logger):
146157
=== modified file 'lib/lp/buildmaster/model/packagebuild.py'
--- lib/lp/buildmaster/model/packagebuild.py 2010-05-21 09:42:21 +0000
+++ lib/lp/buildmaster/model/packagebuild.py 2010-06-08 16:04:27 +0000
@@ -24,7 +24,7 @@
24from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobSource24from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobSource
25from lp.buildmaster.interfaces.packagebuild import (25from lp.buildmaster.interfaces.packagebuild import (
26 IPackageBuild, IPackageBuildSource)26 IPackageBuild, IPackageBuildSource)
27from lp.buildmaster.model.buildbase import BuildBase27from lp.buildmaster.model.buildbase import handle_status_for_build, BuildBase
28from lp.buildmaster.model.buildfarmjob import BuildFarmJobDerived28from lp.buildmaster.model.buildfarmjob import BuildFarmJobDerived
29from lp.registry.interfaces.pocket import PackagePublishingPocket29from lp.registry.interfaces.pocket import PackagePublishingPocket
30from lp.soyuz.adapters.archivedependencies import (30from lp.soyuz.adapters.archivedependencies import (
@@ -185,7 +185,7 @@
185185
186 def handleStatus(self, status, librarian, slave_status):186 def handleStatus(self, status, librarian, slave_status):
187 """See `IPackageBuild`."""187 """See `IPackageBuild`."""
188 return BuildBase.handleStatus(self, status, librarian, slave_status)188 return handle_status_for_build(self, status, librarian, slave_status)
189189
190 # The following private handlers currently re-use the BuildBase190 # The following private handlers currently re-use the BuildBase
191 # implementation until it is no longer in use. If we find in the191 # implementation until it is no longer in use. If we find in the
192192
=== modified file 'lib/lp/buildmaster/tests/test_buildbase.py'
--- lib/lp/buildmaster/tests/test_buildbase.py 2010-05-21 09:42:21 +0000
+++ lib/lp/buildmaster/tests/test_buildbase.py 2010-06-08 16:04:27 +0000
@@ -15,17 +15,16 @@
15from datetime import datetime15from datetime import datetime
16import os16import os
17import unittest17import unittest
18from zope.security.proxy import removeSecurityProxy
1819
19from canonical.config import config20from canonical.config import config
20from canonical.database.constants import UTC_NOW21from canonical.database.constants import UTC_NOW
21from canonical.testing.layers import (22from canonical.testing.layers import LaunchpadZopelessLayer
22 DatabaseFunctionalLayer, LaunchpadZopelessLayer)
23from lp.buildmaster.interfaces.buildbase import BuildStatus23from lp.buildmaster.interfaces.buildbase import BuildStatus
24from lp.buildmaster.model.buildbase import BuildBase24from lp.buildmaster.model.buildbase import BuildBase
25from lp.registry.interfaces.pocket import pocketsuffix25from lp.registry.interfaces.pocket import pocketsuffix
26from lp.soyuz.tests.soyuzbuilddhelpers import WaitingSlave26from lp.soyuz.tests.soyuzbuilddhelpers import WaitingSlave
27from lp.soyuz.tests.test_publishing import SoyuzTestPublisher27from lp.testing import TestCase
28from lp.testing import TestCase, TestCaseWithFactory
29from lp.testing.fakemethod import FakeMethod28from lp.testing.fakemethod import FakeMethod
3029
3130
@@ -62,27 +61,41 @@
62 self.package_build = BuildBase()61 self.package_build = BuildBase()
6362
6463
65class TestBuildBaseWithDatabase(TestCaseWithFactory):64class TestGetUploadMethodsMixin:
66 """Tests for `IBuildBase` that need objects from the rest of Launchpad."""65 """Tests for `IBuildBase` that need objects from the rest of Launchpad."""
6766
68 layer = DatabaseFunctionalLayer67 layer = LaunchpadZopelessLayer
68
69 def makeBuild(self):
70 """Allow classes to override the build with which the test runs.
71
72 XXX michaeln 2010-06-03 bug=567922
73 Until buildbase is removed, we need to ensure these tests
74 run against new IPackageBuild builds (BinaryPackageBuild)
75 and the IBuildBase builds (SPRecipeBuild). They assume the build
76 is successfully built and check that incorrect upload paths will
77 set the status to FAILEDTOUPLOAD.
78 """
79 raise NotImplemented
80
81 def setUp(self):
82 super(TestGetUploadMethodsMixin, self).setUp()
83 self.build = self.makeBuild()
6984
70 def test_getUploadLogContent_nolog(self):85 def test_getUploadLogContent_nolog(self):
71 """If there is no log file there, a string explanation is returned.86 """If there is no log file there, a string explanation is returned.
72 """87 """
73 self.useTempDir()88 self.useTempDir()
74 build_base = BuildBase()
75 self.assertEquals('Could not find upload log file',89 self.assertEquals('Could not find upload log file',
76 build_base.getUploadLogContent(os.getcwd(), "myleaf"))90 self.build.getUploadLogContent(os.getcwd(), "myleaf"))
7791
78 def test_getUploadLogContent_only_dir(self):92 def test_getUploadLogContent_only_dir(self):
79 """If there is a directory but no log file, expect the error string,93 """If there is a directory but no log file, expect the error string,
80 not an exception."""94 not an exception."""
81 self.useTempDir()95 self.useTempDir()
82 os.makedirs("accepted/myleaf")96 os.makedirs("accepted/myleaf")
83 build_base = BuildBase()
84 self.assertEquals('Could not find upload log file',97 self.assertEquals('Could not find upload log file',
85 build_base.getUploadLogContent(os.getcwd(), "myleaf"))98 self.build.getUploadLogContent(os.getcwd(), "myleaf"))
8699
87 def test_getUploadLogContent_readsfile(self):100 def test_getUploadLogContent_readsfile(self):
88 """If there is a log file, return its contents."""101 """If there is a log file, return its contents."""
@@ -90,47 +103,53 @@
90 os.makedirs("accepted/myleaf")103 os.makedirs("accepted/myleaf")
91 with open('accepted/myleaf/uploader.log', 'w') as f:104 with open('accepted/myleaf/uploader.log', 'w') as f:
92 f.write('foo')105 f.write('foo')
93 build_base = BuildBase()
94 self.assertEquals('foo',106 self.assertEquals('foo',
95 build_base.getUploadLogContent(os.getcwd(), "myleaf"))107 self.build.getUploadLogContent(os.getcwd(), "myleaf"))
96108
97 def test_getUploaderCommand(self):109 def test_getUploaderCommand(self):
98 build_base = BuildBase()
99 upload_leaf = self.factory.getUniqueString('upload-leaf')110 upload_leaf = self.factory.getUniqueString('upload-leaf')
100 build_base.distro_series = self.factory.makeDistroSeries()
101 build_base.distribution = build_base.distro_series.distribution
102 build_base.pocket = self.factory.getAnyPocket()
103 build_base.id = self.factory.getUniqueInteger()
104 build_base.policy_name = self.factory.getUniqueString('policy-name')
105 config_args = list(config.builddmaster.uploader.split())111 config_args = list(config.builddmaster.uploader.split())
106 log_file = self.factory.getUniqueString('logfile')112 log_file = self.factory.getUniqueString('logfile')
107 config_args.extend(113 config_args.extend(
108 ['--log-file', log_file,114 ['--log-file', log_file,
109 '-d', build_base.distribution.name,115 '-d', self.build.distribution.name,
110 '-s', (build_base.distro_series.name116 '-s', (self.build.distro_series.name
111 + pocketsuffix[build_base.pocket]),117 + pocketsuffix[self.build.pocket]),
112 '-b', str(build_base.id),118 '-b', str(self.build.id),
113 '-J', upload_leaf,119 '-J', upload_leaf,
114 '--context=%s' % build_base.policy_name,120 '--context=%s' % self.build.policy_name,
115 os.path.abspath(config.builddmaster.root),121 os.path.abspath(config.builddmaster.root),
116 ])122 ])
117 uploader_command = build_base.getUploaderCommand(123 uploader_command = self.build.getUploaderCommand(
118 build_base, upload_leaf, log_file)124 self.build, upload_leaf, log_file)
119 self.assertEqual(config_args, uploader_command)125 self.assertEqual(config_args, uploader_command)
120126
121127
122class TestBuildBaseHandleStatus(TestCaseWithFactory):128class TestHandleStatusMixin:
123 """Tests for `IBuildBase`s handleStatus method."""129 """Tests for `IBuildBase`s handleStatus method.
130
131 Note: these tests do *not* test the updating of the build
132 status to FULLYBUILT as this happens during the upload which
133 is stubbed out by a mock function.
134 """
124135
125 layer = LaunchpadZopelessLayer136 layer = LaunchpadZopelessLayer
126137
138 def makeBuild(self):
139 """Allow classes to override the build with which the test runs.
140
141 XXX michaeln 2010-06-03 bug=567922
142 Until buildbase is removed, we need to ensure these tests
143 run against new IPackageBuild builds (BinaryPackageBuild)
144 and the IBuildBase builds (SPRecipeBuild). They assume the build
145 is successfully built and check that incorrect upload paths will
146 set the status to FAILEDTOUPLOAD.
147 """
148 raise NotImplementedError
149
127 def setUp(self):150 def setUp(self):
128 super(TestBuildBaseHandleStatus, self).setUp()151 super(TestHandleStatusMixin, self).setUp()
129 test_publisher = SoyuzTestPublisher()152 self.build = self.makeBuild()
130 test_publisher.prepareBreezyAutotest()
131 binaries = test_publisher.getPubBinaries()
132 self.build = binaries[0].binarypackagerelease.build
133
134 # For the moment, we require a builder for the build so that153 # For the moment, we require a builder for the build so that
135 # handleStatus_OK can get a reference to the slave.154 # handleStatus_OK can get a reference to the slave.
136 builder = self.factory.makeBuilder()155 builder = self.factory.makeBuilder()
@@ -149,10 +168,14 @@
149 config.push('tmp_builddmaster_root', tmp_builddmaster_root)168 config.push('tmp_builddmaster_root', tmp_builddmaster_root)
150169
151 # We stub out our builds getUploaderCommand() method so170 # We stub out our builds getUploaderCommand() method so
152 # we can check whether it was called.171 # we can check whether it was called as well as
172 # verifySuccessfulUpload().
153 self.fake_getUploaderCommand = FakeMethod(173 self.fake_getUploaderCommand = FakeMethod(
154 result=['echo', 'noop'])174 result=['echo', 'noop'])
155 self.build.getUploaderCommand = self.fake_getUploaderCommand175 removeSecurityProxy(self.build).getUploaderCommand = (
176 self.fake_getUploaderCommand)
177 removeSecurityProxy(self.build).verifySuccessfulUpload = FakeMethod(
178 result=True)
156179
157 def test_handleStatus_OK_normal_file(self):180 def test_handleStatus_OK_normal_file(self):
158 # A filemap with plain filenames should not cause a problem.181 # A filemap with plain filenames should not cause a problem.
@@ -183,6 +206,24 @@
183 self.assertEqual(BuildStatus.FAILEDTOUPLOAD, self.build.status)206 self.assertEqual(BuildStatus.FAILEDTOUPLOAD, self.build.status)
184 self.assertEqual(0, self.fake_getUploaderCommand.call_count)207 self.assertEqual(0, self.fake_getUploaderCommand.call_count)
185208
209 def test_handleStatus_OK_sets_build_log(self):
210 # The build log is set during handleStatus.
211 removeSecurityProxy(self.build).log = None
212 self.assertEqual(None, self.build.log)
213 self.build.handleStatus('OK', None, {
214 'filemap': { 'myfile.py': 'test_file_hash'},
215 })
216 self.assertNotEqual(None, self.build.log)
217
218 def test_date_finished_set(self):
219 # The date finished is updated during handleStatus_OK.
220 removeSecurityProxy(self.build).date_finished = None
221 self.assertEqual(None, self.build.date_finished)
222 self.build.handleStatus('OK', None, {
223 'filemap': { 'myfile.py': 'test_file_hash'},
224 })
225 self.assertNotEqual(None, self.build.date_finished)
226
186227
187def test_suite():228def test_suite():
188 return unittest.TestLoader().loadTestsFromName(__name__)229 return unittest.TestLoader().loadTestsFromName(__name__)
189230
=== modified file 'lib/lp/code/model/sourcepackagerecipebuild.py'
--- lib/lp/code/model/sourcepackagerecipebuild.py 2010-05-27 22:18:16 +0000
+++ lib/lp/code/model/sourcepackagerecipebuild.py 2010-06-08 16:04:27 +0000
@@ -75,7 +75,6 @@
75 buildlog = Reference(buildlog_id, 'LibraryFileAlias.id')75 buildlog = Reference(buildlog_id, 'LibraryFileAlias.id')
7676
77 buildstate = DBEnum(enum=BuildStatus, name='build_state')77 buildstate = DBEnum(enum=BuildStatus, name='build_state')
78
79 dependencies = Unicode(allow_none=True)78 dependencies = Unicode(allow_none=True)
8079
81 upload_log_id = Int(name='upload_log', allow_none=True)80 upload_log_id = Int(name='upload_log', allow_none=True)
@@ -88,6 +87,13 @@
88 datecreated = UtcDateTimeCol(notNull=True, dbName='date_created')87 datecreated = UtcDateTimeCol(notNull=True, dbName='date_created')
89 datebuilt = UtcDateTimeCol(notNull=False, dbName='date_built')88 datebuilt = UtcDateTimeCol(notNull=False, dbName='date_built')
9089
90 # See `IBuildBase` - the following attributes are aliased
91 # to allow a shared implementation of the handleStatus methods
92 # until IBuildBase is removed.
93 status = buildstate
94 date_finished = datebuilt
95 log = buildlog
96
91 @property97 @property
92 def datestarted(self):98 def datestarted(self):
93 """See `IBuild`."""99 """See `IBuild`."""
94100
=== modified file 'lib/lp/code/model/tests/test_sourcepackagerecipebuild.py'
--- lib/lp/code/model/tests/test_sourcepackagerecipebuild.py 2010-05-27 22:18:16 +0000
+++ lib/lp/code/model/tests/test_sourcepackagerecipebuild.py 2010-06-08 16:04:27 +0000
@@ -20,11 +20,14 @@
2020
21from canonical.launchpad.interfaces.launchpad import NotFoundError21from canonical.launchpad.interfaces.launchpad import NotFoundError
22from canonical.launchpad.webapp.authorization import check_permission22from canonical.launchpad.webapp.authorization import check_permission
23from lp.buildmaster.interfaces.buildbase import IBuildBase23from lp.buildmaster.interfaces.buildbase import BuildStatus, IBuildBase
24from lp.buildmaster.interfaces.buildqueue import IBuildQueue24from lp.buildmaster.interfaces.buildqueue import IBuildQueue
25from lp.buildmaster.tests.test_buildbase import (
26 TestGetUploadMethodsMixin, TestHandleStatusMixin)
25from lp.code.interfaces.sourcepackagerecipebuild import (27from lp.code.interfaces.sourcepackagerecipebuild import (
26 ISourcePackageRecipeBuildJob, ISourcePackageRecipeBuild,28 ISourcePackageRecipeBuildJob, ISourcePackageRecipeBuild,
27 ISourcePackageRecipeBuildSource)29 ISourcePackageRecipeBuildSource)
30from lp.soyuz.interfaces.processor import IProcessorFamilySet
28from lp.soyuz.model.processor import ProcessorFamily31from lp.soyuz.model.processor import ProcessorFamily
29from lp.testing import ANONYMOUS, login, person_logged_in, TestCaseWithFactory32from lp.testing import ANONYMOUS, login, person_logged_in, TestCaseWithFactory
3033
@@ -193,6 +196,33 @@
193 self.assertEqual([binary], list(spb.binary_builds))196 self.assertEqual([binary], list(spb.binary_builds))
194197
195198
199class MakeSPRecipeBuildMixin:
200 """Provide the common makeBuild method returning a queued build."""
201
202 def makeBuild(self):
203 person = self.factory.makePerson()
204 distroseries = self.factory.makeDistroSeries()
205 processor_fam = getUtility(IProcessorFamilySet).getByName('x86')
206 distroseries_i386 = distroseries.newArch(
207 'i386', processor_fam, False, person,
208 supports_virtualized=True)
209 distroseries.nominatedarchindep = distroseries_i386
210 build = self.factory.makeSourcePackageRecipeBuild(
211 distroseries=distroseries,
212 status=BuildStatus.FULLYBUILT)
213 build.queueBuild(build)
214 return build
215
216
217class TestGetUploadMethodsForSPRecipeBuild(
218 MakeSPRecipeBuildMixin, TestGetUploadMethodsMixin, TestCaseWithFactory):
219 """IBuildBase.getUpload-related methods work with SPRecipe builds."""
220
221
222class TestHandleStatusForSPRBuild(
223 MakeSPRecipeBuildMixin, TestHandleStatusMixin, TestCaseWithFactory):
224 """IBuildBase.handleStatus works with SPRecipe builds."""
225
196226
197def test_suite():227def test_suite():
198 return unittest.TestLoader().loadTestsFromName(__name__)228 return unittest.TestLoader().loadTestsFromName(__name__)
199229
=== modified file 'lib/lp/soyuz/tests/test_binarypackagebuild.py'
--- lib/lp/soyuz/tests/test_binarypackagebuild.py 2010-06-07 20:21:02 +0000
+++ lib/lp/soyuz/tests/test_binarypackagebuild.py 2010-06-08 16:04:27 +0000
@@ -17,6 +17,8 @@
17from lp.buildmaster.interfaces.buildqueue import IBuildQueue17from lp.buildmaster.interfaces.buildqueue import IBuildQueue
18from lp.buildmaster.interfaces.packagebuild import IPackageBuild18from lp.buildmaster.interfaces.packagebuild import IPackageBuild
19from lp.buildmaster.model.buildqueue import BuildQueue19from lp.buildmaster.model.buildqueue import BuildQueue
20from lp.buildmaster.tests.test_buildbase import (
21 TestGetUploadMethodsMixin, TestHandleStatusMixin)
20from lp.soyuz.interfaces.binarypackagebuild import (22from lp.soyuz.interfaces.binarypackagebuild import (
21 IBinaryPackageBuild, IBinaryPackageBuildSet)23 IBinaryPackageBuild, IBinaryPackageBuildSet)
22from lp.soyuz.interfaces.buildpackagejob import IBuildPackageJob24from lp.soyuz.interfaces.buildpackagejob import IBuildPackageJob
@@ -345,5 +347,26 @@
345 self.assertIsNot(None, self.build.date_finished)347 self.assertIsNot(None, self.build.date_finished)
346348
347349
350class MakeBinaryPackageBuildMixin:
351 """Provide the makeBuild method returning a queud build."""
352
353 def makeBuild(self):
354 test_publisher = SoyuzTestPublisher()
355 test_publisher.prepareBreezyAutotest()
356 binaries = test_publisher.getPubBinaries()
357 return binaries[0].binarypackagerelease.build
358
359
360class TestGetUploadMethodsForBinaryPackageBuild(
361 MakeBinaryPackageBuildMixin, TestGetUploadMethodsMixin,
362 TestCaseWithFactory):
363 """IBuildBase.getUpload-related methods work with binary builds."""
364
365
366class TestHandleStatusForBinaryPackageBuild(
367 MakeBinaryPackageBuildMixin, TestHandleStatusMixin, TestCaseWithFactory):
368 """IBuildBase.handleStatus works with binary builds."""
369
370
348def test_suite():371def test_suite():
349 return unittest.TestLoader().loadTestsFromName(__name__)372 return unittest.TestLoader().loadTestsFromName(__name__)
350373
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2010-05-30 04:06:48 +0000
+++ lib/lp/testing/factory.py 2010-06-08 16:04:27 +0000
@@ -1789,7 +1789,8 @@
1789 def makeSourcePackageRecipeBuild(self, sourcepackage=None, recipe=None,1789 def makeSourcePackageRecipeBuild(self, sourcepackage=None, recipe=None,
1790 requester=None, archive=None,1790 requester=None, archive=None,
1791 sourcename=None, distroseries=None,1791 sourcename=None, distroseries=None,
1792 pocket=None):1792 pocket=None,
1793 status=BuildStatus.NEEDSBUILD):
1793 """Make a new SourcePackageRecipeBuild."""1794 """Make a new SourcePackageRecipeBuild."""
1794 if recipe is None:1795 if recipe is None:
1795 recipe = self.makeSourcePackageRecipe(name=sourcename)1796 recipe = self.makeSourcePackageRecipe(name=sourcename)
@@ -1800,12 +1801,14 @@
1800 distribution=archive.distribution)1801 distribution=archive.distribution)
1801 if requester is None:1802 if requester is None:
1802 requester = self.makePerson()1803 requester = self.makePerson()
1803 return getUtility(ISourcePackageRecipeBuildSource).new(1804 spr_build = getUtility(ISourcePackageRecipeBuildSource).new(
1804 distroseries=distroseries,1805 distroseries=distroseries,
1805 recipe=recipe,1806 recipe=recipe,
1806 archive=archive,1807 archive=archive,
1807 requester=requester,1808 requester=requester,
1808 pocket=pocket)1809 pocket=pocket)
1810 removeSecurityProxy(spr_build).buildstate = status
1811 return spr_build
18091812
1810 def makeSourcePackageRecipeBuildJob(1813 def makeSourcePackageRecipeBuildJob(
1811 self, score=9876, virtualized=True, estimated_duration=64,1814 self, score=9876, virtualized=True, estimated_duration=64,