Merge lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-3 into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: 12253
Proposed branch: lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-3
Merge into: lp:launchpad
Prerequisite: lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-2
Diff against target: 736 lines (+187/-455)
3 files modified
lib/lp/soyuz/doc/binarypackagebuild.txt (+0/-443)
lib/lp/soyuz/tests/test_binarypackagebuild.py (+3/-3)
lib/lp/soyuz/tests/test_hasbuildrecords.py (+184/-9)
To merge this branch: bzr merge lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-3
Reviewer Review Type Date Requested Status
Graham Binns (community) code Approve
Review via email: mp+46209@code.launchpad.net

Description of the change

This branch moves more of binarypackagebuild.txt into unit tests.

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

StevenK: r=me; There are a few instances of "# Test that ..." that need to be turned into a statement of expected behaviour, but I know you'll take care of those.

review: Approve (code)
Revision history for this message
Graham Binns (gmb) wrote :

Oops. Missed part of the diff.

review: Abstain (code)
Revision history for this message
Graham Binns (gmb) wrote :

This method is crying out for some comments explaining what it's actually doing and why. I mean, I get that it's setting things up for later tests, but it took me a couple of goes to understand what each bit does. If you can add comments to explain it a bit better, that'd be great.

538 + def setUp(self):
539 + super(TestDistributionHasBuildRecords, self).setUp()
540 + self.admin = getUtility(IPersonSet).getByEmail(ADMIN_EMAIL)
541 + self.pf_one = self.factory.makeProcessorFamily()
542 + pf_proc_1 = self.pf_one.addProcessor(
543 + self.factory.getUniqueString(), '', '')
544 + self.pf_two = self.factory.makeProcessorFamily()
545 + pf_proc_2 = self.pf_two.addProcessor(
546 + self.factory.getUniqueString(), '', '')
547 + self.distroseries = self.factory.makeDistroSeries()
548 + self.distribution = self.distroseries.distribution
549 + self.das_one = self.factory.makeDistroArchSeries(
550 + distroseries=self.distroseries, processorfamily=self.pf_one,
551 + supports_virtualized=True)
552 + self.das_two = self.factory.makeDistroArchSeries(
553 + distroseries=self.distroseries, processorfamily=self.pf_two,
554 + supports_virtualized=True)
555 + self.archive = self.factory.makeArchive(
556 + distribution=self.distroseries.distribution,
557 + purpose=ArchivePurpose.PRIMARY)
558 + self.arch_ids = [arch.id for arch in self.distroseries.architectures]
559 + with person_logged_in(self.admin):
560 + self.publisher = SoyuzTestPublisher()
561 + self.publisher.prepareBreezyAutotest()
562 + self.distroseries.nominatedarchindep = self.das_one
563 + self.publisher.addFakeChroots(distroseries=self.distroseries)
564 + self.builder_one = self.factory.makeBuilder(processor=pf_proc_1)
565 + self.builder_two = self.factory.makeBuilder(processor=pf_proc_2)
566 + self.builds = []
567 + self.createBuilds()

Also, bigjool's concerns on IRC need to be dealt with.

review: Needs Fixing (code)
Revision history for this message
Graham Binns (gmb) wrote :

Happy joy happy happy joy.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/soyuz/doc/binarypackagebuild.txt'
--- lib/lp/soyuz/doc/binarypackagebuild.txt 2011-01-20 21:02:32 +0000
+++ lib/lp/soyuz/doc/binarypackagebuild.txt 2011-01-20 21:02:59 +0000
@@ -1,446 +1,3 @@
1== The BuildSet Class ==
2
3The BuildSet class gives us some useful ways to consider the
4collection of builds.
5
6 >>> bs = getUtility(IBinaryPackageBuildSet)
7
8We can find builds given a source package release and architecture tag.
9
10 >>> i386_builds = bs.getBuildBySRAndArchtag(20, 'i386')
11 >>> i386_builds.count()
12 4
13
14IHasBuildRecords uses a base method provided by IBinaryPackageBuildSet,
15getBuildsByArchIds():
16
17It receives list of architectures IDs:
18
19 >>> hoary = ubuntu.getSeries('hoary')
20 >>> arch_ids = [arch.id for arch in hoary.architectures]
21 >>> bs.getBuildsByArchIds(ubuntu, arch_ids).count()
22 5
23
24It still working for empty list or None:
25
26 >>> bs.getBuildsByArchIds(ubuntu, []).count()
27 0
28
29 >>> bs.getBuildsByArchIds(ubuntu, None).count()
30 0
31
32Using build status, only the successfully built ones:
33
34 >>> bs.getBuildsByArchIds(ubuntu, arch_ids,
35 ... status=BuildStatus.FULLYBUILT).count()
36 2
37
38Check the result content:
39
40 >>> [b.title for b in bs.getBuildsByArchIds(ubuntu, arch_ids,
41 ... status=BuildStatus.FULLYBUILT)]
42 [u'i386 build of pmount 0.1-1 in ubuntu hoary RELEASE', u'hppa build
43 of pmount 0.1-1 in ubuntu hoary RELEASE']
44
45Using optional 'name' filter (matching with SQL LIKE %||filter||%)
46
47 >>> bs.getBuildsByArchIds(ubuntu, arch_ids,
48 ... status=BuildStatus.FULLYBUILT,
49 ... name='pmo').count()
50 2
51
52Checking optional 'pocket' restriction:
53
54 >>> from lp.registry.interfaces.pocket import PackagePublishingPocket
55 >>> bs.getBuildsByArchIds(ubuntu, arch_ids,
56 ... pocket=PackagePublishingPocket.UPDATES).count()
57 0
58
59 >>> bs.getBuildsByArchIds(ubuntu, arch_ids,
60 ... pocket=PackagePublishingPocket.RELEASE).count()
61 5
62
63getBuildsByArchIds will also return builds for archives other than the
64primary archive.
65
66 >>> breezy = ubuntu.getSeries('breezy-autotest')
67 >>> arch_ids = [arch.id for arch in breezy.architectures]
68 >>> [(build.archive.purpose.name, build.title) for build in
69 ... bs.getBuildsByArchIds(ubuntu, arch_ids, name='commercialpackage')]
70 [('PARTNER', u'i386 build of commercialpackage 1.0-1 in ubuntu breezy-autotest RELEASE')]
71
72`IBinaryPackageBuildSet` also provides getStatusSummaryForBuilds which
73summarizes the build status of a set of builds:
74
75First we'll define a helper to print the build summary:
76
77 >>> def print_build_summary(summary):
78 ... print "%s\n%s\nRelevant builds:\n%s" % (
79 ... summary['status'].title,
80 ... summary['status'].description,
81 ... "\n".join(
82 ... " - %s" % build.title for build in summary['builds'])
83 ... )
84
85 >>> build_summary = bs.getStatusSummaryForBuilds(i386_builds)
86 >>> print_build_summary(build_summary)
87 NEEDSBUILD
88 There are some builds waiting to be built.
89 Relevant builds:
90 - i386 build of pmount 0.1-1 in ubuntu warty RELEASE
91
92The build set class furthermore provides a mechanism to load build-related
93data from the database for a given set of builds:
94
95 >>> from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
96 >>> from storm.expr import In
97 >>> from canonical.launchpad.webapp.interfaces import (
98 ... IStoreSelector, MAIN_STORE, DEFAULT_FLAVOR)
99 >>> store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
100 >>> results = list(store.find(
101 ... BinaryPackageBuild, In(BinaryPackageBuild.id, (2,6,7,8))))
102 >>> rset = removeSecurityProxy(bs)._prefetchBuildData(results)
103 >>> def filename_or_none(item):
104 ... if item is not None:
105 ... return '%s' % item.filename
106 ... else:
107 ... return 'n/a'
108 >>> def id_or_none(item):
109 ... if item is not None:
110 ... return '%d' % item.id
111 ... else:
112 ... return 'n/a'
113 >>> def sort_result_key(row):
114 ... return row[0].id
115 >>> for row in sorted(rset, key=sort_result_key):
116 ... (sourcepackagerelease, buildlog,
117 ... sourcepackagename, buildlog_content, builder,
118 ... package_build, build_farm_job) = row
119 ... print(
120 ... 'builder: %s, spr: %s, log: %s' %
121 ... (id_or_none(builder),
122 ... sourcepackagerelease.title, filename_or_none(buildlog)))
123 builder: 1, spr: mozilla-firefox - 0.9, log: netapplet-1.0.0.tar.gz
124 builder: n/a, spr: mozilla-firefox - 0.9, log: n/a
125 builder: 1, spr: pmount - 0.1-1, log: netapplet-1.0.0.tar.gz
126 builder: 1, spr: foobar - 1.0, log: netapplet-1.0.0.tar.gz
127
128
129== IHadBuildRecords.getBuildRecords() Implementations ==
130
131XXX: Michael Nelson 20090701 bug=394276
132The documentation for IHasBuildRecords is now in
133lp/soyuz/doc/hasbuildrecords.txt. The following implementation tests should
134be converted to unit-tests in lib/soyuz/tests/test_hasbuildrecords.py.
135
136We can find recent and pending builds for a given distrarchoseries.
137
138 >>> hoaryi386 = hoary['i386']
139 >>> hoaryi386.title
140 u'The Hoary Hedgehog Release for i386 (x86)'
141
142Exercises IHasBuildRecords abilities for distroarchseriess
143
144 >>> hoaryi386.getBuildRecords().count()
145 4
146
147 >>> hoaryi386.getBuildRecords(build_state=BuildStatus.FULLYBUILT).count()
148 1
149
150 >>> hoaryi386.getBuildRecords(name='pm').count()
151 1
152
153 >>> hoaryi386.getBuildRecords(
154 ... pocket=PackagePublishingPocket.RELEASE).count()
155 4
156
157 >>> hoaryi386.getBuildRecords(
158 ... pocket=PackagePublishingPocket.UPDATES).count()
159 0
160
161
162For SourcePackages, getBuildRecords() returns all build records
163published in its context (distroseries and distribution main
164archives), independent of their corresponding source publishing
165status.
166
167 >>> firefox = warty.getSourcePackage('mozilla-firefox')
168
169 >>> firefox.getBuildRecords().count()
170 8
171
172 >>> firefox.getBuildRecords(
173 ... build_state=BuildStatus.FULLYBUILT).count()
174 6
175
176 >>> firefox.getBuildRecords(
177 ... pocket=PackagePublishingPocket.RELEASE).count()
178 8
179
180 >>> firefox.getBuildRecords(
181 ... pocket=PackagePublishingPocket.UPDATES).count()
182 0
183
184As mentioned above, SourcePackage.getBuildRecords() will return builds
185for packages that are no longer published. At first, there are no
186traces of the 'old-source' sourcepackage in ubuntutest/breezy-autotest
187
188 >>> ubuntutest = getUtility(IDistributionSet).getByName('ubuntutest')
189 >>> breezy_autotest = ubuntutest.getSeries('breezy-autotest')
190 >>> print breezy_autotest.getSourcePackage('old-source')
191 None
192
193Once the SourcePackage exists and has builds, they will be returned by
194getBuildRecords() ordered by descending creation date.
195
196 # Create a DELETED and a SUPERSEDED source publication in
197 # ubuntutest/breezy-autotest.
198 >>> from lp.soyuz.enums import PackagePublishingStatus
199 >>> login('foo.bar@canonical.com')
200 >>> old_source_pub = test_publisher.getPubSource(
201 ... sourcename='old-source', version='1.0',
202 ... status=PackagePublishingStatus.SUPERSEDED)
203 >>> [superseded_build] = old_source_pub.createMissingBuilds()
204 >>> deleted_source_pub = test_publisher.getPubSource(
205 ... sourcename='old-source', version='1.1',
206 ... status=PackagePublishingStatus.DELETED)
207 >>> [deleted_build] = deleted_source_pub.createMissingBuilds()
208 >>> login(ANONYMOUS)
209
210 >>> old_source_sp = breezy_autotest.getSourcePackage('old-source')
211 >>> old_source_builds = old_source_sp.getBuildRecords()
212 >>> [deleted_build, superseded_build] == list(old_source_builds)
213 True
214
215 >>> deleted_build.date_created > superseded_build.date_created
216 True
217
218Builds records for the exactly the same `SourcePackageRelease`s may
219exist in a rebuild archive context, but they do not 'leak' to the
220domain of SourcePackage.
221
222 # Create a rebuild archive, copy the 'old-source' source
223 # publications to it and create builds in the rebuild archive
224 # context.
225 >>> from lp.soyuz.enums import ArchivePurpose
226 >>> login('foo.bar@canonical.com')
227 >>> rebuild_archive = factory.makeArchive(
228 ... ubuntutest, ubuntutest.owner, 'test-rebuild',
229 ... ArchivePurpose.COPY)
230 >>> rebuild_old_pub = old_source_pub.copyTo(
231 ... breezy_autotest, PackagePublishingPocket.RELEASE,
232 ... rebuild_archive)
233 >>> [rebuild_old_build] = rebuild_old_pub.createMissingBuilds()
234 >>> rebuild_deleted_pub = deleted_source_pub.copyTo(
235 ... breezy_autotest, PackagePublishingPocket.RELEASE,
236 ... rebuild_archive)
237 >>> [rebuild_deleted_build] = rebuild_deleted_pub.createMissingBuilds()
238 >>> login(ANONYMOUS)
239
240 >>> rebuild_builds = rebuild_archive.getBuildRecords()
241 >>> [rebuild_deleted_build, rebuild_old_build] == list(rebuild_builds)
242 True
243
244 >>> old_source_sp.getBuildRecords().count()
245 2
246
247For a given distribution as well:
248
249 >>> ubuntu.getBuildRecords().count()
250 17
251
252 >>> builds = ubuntu.getBuildRecords(build_state=BuildStatus.FULLYBUILT)
253 >>> for build in builds:
254 ... print build.date_finished, build.id, build.status.value
255 2007-08-10 00:00:14+00:00 30 1
256 2007-08-09 23:59:59+00:00 29 1
257 2005-03-25 00:00:03+00:00 7 1
258 2005-03-25 00:00:02+00:00 16 1
259 2005-03-25 00:00:01+00:00 19 1
260 2004-09-27 11:57:14+00:00 2 1
261 2004-09-27 11:57:13+00:00 18 1
262
263Retrieve the current PENDING builds
264
265 >>> builds = ubuntu.getBuildRecords(build_state=BuildStatus.NEEDSBUILD)
266 >>> builds.count()
267 2
268
269Note, by ordering the build by BuildQueue.lastscore, it already notice
270the existence of a new pending build, since retry already creates a
271new BuildQueue record:
272
273 >>> builds = ubuntu.getBuildRecords(build_state=BuildStatus.NEEDSBUILD)
274 >>> builds.count()
275 2
276
277Note that they are ordered by DESC lastscore, as expected:
278
279 >>> for b in builds:
280 ... b.id, b.status.value, b.buildqueue_record.lastscore
281 (9, 0, 2505)
282 (11, 0, 10)
283
284Define a helper function to print out build details.
285
286 >>> def print_build_details(builds):
287 ... for build in builds:
288 ... if build.archive.owner:
289 ... print "%s: %s" % (build.archive.owner.name, build.title)
290 ... else:
291 ... print "main: %s" % (build.title)
292
293Using the optional name argument to filter build results:
294
295 >>> builds = ubuntu.getBuildRecords(name='pm')
296 >>> builds.count()
297 4
298 >>> print_build_details(builds)
299 ubuntu-team: i386 build of pmount 0.1-1 in ubuntu warty RELEASE
300 ubuntu-team: i386 build of pmount 0.1-1 in ubuntu breezy-autotest RELEASE
301 ubuntu-team: hppa build of pmount 0.1-1 in ubuntu hoary RELEASE
302 ubuntu-team: i386 build of pmount 0.1-1 in ubuntu hoary RELEASE
303
304or using optional pocket argument:
305
306 >>> from lp.registry.interfaces.pocket import PackagePublishingPocket
307
308 >>> ubuntu.getBuildRecords(
309 ... build_state=BuildStatus.NEEDSBUILD,
310 ... pocket=PackagePublishingPocket.RELEASE).count()
311 2
312
313 >>> ubuntu.getBuildRecords(
314 ... build_state=BuildStatus.NEEDSBUILD,
315 ... pocket=PackagePublishingPocket.SECURITY).count()
316 0
317
318IHasBuildRecords is implemented by Builder. It can filter on build state
319and name. A user can also be passed for security checks on private builds;
320if user is not passed then the query runs anonymously which means private
321builds are excluded from anything returned.
322
323Log in as admin to avoid security on IBinaryPackageBuild for the moment.
324
325 >>> login('foo.bar@canonical.com')
326
327Let's create a private PPA for cprov (and hence its builds become private):
328
329 >>> from lp.registry.interfaces.person import IPersonSet
330 >>> cprov = removeSecurityProxy(getUtility(IPersonSet).getByName('cprov'))
331 >>> cprov_private_ppa = factory.makeArchive(
332 ... owner=cprov, private=True, name='p3a',
333 ... distribution=cprov.archive.distribution)
334 >>> from lp.buildmaster.interfaces.builder import IBuilderSet
335 >>> bob = getUtility(IBuilderSet)['bob']
336 >>> binaries = test_publisher.getPubBinaries(
337 ... archive=cprov_private_ppa, builder=bob,
338 ... binaryname='privacycheck-bin')
339 >>> flush_database_updates()
340
341The default set of builds with no user specified excludes private builds:
342
343 >>> bob_builds = bob.getBuildRecords()
344 >>> print_build_details(bob_builds)
345 ubuntu-team: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
346 cprov: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
347 cprov: i386 build of pmount 0.1-1 in ubuntu warty RELEASE
348 cprov: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
349 no-priv: i386 build of cdrkit 1.0 in ubuntu warty RELEASE
350 ubuntu-team: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
351 ...
352 ubuntu-team: i386 build of mozilla-firefox 0.9 in ubuntu warty RELEASE
353 ubuntu-team: i386 build of mozilla-firefox 0.9 in ubuntu breezy-autotest
354 RELEASE
355
356 >>> bob_builds.count()
357 16
358
359If we include an admin user, we can see all the builds. Here, we get
360an additional private build for cprov:
361
362 >>> from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
363 >>> admin = getUtility(ILaunchpadCelebrities).admin
364 >>> bob_builds = bob.getBuildRecords(user=admin)
365 >>> print_build_details(bob_builds)
366 cprov: i386 build of privacycheck 666 in ubuntutest breezy-autotest...
367 ubuntu-team: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
368 cprov: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
369 cprov: i386 build of pmount 0.1-1 in ubuntu warty RELEASE
370 cprov: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
371 no-priv: i386 build of cdrkit 1.0 in ubuntu warty RELEASE
372 ubuntu-team: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
373 ...
374 ubuntu-team: i386 build of mozilla-firefox 0.9 in ubuntu warty RELEASE
375 ubuntu-team: i386 build of mozilla-firefox 0.9 in ubuntu breezy-autotest
376 RELEASE
377
378 >>> bob_builds.count()
379 17
380
381Cprov can also see his own builds of course:
382
383 >>> bob_builds = bob.getBuildRecords(user=cprov)
384 >>> print_build_details(bob_builds)
385 cprov: i386 build of privacycheck 666 in ubuntutest breezy-autotest...
386 ubuntu-team: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
387 cprov: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
388 cprov: i386 build of pmount 0.1-1 in ubuntu warty RELEASE
389 cprov: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
390 no-priv: i386 build of cdrkit 1.0 in ubuntu warty RELEASE
391 ubuntu-team: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
392 ...
393 ubuntu-team: i386 build of mozilla-firefox 0.9 in ubuntu warty RELEASE
394 ubuntu-team: i386 build of mozilla-firefox 0.9 in ubuntu breezy-autotest
395 RELEASE
396
397 >>> bob_builds.count()
398 17
399
400Buildd admins specifically are not allowed to see private builds, which will
401be filtered from the list returned:
402
403 >>> buildd_admin = factory.makePerson()
404 >>> buildd_admins = getUtility(
405 ... IPersonSet).getByName('launchpad-buildd-admins')
406 >>> ignored = buildd_admins.addMember(buildd_admin, buildd_admin)
407 >>> bob_builds = bob.getBuildRecords(user=buildd_admin)
408 >>> print_build_details(bob_builds)
409 ubuntu-team: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
410 cprov: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
411 cprov: i386 build of pmount 0.1-1 in ubuntu warty RELEASE
412 cprov: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
413 no-priv: i386 build of cdrkit 1.0 in ubuntu warty RELEASE
414 ubuntu-team: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
415 ...
416 ubuntu-team: i386 build of mozilla-firefox 0.9 in ubuntu warty RELEASE
417 ubuntu-team: i386 build of mozilla-firefox 0.9 in ubuntu breezy-autotest
418 RELEASE
419
420 >>> bob_builds.count()
421 16
422
423You can filter on build state:
424
425 >>> bob_failed_builds = bob.getBuildRecords(
426 ... build_state=BuildStatus.FAILEDTOBUILD, user=admin)
427 >>> bob_failed_builds.count()
428 3
429
430You can filter on package name:
431
432 >>> bob_pmount_builds = bob.getBuildRecords(name='pmount', user=admin)
433 >>> bob_pmount_builds.count()
434 4
435
436You can filter on build state and package name:
437
438 >>> bob_pmount_ok_builds = bob.getBuildRecords(
439 ... build_state=BuildStatus.FULLYBUILT, name='pmount', user=admin)
440 >>> bob_pmount_ok_builds.count()
441 4
442
443
444== AssertionErrors in IBinaryPackageBuild ==1== AssertionErrors in IBinaryPackageBuild ==
4452
446Build records inserted by gina don't provide calculated_buildstart3Build records inserted by gina don't provide calculated_buildstart
4474
=== modified file 'lib/lp/soyuz/tests/test_binarypackagebuild.py'
--- lib/lp/soyuz/tests/test_binarypackagebuild.py 2011-01-14 10:06:08 +0000
+++ lib/lp/soyuz/tests/test_binarypackagebuild.py 2011-01-20 21:02:59 +0000
@@ -49,9 +49,9 @@
49 super(TestBinaryPackageBuild, self).setUp()49 super(TestBinaryPackageBuild, self).setUp()
50 publisher = SoyuzTestPublisher()50 publisher = SoyuzTestPublisher()
51 publisher.prepareBreezyAutotest()51 publisher.prepareBreezyAutotest()
52 gedit_spr = publisher.getPubSource(52 gedit_spph = publisher.getPubSource(
53 spr_only=True, sourcename="gedit",53 sourcename="gedit", status=PackagePublishingStatus.PUBLISHED)
54 status=PackagePublishingStatus.PUBLISHED)54 gedit_spr = gedit_spph.sourcepackagerelease
55 self.build = gedit_spr.createBuild(55 self.build = gedit_spr.createBuild(
56 distro_arch_series=publisher.distroseries['i386'],56 distro_arch_series=publisher.distroseries['i386'],
57 archive=gedit_spr.upload_archive,57 archive=gedit_spr.upload_archive,
5858
=== modified file 'lib/lp/soyuz/tests/test_hasbuildrecords.py'
--- lib/lp/soyuz/tests/test_hasbuildrecords.py 2010-10-04 19:50:45 +0000
+++ lib/lp/soyuz/tests/test_hasbuildrecords.py 2011-01-20 21:02:59 +0000
@@ -1,20 +1,33 @@
1# Copyright 2009-2010 Canonical Ltd. This software is licensed under the1# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Test implementations of the IHasBuildRecords interface."""4"""Test implementations of the IHasBuildRecords interface."""
55
6from datetime import (
7 datetime,
8 timedelta,
9 )
10import pytz
6from zope.component import getUtility11from zope.component import getUtility
7from zope.security.proxy import removeSecurityProxy12from zope.security.proxy import removeSecurityProxy
813
9from canonical.testing.layers import LaunchpadZopelessLayer14from canonical.testing.layers import LaunchpadZopelessLayer
10from lp.buildmaster.enums import BuildFarmJobType15from lp.buildmaster.enums import (
16 BuildFarmJobType,
17 BuildStatus,
18 )
11from lp.buildmaster.interfaces.builder import IBuilderSet19from lp.buildmaster.interfaces.builder import IBuilderSet
12from lp.buildmaster.interfaces.buildfarmjob import (20from lp.buildmaster.interfaces.buildfarmjob import (
13 IBuildFarmJob,21 IBuildFarmJob,
14 )22 )
15from lp.buildmaster.interfaces.packagebuild import IPackageBuildSource23from lp.buildmaster.interfaces.packagebuild import IPackageBuildSource
24from lp.registry.interfaces.person import IPersonSet
16from lp.registry.interfaces.pocket import PackagePublishingPocket25from lp.registry.interfaces.pocket import PackagePublishingPocket
17from lp.registry.model.sourcepackage import SourcePackage26from lp.registry.model.sourcepackage import SourcePackage
27from lp.soyuz.enums import (
28 ArchivePurpose,
29 PackagePublishingStatus,
30 )
18from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuild31from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuild
19from lp.soyuz.interfaces.buildrecords import (32from lp.soyuz.interfaces.buildrecords import (
20 IHasBuildRecords,33 IHasBuildRecords,
@@ -22,6 +35,12 @@
22 )35 )
23from lp.soyuz.model.processor import ProcessorFamilySet36from lp.soyuz.model.processor import ProcessorFamilySet
24from lp.soyuz.tests.test_binarypackagebuild import BaseTestCaseWithThreeBuilds37from lp.soyuz.tests.test_binarypackagebuild import BaseTestCaseWithThreeBuilds
38from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
39from lp.testing import (
40 person_logged_in,
41 TestCaseWithFactory,
42 )
43from lp.testing.sampledata import ADMIN_EMAIL
2544
2645
27class TestHasBuildRecordsInterface(BaseTestCaseWithThreeBuilds):46class TestHasBuildRecordsInterface(BaseTestCaseWithThreeBuilds):
@@ -37,7 +56,6 @@
37 def setUp(self):56 def setUp(self):
38 """Use `SoyuzTestPublisher` to publish some sources in archives."""57 """Use `SoyuzTestPublisher` to publish some sources in archives."""
39 super(TestHasBuildRecordsInterface, self).setUp()58 super(TestHasBuildRecordsInterface, self).setUp()
40
41 self.context = self.publisher.distroseries.distribution59 self.context = self.publisher.distroseries.distribution
4260
43 def testProvidesHasBuildRecords(self):61 def testProvidesHasBuildRecords(self):
@@ -64,6 +82,67 @@
64 self.assertContentEqual(i386_builds, builds)82 self.assertContentEqual(i386_builds, builds)
6583
6684
85class TestDistributionHasBuildRecords(TestCaseWithFactory):
86 """Populate a distroseries with builds"""
87
88 layer = LaunchpadZopelessLayer
89
90 def setUp(self):
91 super(TestDistributionHasBuildRecords, self).setUp()
92 self.admin = getUtility(IPersonSet).getByEmail(ADMIN_EMAIL)
93 # Create the machinery we need to create builds, such as
94 # DistroArchSeries and builders.
95 self.pf_one = self.factory.makeProcessorFamily()
96 pf_proc_1 = self.pf_one.addProcessor(
97 self.factory.getUniqueString(), '', '')
98 self.pf_two = self.factory.makeProcessorFamily()
99 pf_proc_2 = self.pf_two.addProcessor(
100 self.factory.getUniqueString(), '', '')
101 self.distroseries = self.factory.makeDistroSeries()
102 self.distribution = self.distroseries.distribution
103 self.das_one = self.factory.makeDistroArchSeries(
104 distroseries=self.distroseries, processorfamily=self.pf_one,
105 supports_virtualized=True)
106 self.das_two = self.factory.makeDistroArchSeries(
107 distroseries=self.distroseries, processorfamily=self.pf_two,
108 supports_virtualized=True)
109 self.archive = self.factory.makeArchive(
110 distribution=self.distroseries.distribution,
111 purpose=ArchivePurpose.PRIMARY)
112 self.arch_ids = [arch.id for arch in self.distroseries.architectures]
113 with person_logged_in(self.admin):
114 self.publisher = SoyuzTestPublisher()
115 self.publisher.prepareBreezyAutotest()
116 self.distroseries.nominatedarchindep = self.das_one
117 self.publisher.addFakeChroots(distroseries=self.distroseries)
118 self.builder_one = self.factory.makeBuilder(processor=pf_proc_1)
119 self.builder_two = self.factory.makeBuilder(processor=pf_proc_2)
120 self.builds = []
121 self.createBuilds()
122
123 def createBuilds(self):
124 for i in range(5):
125 # Create some test builds.
126 spph = self.publisher.getPubSource(
127 sourcename=self.factory.getUniqueString(),
128 version="%s.%s" % (self.factory.getUniqueInteger(), i),
129 distroseries=self.distroseries, architecturehintlist='any')
130 builds = spph.createMissingBuilds()
131 for b in builds:
132 if i == 4:
133 b.status = BuildStatus.FAILEDTOBUILD
134 else:
135 b.status = BuildStatus.FULLYBUILT
136 b.buildqueue_record.destroySelf()
137 b.date_started = datetime.now(pytz.UTC)
138 b.date_finished = b.date_started + timedelta(minutes=5)
139 self.builds += builds
140
141 def test_get_build_records(self):
142 # A Distribution also implements IHasBuildRecords.
143 builds = self.distribution.getBuildRecords().count()
144 self.assertEquals(10, builds)
145
67class TestDistroSeriesHasBuildRecords(TestHasBuildRecordsInterface):146class TestDistroSeriesHasBuildRecords(TestHasBuildRecordsInterface):
68 """Test the DistroSeries implementation of IHasBuildRecords."""147 """Test the DistroSeries implementation of IHasBuildRecords."""
69148
@@ -73,13 +152,30 @@
73 self.context = self.publisher.distroseries152 self.context = self.publisher.distroseries
74153
75154
76class TestDistroArchSeriesHasBuildRecords(TestHasBuildRecordsInterface):155class TestDistroArchSeriesHasBuildRecords(TestDistributionHasBuildRecords):
77 """Test the DistroArchSeries implementation of IHasBuildRecords."""156 """Test the DistroArchSeries implementation of IHasBuildRecords."""
78157
158 layer = LaunchpadZopelessLayer
159
79 def setUp(self):160 def setUp(self):
80 super(TestDistroArchSeriesHasBuildRecords, self).setUp()161 super(TestDistroArchSeriesHasBuildRecords, self).setUp()
81162
82 self.context = self.publisher.distroseries['i386']163 def test_distroarchseries(self):
164 # We can fetch builds records from a DistroArchSeries.
165 builds = self.das_one.getBuildRecords().count()
166 self.assertEquals(5, builds)
167 builds = self.das_one.getBuildRecords(
168 build_state=BuildStatus.FULLYBUILT).count()
169 self.assertEquals(4, builds)
170 spn = self.builds[0].source_package_release.sourcepackagename.name
171 builds = self.das_one.getBuildRecords(name=spn).count()
172 self.assertEquals(1, builds)
173 builds = self.das_one.getBuildRecords(
174 pocket=PackagePublishingPocket.RELEASE).count()
175 self.assertEquals(5, builds)
176 builds = self.das_one.getBuildRecords(
177 pocket=PackagePublishingPocket.UPDATES).count()
178 self.assertEquals(0, builds)
83179
84180
85class TestArchiveHasBuildRecords(TestHasBuildRecordsInterface):181class TestArchiveHasBuildRecords(TestHasBuildRecordsInterface):
@@ -144,7 +240,6 @@
144 # can only test this by creating a lone IBuildFarmJob of a240 # can only test this by creating a lone IBuildFarmJob of a
145 # different type.241 # different type.
146 from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobSource242 from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobSource
147 from lp.buildmaster.enums import BuildStatus
148 build_farm_job = getUtility(IBuildFarmJobSource).new(243 build_farm_job = getUtility(IBuildFarmJobSource).new(
149 job_type=BuildFarmJobType.RECIPEBRANCHBUILD, virtualized=True,244 job_type=BuildFarmJobType.RECIPEBRANCHBUILD, virtualized=True,
150 status=BuildStatus.BUILDING)245 status=BuildStatus.BUILDING)
@@ -180,11 +275,9 @@
180275
181 def setUp(self):276 def setUp(self):
182 super(TestSourcePackageHasBuildRecords, self).setUp()277 super(TestSourcePackageHasBuildRecords, self).setUp()
183
184 gedit_name = self.builds[0].source_package_release.sourcepackagename278 gedit_name = self.builds[0].source_package_release.sourcepackagename
185 self.context = SourcePackage(279 self.context = SourcePackage(
186 gedit_name,280 gedit_name, self.builds[0].distro_arch_series.distroseries)
187 self.builds[0].distro_arch_series.distroseries)
188281
189 # Convert the other two builds to be builds of282 # Convert the other two builds to be builds of
190 # gedit as well so that the one source package (gedit) will have283 # gedit as well so that the one source package (gedit) will have
@@ -192,3 +285,85 @@
192 for build in self.builds[1:3]:285 for build in self.builds[1:3]:
193 spr = build.source_package_release286 spr = build.source_package_release
194 removeSecurityProxy(spr).sourcepackagename = gedit_name287 removeSecurityProxy(spr).sourcepackagename = gedit_name
288
289 # Set them as sucessfully built
290 for build in self.builds:
291 build.status = BuildStatus.FULLYBUILT
292 build.buildqueue_record.destroySelf()
293 removeSecurityProxy(build).date_created = (
294 self.factory.getUniqueDate())
295 build.date_started = datetime.now(pytz.UTC)
296 build.date_finished = build.date_started + timedelta(minutes=5)
297
298 def test_get_build_records(self):
299 # We can fetch builds records from a SourcePackage.
300 builds = self.context.getBuildRecords(
301 build_state=BuildStatus.FULLYBUILT).count()
302 self.assertEquals(3, builds)
303 builds = self.context.getBuildRecords(
304 pocket=PackagePublishingPocket.RELEASE).count()
305 self.assertEquals(3, builds)
306 builds = self.context.getBuildRecords(
307 pocket=PackagePublishingPocket.UPDATES).count()
308 self.assertEquals(0, builds)
309
310 def test_ordering_date(self):
311 # Build records returned are ordered by creation date.
312 builds = self.context.getBuildRecords(
313 build_state=BuildStatus.FULLYBUILT)
314 date_created = [build.date_created for build in builds]
315 self.assertTrue(date_created[0] > date_created[1] > date_created[2])
316
317 def test_ordering_lastscore(self):
318 # PENDING build records returned are ordered by score.
319 spph = self.factory.makeSourcePackagePublishingHistory()
320 spr = spph.sourcepackagerelease
321 source_package = SourcePackage.new(
322 spph.sourcepackagerelease.sourcepackagename, spph.distroseries)
323 build1 = self.factory.makeBinaryPackageBuild(
324 source_package_release=spr)
325 build2 = self.factory.makeBinaryPackageBuild(
326 source_package_release=spr)
327 build1.queueBuild()
328 build2.queueBuild()
329 build1.buildqueue_record.lastscore = 10
330 build2.buildqueue_record.lastscore = 1000
331 builds = list(source_package.getBuildRecords())
332 self.assertEquals([build2, build1], builds)
333
334 def test_copy_archive_without_leak(self):
335 # If source publications are copied to a .COPY archive, they don't
336 # "leak" into SourcePackage.getBuildRecords().
337 admin = getUtility(IPersonSet).getByEmail(ADMIN_EMAIL)
338 # Set up a distroseries and related bits, so we can create builds.
339 source_name = self.factory.getUniqueString()
340 spn = self.factory.makeSourcePackageName(name=source_name)
341 pf = self.factory.makeProcessorFamily()
342 pf_proc = pf.addProcessor(self.factory.getUniqueString(), '', '')
343 distroseries = self.factory.makeDistroSeries()
344 das = self.factory.makeDistroArchSeries(
345 distroseries=distroseries, processorfamily=pf,
346 supports_virtualized=True)
347 with person_logged_in(admin):
348 publisher = SoyuzTestPublisher()
349 publisher.prepareBreezyAutotest()
350 publisher.addFakeChroots(distroseries=distroseries)
351 distroseries.nominatedarchindep = das
352 builder = self.factory.makeBuilder(processor=pf_proc)
353 spph = self.factory.makeSourcePackagePublishingHistory(
354 sourcepackagename=spn, distroseries=distroseries)
355 spph.createMissingBuilds()
356 # Create a copy archive.
357 copy = self.factory.makeArchive(
358 purpose=ArchivePurpose.COPY,
359 distribution=distroseries.distribution)
360 # And copy the publication into it.
361 copy_spph = spph.copyTo(
362 distroseries, PackagePublishingPocket.RELEASE, copy)
363 [copy_build] = copy_spph.createMissingBuilds()
364 builds = copy.getBuildRecords()
365 self.assertEquals([copy_build], list(builds))
366 source = SourcePackage(spn, spph.distroseries)
367 # SourcePackage.getBuildRecords() doesn't have two build records.
368 builds = source.getBuildRecords().count()
369 self.assertEquals(1, builds)