launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #02376
[Merge] lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-6 into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-6 into lp:launchpad with lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-5 as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion-part-6/+merge/46859
Building on the work from https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion-part-5/+merge/46852, this final branch finally rips out the assertion that I had to wait 6 branches for. It finally knocks out the dazed binarypackagebuild.txt.
All of the tests in lp.soyuz now pass with the assertion.
--
https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion-part-6/+merge/46859
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-6 into lp:launchpad.
=== removed file 'lib/lp/soyuz/doc/binarypackagebuild.txt'
--- lib/lp/soyuz/doc/binarypackagebuild.txt 2011-01-20 00:23:45 +0000
+++ lib/lp/soyuz/doc/binarypackagebuild.txt 1970-01-01 00:00:00 +0000
@@ -1,216 +0,0 @@
-== AssertionErrors in IBinaryPackageBuild ==
-
-Build records inserted by gina don't provide calculated_buildstart
-value, since they miss fields used in its calculation.
-TODO: check and update this based on the new model.
-
- >>> gina_build = getUtility(IBinaryPackageBuildSet).getByBuildID(10)
- >>> gina_build.title
- u'i386 build of cnews cr.g7-37 in ubuntu warty RELEASE'
-
-even if IBinaryPackageBuild.was_built return true:
-
- >>> gina_build.was_built
- True
-
-Only builds in failed_states (FAILEDTOBUILD, MANUALDEPWAIT and
-CHROOTWAIT) can be retried. We must check if Soyuz is able to accept
-its result in case of success, i.e., we should not be able to retry a
-build for a released pocket.
-
-All those conditions are controlled by
-IBinaryPackageBuild.can_be_retried() property (see above).
-
- >>> failed_build = getUtility(IBinaryPackageBuildSet).getByBuildID(6)
-
- >>> failed_build.title
- u'i386 build of foobar 1.0 in ubuntu warty RELEASE'
-
- >>> failed_build.status.name
- 'FAILEDTOBUILD'
-
- >>> failed_build.can_be_retried
- False
-
-Attempt to retry this build record will fail with an AssertionError:
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
- >>> failed_build.retry()
- Traceback (most recent call last):
- ...
- AssertionError: Build 6 cannot be retried
-
- >>> login(ANONYMOUS)
-
-storeUploadLog() refuses to override any previously stored
-'upload_log'.
-
- >>> failedtoupload_build = getUtility(IBinaryPackageBuildSet).getByBuildID(22)
- >>> print failedtoupload_build.title
- i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
-
- >>> print failedtoupload_build.upload_log.filename
- upload_22_log.txt
-
- >>> failedtoupload_build.storeUploadLog('something')
- Traceback (most recent call last):
- ...
- AssertionError: Upload log information already exists and cannot be
- overridden.
-
-It's only possible to store another 'upload_log' content once the
-build is retried.
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
- >>> failedtoupload_build.retry()
- >>> login(ANONYMOUS)
- >>> print failedtoupload_build.upload_log
- None
-
- >>> failedtoupload_build.storeUploadLog('something')
-
- >>> print failedtoupload_build.upload_log.filename
- upload_22_log.txt
-
-There are other settable attributes declared in the zcml that require
-launchpad.Edit.
-
- >>> def check_setting_property(build_rec, property, value, should_fail):
- ... try:
- ... setattr(build_rec, property, value)
- ... if should_fail:
- ... print "Should have failed setting %s" % property
- ... except Unauthorized:
- ... if not should_fail:
- ... print "Did not fail when expected setting %s" % property
- >>> from canonical.database.constants import UTC_NOW
- >>> properties = {
- ... 'log': 1,
- ... 'date_finished': UTC_NOW,
- ... 'date_started': UTC_NOW,
- ... 'builder': bob,
- ... 'status': BuildStatus.FAILEDTOUPLOAD,
- ... 'dependencies': u'whatever',
- ... 'upload_log': 1,
- ... }
-
-Login as a non-privileged user and set the properties. It will fail.
-
- >>> login('no-priv@xxxxxxxxxxxxx')
- >>> for property in properties:
- ... check_setting_property(
- ... depwait_build, property, properties[property],
- ... should_fail=True)
-
-As a buildd-admin it will work:
-
- >>> login('celso.providelo@xxxxxxxxxxxxx')
- >>> for property in properties:
- ... check_setting_property(
- ... depwait_build, property, properties[property],
- ... should_fail=False)
-
-== Estimated Build Duration ==
-
-Build records will have an 'estimated_duration' time in the associated
-BuildQueue record. The latter is set from a previous builds' 'buildduration'
-value.
-
-We will use SoyuzTestPublisher to generate coherent publications to
-test this behaviour.
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
-
-Create oldest SourcePackageRelease instance.
-
- >>> oldest_spr = test_publisher.getPubSource(
- ... status=PackagePublishingStatus.PUBLISHED,
- ... sourcename='ebdtest')
-
-Create oldest build instance.
-
- >>> oldest_build = oldest_spr.sourcepackagerelease.createBuild(
- ... test_publisher.breezy_autotest_hppa,
- ... PackagePublishingPocket.UPDATES,
- ... test_publisher.breezy_autotest.main_archive,
- ... status=BuildStatus.FULLYBUILT)
- >>> oldest_build.date_finished = datetime(2008, 4, 1, 10, 45, 39, tzinfo=UTC)
- >>> oldest_build.date_started = oldest_build.date_finished - timedelta(minutes=72)
-
-Check that the oldest build instance's 'estimated_duration'
-is initialized based on its package size. Since the latter is very
-small (less than a KB) the 'estimated_duration' will be a
-minute.
-
- >>> bq = oldest_build.queueBuild()
- >>> bq.estimated_duration
- datetime.timedelta(0, 60)
-
-Create intermediate SourcePackageRelease instance.
-
- >>> medium_spr = test_publisher.getPubSource(
- ... status=PackagePublishingStatus.PUBLISHED,
- ... sourcename='ebdtest')
-
-Create intermediate build instance.
-
- >>> medium_build = medium_spr.sourcepackagerelease.createBuild(
- ... test_publisher.breezy_autotest_hppa,
- ... PackagePublishingPocket.UPDATES,
- ... test_publisher.breezy_autotest.main_archive,
- ... status=BuildStatus.FULLYBUILT)
- >>> medium_build.date_finished = datetime(2008, 4, 2, 11, 56, 33, tzinfo=UTC)
- >>> medium_build.date_started = medium_build.date_finished - timedelta(minutes=60)
-
-Check whether the intermediate build instance's 'estimated_duration'
-value equals the oldest instance's 'buildduration' (72 minutes equals 4320
-seconds).
-
- >>> bq = medium_build.queueBuild()
- >>> bq.estimated_duration
- datetime.timedelta(0, 4320)
-
-Create most recent SourcePackageRelease instance.
-
- >>> recent_spr = test_publisher.getPubSource(
- ... status=PackagePublishingStatus.PUBLISHED,
- ... sourcename='ebdtest')
-
-Create most recent build instance. Please note: this one is in state
-NEEDSBUILD.
-
- >>> recent_build = recent_spr.sourcepackagerelease.createBuild(
- ... test_publisher.breezy_autotest_hppa,
- ... PackagePublishingPocket.UPDATES,
- ... test_publisher.breezy_autotest.main_archive,
- ... status=BuildStatus.NEEDSBUILD)
-
-Check whether the most recent build instance's 'estimated_duration'
-value equals the intermediate instance's 'buildduration'.
-
- >>> bq = recent_build.queueBuild()
- >>> bq.estimated_duration
- datetime.timedelta(0, 3600)
-
-Create a SourcePackageRelease instance in a PPA.
-
- >>> ppa_spr = test_publisher.getPubSource(
- ... status=PackagePublishingStatus.PUBLISHED,
- ... sourcename='ebdtest')
-
-Create most recent build instance.
-
- >>> ppa_build = ppa_spr.sourcepackagerelease.createBuild(
- ... test_publisher.breezy_autotest_hppa,
- ... PackagePublishingPocket.UPDATES,
- ... cprov.archive,
- ... status=BuildStatus.NEEDSBUILD)
-
-Check whether the PPA build instance's 'estimated_duration'
-value was set from the intermediate instance's 'buildduration' in
-the main archive.
-
- >>> bq = ppa_build.queueBuild()
- >>> bq.estimated_duration
- datetime.timedelta(0, 3600)
-
=== modified file 'lib/lp/soyuz/model/binarypackagebuild.py'
--- lib/lp/soyuz/model/binarypackagebuild.py 2011-01-20 00:23:45 +0000
+++ lib/lp/soyuz/model/binarypackagebuild.py 2011-01-20 00:24:27 +0000
@@ -4,7 +4,10 @@
# pylint: disable-msg=E0611,W0212
__metaclass__ = type
-__all__ = ['BinaryPackageBuild', 'BinaryPackageBuildSet']
+__all__ = [
+ 'BinaryPackageBuild',
+ 'BinaryPackageBuildSet',
+ ]
import datetime
import logging
@@ -160,18 +163,8 @@
def current_component(self):
"""See `IBuild`."""
latest_publication = self._getLatestPublication()
-
- # XXX cprov 2009-06-06 bug=384220:
- # This assertion works fine in production, since all build records
- # are legitimate and have a corresponding source publishing record
- # (which triggered their creation, in first place). However our
- # sampledata is severely broken in this area and depends heavily
- # on the fallback to the source package original component.
- #assert latest_publication is not None, (
- # 'Build %d lacks a corresponding source publication.' % self.id)
- if latest_publication is None:
- return self.source_package_release.component
-
+ assert latest_publication is not None, (
+ 'Build %d lacks a corresponding source publication.' % self.id)
return latest_publication.component
@property
=== modified file 'lib/lp/soyuz/tests/test_build.py'
--- lib/lp/soyuz/tests/test_build.py 2011-01-20 00:23:45 +0000
+++ lib/lp/soyuz/tests/test_build.py 2011-01-20 00:24:27 +0000
@@ -7,9 +7,11 @@
datetime,
timedelta,
)
+from exceptions import AssertionError
import pytz
import transaction
from zope.component import getUtility
+from zope.security.interfaces import Unauthorized
from zope.security.proxy import removeSecurityProxy
from canonical.testing.layers import LaunchpadFunctionalLayer
@@ -53,6 +55,11 @@
self.distroseries.nominatedarchindep = self.das
self.publisher.addFakeChroots(distroseries=self.distroseries)
self.builder = self.factory.makeBuilder(processor=pf_proc)
+ self.now = datetime.now(pytz.UTC)
+ self.properties = {
+ 'log': 1, 'date_started': self.now, 'date_finished': self.now,
+ 'builder': self.builder, 'status': BuildStatus.FAILEDTOUPLOAD,
+ 'dependencies': u'whatever', 'upload_log': 1}
def test_title(self):
# A build has a title which describes the context source version and
@@ -225,16 +232,15 @@
version="%s.1" % self.factory.getUniqueInteger(),
distroseries=self.distroseries)
[build] = spph.createMissingBuilds()
- now = datetime.now(pytz.UTC)
with person_logged_in(self.admin):
build.status = BuildStatus.FAILEDTOBUILD
# The build can't be queued if we're going to retry it
build.buildqueue_record.destroySelf()
- removeSecurityProxy(build).date_first_dispatched = now
+ removeSecurityProxy(build).date_first_dispatched = self.now
with person_logged_in(self.admin):
build.retry()
self.assertEquals(BuildStatus.NEEDSBUILD, build.status)
- self.assertEquals(now, build.date_first_dispatched)
+ self.assertEquals(self.now, build.date_first_dispatched)
self.assertEquals(None, build.log)
self.assertEquals(None, build.upload_log)
@@ -268,7 +274,7 @@
bpn_name = '%s-%s' % (spn, i)
bpn = self.factory.makeBinaryPackageName(bpn_name)
expected_names.append(bpn_name)
- binary = build.createBinaryPackageRelease(
+ build.createBinaryPackageRelease(
binarypackagename=bpn, version=str(i), summary='',
description='', binpackageformat=BinaryPackageFormat.DEB,
component=spph.sourcepackagerelease.component.id,
@@ -320,3 +326,72 @@
# publication.
self.assertNotEquals(spph, build.current_source_publication)
self.assertEquals(overridden_spph, build.current_source_publication)
+
+ def test_security_anonymous(self):
+ # Certain attributes of a build cannot be set by anonymous users.
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=self.distroseries)
+ [build] = spph.createMissingBuilds()
+ for key in self.properties.keys():
+ self.assertRaises(
+ Unauthorized, setattr, build, key, self.properties[key])
+
+ def test_security_admin(self):
+ # Certain attributes of a build can be set by an admin.
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=self.distroseries)
+ [build] = spph.createMissingBuilds()
+ with person_logged_in(self.admin):
+ props = self.properties.keys()
+ props.reverse()
+ for key in props:
+ setattr(build, key, self.properties[key])
+ actual = getattr(build, key)
+ if key.endswith('log'):
+ self.assertEquals(1, actual.id)
+ elif key.startswith('date'):
+ self.assertEquals(self.now, actual)
+ else:
+ self.assertEquals(self.properties[key], actual)
+
+ def test_estimated_duration(self):
+ # Builds will have an estimated duration that is set to a
+ # previous build of the same sources duration.
+ spn = self.factory.getUniqueString()
+ spph = self.publisher.getPubSource(
+ sourcename=spn, status=PackagePublishingStatus.PUBLISHED)
+ [build] = spph.createMissingBuilds()
+ # Duration is based on package size if there is no previous build.
+ self.assertEquals(
+ timedelta(0, 60), build.buildqueue_record.estimated_duration)
+ # Set the build as done, and its duration.
+ with person_logged_in(self.admin):
+ build.status = BuildStatus.FULLYBUILT
+ build.date_started = self.now - timedelta(minutes=72)
+ build.date_finished = self.now
+ build.buildqueue_record.destroySelf()
+ transaction.commit()
+ new_spph = self.publisher.getPubSource(
+ sourcename=spn, status=PackagePublishingStatus.PUBLISHED)
+ [new_build] = new_spph.createMissingBuilds()
+ # The duration for this build is now 72 minutes.
+ self.assertEquals(
+ timedelta(0, 72 * 60),
+ new_build.buildqueue_record.estimated_duration)
+
+ def test_store_uploadlog_refuses_to_overwrite(self):
+ # Storing an upload log for a build will fail if the build already
+ # has an upload log.
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=self.distroseries)
+ [build] = spph.createMissingBuilds()
+ with person_logged_in(self.admin):
+ build.status = BuildStatus.FAILEDTOUPLOAD
+ build.storeUploadLog('foo')
+ self.assertRaises(AssertionError, build.storeUploadLog, 'bar')
Follow ups