launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #02347
[Merge] lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-4 into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-4 into lp:launchpad with lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-3 as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion-part-4/+merge/46535
Building on https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion-part-3/+merge/46209, this branch moves even more of binarypackagebuild.txt into unit tests.
--
https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion-part-4/+merge/46535
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-4 into lp:launchpad.
=== modified file 'lib/lp/soyuz/doc/binarypackagebuild.txt'
--- lib/lp/soyuz/doc/binarypackagebuild.txt 2011-01-17 21:32:16 +0000
+++ lib/lp/soyuz/doc/binarypackagebuild.txt 2011-01-17 21:32:17 +0000
@@ -42,26 +42,6 @@
>>> login(ANONYMOUS)
-Partner archive builds are an exception to this rule; they can be retried
-in the release pocket for a released distro. Let's turn build 9 into a
-partner archive build:
-
- >>> partner_archive = ubuntu.getArchiveByComponent('partner')
- >>> removeSecurityProxy(failed_build).archive = partner_archive
-
-The build can now be re-tried:
-
- >>> failed_build.can_be_retried
- True
-
-Similarly to PPA builds, they can be retried for release pockets since
-they will happen in another archive.
-
- >>> removeSecurityProxy(failed_build).archive = cprov.archive
-
- >>> failed_build.can_be_retried
- True
-
storeUploadLog() refuses to override any previously stored
'upload_log'.
@@ -92,251 +72,6 @@
>>> print failedtoupload_build.upload_log.filename
upload_22_log.txt
-
-== Updating build-dependencies line ==
-
-The IBinaryPackageBuild.dependencies field is only filled when a build
-job is collected as MANUALDEPWAIT, its content is informed by the
-buildd-slave in the apt-dependencies format.
-
- >>> depwait_build = getUtility(IBinaryPackageBuildSet).getByBuildID(12)
- >>> print depwait_build.dependencies
- cpp (>= 4:4.0.1-3), gcc-4.0 (>= 4.0.1-2)
-
-IBinaryPackageBuild.updateDependencies is designed to process this field
-and eliminate dependencies that can be satisfied. It is used as part of
-the auto-depwait processing where all builds marked as MANUALDEPWAIT are
-re-processed and the ones with empty dependencies are re-queued.
-
-If nothing has changed, which is the case of the current
-depwait_build, the 'dependencies' field remains the same.
-
- >>> old_dep = depwait_build.dependencies
- >>> depwait_build.updateDependencies()
- >>> depwait_build.dependencies == old_dep
- True
-
-A dependency can only be used if it is an a component allowed in our
-context (see above on 'Ogre' components). If we do a build using a
-dependency available in the sample data but published in an unreachable
-component, we will see that the dependency is considered to be unsatisfied.
-See also bug 177827.
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
- >>> depwait_build.dependencies = u'pmount'
- >>> flush_database_updates()
-
-'pmount' in hoary/i386 is published in the 'universe' component:
-
- >>> hoary_i386 = depwait_build.distro_arch_series
- >>> pmount_pub = hoary_i386[
- ... 'pmount'].currentrelease.current_publishing_record
- >>> print pmount_pub.component.name
- universe
-
-The build is only allowed to depend on packages published in 'main':
-
- >>> print depwait_build.current_component.name
- main
-
- >>> from lp.soyuz.adapters.archivedependencies import (
- ... get_components_for_context)
- >>> print get_components_for_context(
- ... depwait_build.current_component, depwait_build.pocket)
- ['main']
-
-Thus the 'pmount' dependency remains unsatisfied.
-
- >>> depwait_build.updateDependencies()
- >>> print depwait_build.dependencies
- pmount
-
-If we make pmount in hoary/i386 reachable, by moving it to the 'main'
-component, we can see that it will be excluded from the dependencies
-list.
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
- >>> from lp.soyuz.interfaces.component import IComponentSet
- >>> main_component = getUtility(IComponentSet)['main']
- >>> pmount_pub = hoary_i386[
- ... 'pmount'].currentrelease.current_publishing_record
- >>> pmount_pub.component = main_component
- >>> depwait_build.dependencies = u'mozilla-firefox, pmount'
- >>> from canonical.database.sqlbase import flush_database_caches
- >>> flush_database_caches()
- >>> transaction.commit()
- >>> login(ANONYMOUS)
-
- >>> flush_database_updates()
-
-Note that only the satisfied dependencies are removed the build
-dependency list.
-
- >>> depwait_build.updateDependencies()
- >>> print depwait_build.dependencies
- mozilla-firefox
-
-'pmount' dependency is also satisfied in the Celso's PPA context,
-even when it is published in a component not allowed in its current
-component domain ('ogre_components'). That's because PPAs implicitly
-depend on all components of its distribution PRIMARY archive.
-
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
- >>> depwait_build.dependencies = u'biscuit, pmount'
- >>> universe_component = getUtility(IComponentSet)['universe']
- >>> pmount_pub.component = universe_component
- >>> removeSecurityProxy(depwait_build).archive = cprov.archive
- >>> flush_database_caches()
- >>> login(ANONYMOUS)
-
- >>> print get_components_for_context(
- ... depwait_build.current_component, depwait_build.pocket)
- ['main']
-
- >>> print pmount_pub.component.name
- universe
-
- >>> depwait_build.updateDependencies()
- >>> print depwait_build.dependencies
- biscuit
-
-Restore depwait_build previous state.
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
- >>> pmount_pub.component = main_component
- >>> removeSecurityProxy(depwait_build).archive = ubuntu.main_archive
- >>> flush_database_caches()
- >>> login(ANONYMOUS)
-
-=== Retrying DEPWAIT builds ===
-
-It depends on the callsite to decide whether or not to 'retry' a
-build after calling updateDependencies, to encapsulate such decision
-for performing the mentioned auto-depwait procedure we have a utility
-in IBinaryPackageBuildSet called retryDepWaiting().
-
- >>> print depwait_build.status.name
- MANUALDEPWAIT
- >>> print depwait_build.distro_arch_series.title
- The Hoary Hedgehog Release for i386 (x86)
-
-In order to allow depwait_build to be retried we will forge a
-'fully-satisfiable' dependencies field.
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
- >>> depwait_build.dependencies = u'pmount'
- >>> login(ANONYMOUS)
- >>> flush_database_updates()
-
-Then we can run the utility method for the target distroarchseries and
-expect depwait_build to be 'retried' and scored.
-
- >>> getUtility(IBinaryPackageBuildSet).retryDepWaiting(hoaryi386)
-
- >>> print depwait_build.status.name
- NEEDSBUILD
-
- >>> depwait_build.buildqueue_record.lastscore
- 2505
-
-The 'retryDepWaiting' task is performed periodically via cronjob by
-cronscript/buildd-retry-depwait.py. It can be run in parallel with
-other buildd tasks because the procedure is 'atomic' enough, i.e.,
-after the commit the retried jobs are ready to be dispatched.
-
-
-== Build rescoring ==
-
-Some builds can be rescored, to determine if it's possible check the
-can_be_rescored property:
-
- >>> depwait_build.can_be_rescored
- True
-
-We need to be at least a buildd-admin to rescore:
-
- >>> depwait_build.rescore(1000)
- Traceback (most recent call last):
- ...
- Unauthorized:...
-
- >>> login('celso.providelo@xxxxxxxxxxxxx')
- >>> depwait_build.rescore(1000)
- >>> print depwait_build.buildqueue_record.lastscore
- 1000
-
-If a callsite tries to rescore a build that is not in the NEEDSBUILD state,
-a CannotBeRescored exception is raised.
-
- >>> depwait_build.status = BuildStatus.FAILEDTOUPLOAD
- >>> depwait_build.rescore(1000)
- Traceback (most recent call last):
- ...
- CannotBeRescored: Build cannot be rescored.
-
- >>> login(ANONYMOUS)
-
-
-== Build record security ==
-
-IBinaryPackageBuild's content class is wrapped in a Zope security
-wrapper that prevents access to private builds for unauthorised users.
-
-Accessing the cprov builds when logged in as admin will see the records:
-
- >>> login('admin@xxxxxxxxxxxxx')
- >>> bob_builds = bob.getBuildRecords(user=admin)
- >>> print_build_details(bob_builds)
- cprov: i386 build of privacycheck 666 in ubuntutest breezy-autotest...
- ubuntu-team: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
- cprov: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
- cprov: i386 build of pmount 0.1-1 in ubuntu warty RELEASE
- cprov: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
- ...
-
-Likewise when logged in as cprov:
-
- >>> login('celso.providelo@xxxxxxxxxxxxx')
- >>> bob_builds = bob.getBuildRecords(user=admin)
- >>> print_build_details(bob_builds)
- cprov: i386 build of privacycheck 666 in ubuntutest breezy-autotest...
- ubuntu-team: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
- cprov: hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE
- cprov: i386 build of pmount 0.1-1 in ubuntu warty RELEASE
- cprov: i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
- ...
-
-A user who is a buildd admin is not allowed to see the build records for
-private builds. Even though they are admin, privacy must be maintained.
-
- >>> login(buildd_admin.preferredemail.email)
- >>> bob_builds = bob.getBuildRecords(user=admin)
-
-Define a helper function to catch the security exception:
-
- >>> from zope.security.interfaces import Unauthorized
- >>> def print_builds_with_exception(builds):
- ... try:
- ... print_build_details(bob_builds)
- ... except Unauthorized:
- ... print "Generated Unauthorized exception as expected"
- ... else:
- ... print "FAIL: should raise Unauthorized exception"
-
-And try to access the builds:
-
- >>> print_builds_with_exception(bob_builds)
- Generated Unauthorized exception as expected
-
-When logged in as anonymous this will generate a securtity exception
-when accessing the builds:
-
- >>> login(ANONYMOUS)
- >>> bob_builds = bob.getBuildRecords(user=admin)
- >>> print_builds_with_exception(bob_builds)
- Generated Unauthorized exception as expected
-
There are other settable attributes declared in the zcml that require
launchpad.Edit.
@@ -479,162 +214,3 @@
>>> bq.estimated_duration
datetime.timedelta(0, 3600)
-
-== IBinaryPackageBuildSet.getBuildsBySourcePackageRelease() ==
-
-getBuildsBySourcePackageRelease() will return all the Build records for
-all the SourcePackageRelease IDs passed.
-
-Create some sources with builds:
-
- >>> source_one = test_publisher.getPubSource(
- ... status=PackagePublishingStatus.PUBLISHED,
- ... sourcename='sourceone')
- >>> source_two = test_publisher.getPubSource(
- ... status=PackagePublishingStatus.PUBLISHED,
- ... sourcename='sourcetwo')
- >>> build_one = source_one.sourcepackagerelease.createBuild(
- ... test_publisher.breezy_autotest_hppa,
- ... PackagePublishingPocket.RELEASE,
- ... test_publisher.breezy_autotest.main_archive,
- ... status=BuildStatus.FULLYBUILT)
- >>> build_two = source_two.sourcepackagerelease.createBuild(
- ... test_publisher.breezy_autotest_hppa,
- ... PackagePublishingPocket.RELEASE,
- ... test_publisher.breezy_autotest.main_archive,
- ... status=BuildStatus.NEEDSBUILD)
-
- >>> source_ids = (
- ... source_one.sourcepackagerelease.id,
- ... source_two.sourcepackagerelease.id,
- ... )
- >>> builds = removeSecurityProxy(bs).getBuildsBySourcePackageRelease(
- ... source_ids)
- >>> import operator
- >>> for build in sorted(builds, key=operator.attrgetter("id")):
- ... print build.title, build.status.name
- hppa build of sourceone 666 in ubuntutest breezy-autotest RELEASE
- FULLYBUILT
- hppa build of sourcetwo 666 in ubuntutest breezy-autotest RELEASE
- NEEDSBUILD
-
-The results can also be filtered on build state:
-
- >>> builds = removeSecurityProxy(bs).getBuildsBySourcePackageRelease(
- ... source_ids, buildstate=BuildStatus.FULLYBUILT)
- >>> for build in sorted(builds, key=operator.attrgetter("id")):
- ... print build.title, build.status.name
- hppa build of sourceone 666 in ubuntutest breezy-autotest RELEASE
- FULLYBUILT
-
-If there are no matching results then it returns an empty SelectResults.
-
- >>> builds = removeSecurityProxy(bs).getBuildsBySourcePackageRelease(
- ... source_ids, buildstate=BuildStatus.CHROOTWAIT)
- >>> print builds.count()
- 0
-
-Supplying an empty list or None for the IDs results in an empty list
-being returned.
-
- >>> removeSecurityProxy(bs).getBuildsBySourcePackageRelease(None)
- []
-
- >>> removeSecurityProxy(bs).getBuildsBySourcePackageRelease([])
- []
-
-
-== Getting the build records for a particular builder ==
-
-The getBuildsForBuilder method returns all the builds for the
-specified builder ID, ordered from most-recently built.
-
- Create some source packages with which to test the
- getBuildsForBuilder method:
-
- >>> src_pkg_earlier = test_publisher.getPubSource(
- ... status=PackagePublishingStatus.PUBLISHED,
- ... sourcename='earlierbuildsrc', architecturehintlist='hppa i386')
- >>> src_pkg_later = test_publisher.getPubSource(
- ... status=PackagePublishingStatus.PUBLISHED,
- ... sourcename='laterbuildsrc',
- ... architecturehintlist='hppa i386')
-
- Create the builds based on the source packages, with the builds
- for 'earlierbuildsrc' built one day before the 'laterbuildsrc':
-
- >>> frog_builder = getUtility(IBuilderSet)['frog']
- >>> bob_builder = getUtility(IBuilderSet)['bob']
-
- >>> earlier_builds = src_pkg_earlier.createMissingBuilds()
- >>> eg_build_date = earlier_builds[0].date_created
- >>> for build in earlier_builds:
- ... build.date_started = eg_build_date - timedelta(1)
- ... build.date_finished = eg_build_date - timedelta(1)
-
- >>> later_builds = src_pkg_later.createMissingBuilds()
- >>> for build in later_builds:
- ... build.date_started = eg_build_date
- ... build.date_finished = eg_build_date
-
- Ensure that the i386 builds are created by the 'frog' builder,
- while the hppa builds are created by 'bob' the builder:
-
- >>> builds = earlier_builds + later_builds
- >>> for build in builds:
- ... if build.processor.name == u'386':
- ... build.builder = frog_builder
- ... else:
- ... build.builder = bob_builder
-
- A call to getBuildsForBuilder returns only those builds that were
- built by the specified builder, ordered by datebuilt DESC:
-
- >>> frog_builds = getUtility(IBinaryPackageBuildSet).getBuildsForBuilder(
- ... frog_builder.id)
- >>> print_build_details(frog_builds)
- ubuntu-team: i386 build of laterbuildsrc 666 in ubuntutest
- breezy-autotest RELEASE
- ubuntu-team: i386 build of earlierbuildsrc 666 in ubuntutest
- breezy-autotest RELEASE
-
-
-== Source publication for builds ==
-
-The current source publication for a given build is available via
-its 'current_source_publication' property.
-
-We will create a new publication and its corresponding build.
-
- >>> original_pub = test_publisher.getPubSource()
- >>> [build] = original_pub.createMissingBuilds()
-
-The publication returned by 'current_source_publication' is the one
-that originated the build.
-
- >>> build.current_source_publication == original_pub
- True
-
-We will override the source publication, moving it from 'main'
-component (default) to 'universe'.
-
- >>> universe_component = getUtility(IComponentSet)['universe']
- >>> secure_overridden_pub = original_pub.changeOverride(
- ... new_component=universe_component)
-
-Fetching the corresponding `SourcePackagePublishingHistory` for the
-comparisons.
-
- >>> from lp.soyuz.model.publishing import (
- ... SourcePackagePublishingHistory)
- >>> overridden_pub = SourcePackagePublishingHistory.get(
- ... secure_overridden_pub.id)
-
-An we can see that the build 'current_source_publication' now points
-to the most recent publication, the overridden one.
-
- >>> original_pub == build.current_source_publication
- False
-
- >>> overridden_pub == build.current_source_publication
- True
=== modified file 'lib/lp/soyuz/tests/test_build.py'
--- lib/lp/soyuz/tests/test_build.py 2011-01-17 21:32:16 +0000
+++ lib/lp/soyuz/tests/test_build.py 2011-01-17 21:32:17 +0000
@@ -8,6 +8,7 @@
timedelta,
)
import pytz
+import transaction
from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
@@ -17,10 +18,13 @@
from lp.registry.interfaces.pocket import PackagePublishingPocket
from lp.registry.interfaces.series import SeriesStatus
from lp.soyuz.enums import (
+ ArchivePurpose,
BinaryPackageFormat,
PackagePublishingPriority,
PackageUploadStatus,
)
+from lp.soyuz.interfaces.binarypackagebuild import CannotBeRescored
+from lp.soyuz.interfaces.component import IComponentSet
from lp.soyuz.interfaces.publishing import PackagePublishingStatus
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
from lp.testing import (
@@ -75,7 +79,7 @@
[build] = spph.createMissingBuilds()
self.assertEquals(self.distroseries.main_archive, build.archive)
self.assertEquals(self.distroseries.distribution, build.distribution)
- self.assertEquals(self.distroseries, build.distroseries)
+ self.assertEquals(self.distroseries, build.distro_series)
self.assertEquals(self.das, build.distro_arch_series)
self.assertEquals(PackagePublishingPocket.RELEASE, build.pocket)
self.assertEquals(self.das.architecturetag, build.arch_tag)
@@ -160,6 +164,29 @@
[build] = spph.createMissingBuilds()
self.assertFalse(build.can_be_retried)
+ def test_partner_retry_for_released_series(self):
+ # Builds for PARTNER can be retried -- even if the distroseries is
+ # released.
+ distroseries = self.factory.makeDistroSeries()
+ das = self.factory.makeDistroArchSeries(
+ distroseries=distroseries, processorfamily=self.pf,
+ supports_virtualized=True)
+ archive = self.factory.makeArchive(
+ purpose=ArchivePurpose.PARTNER,
+ distribution=distroseries.distribution)
+ with person_logged_in(self.admin):
+ distroseries.nominatedarchindep = das
+ distroseries.status = SeriesStatus.OBSOLETE
+ self.publisher.addFakeChroots(distroseries=distroseries)
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=distroseries, archive=archive)
+ [build] = spph.createMissingBuilds()
+ with person_logged_in(self.admin):
+ build.status = BuildStatus.FAILEDTOBUILD
+ self.assertTrue(build.can_be_retried)
+
def test_retry(self):
# A build can be retried
spph = self.publisher.getPubSource(
@@ -253,3 +280,43 @@
# Verify .binarypackages returns sorted by name
expected_names.sort()
self.assertEquals(expected_names, bin_names)
+
+ def test_cannot_rescore_non_needsbuilds_builds(self):
+ # If a build record isn't in NEEDSBUILD, it can not be rescored.
+ # We will also need to log into an admin to do the rescore
+ with person_logged_in(self.admin):
+ [bpph] = self.publisher.getPubBinaries(
+ binaryname=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=self.distroseries)
+ build = bpph.binarypackagerelease.build
+ self.assertRaises(CannotBeRescored, build.rescore, 20)
+
+ def test_rescore_builds(self):
+ # If the user has build-admin privileges, they can rescore builds
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=self.distroseries)
+ [build] = spph.createMissingBuilds()
+ self.assertEquals(BuildStatus.NEEDSBUILD, build.status)
+ self.assertEquals(2505, build.buildqueue_record.lastscore)
+ with person_logged_in(self.admin):
+ build.rescore(5000)
+ transaction.commit()
+ self.assertEquals(5000, build.buildqueue_record.lastscore)
+
+ def test_source_publication_override(self):
+ # Components can be overridden in builds.
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=self.distroseries)
+ [build] = spph.createMissingBuilds()
+ self.assertEquals(spph, build.current_source_publication)
+ universe = getUtility(IComponentSet)['universe']
+ overridden_spph = spph.changeOverride(new_component=universe)
+ # We can now see current source publication points to the overridden
+ # publication.
+ self.assertNotEquals(spph, build.current_source_publication)
+ self.assertEquals(overridden_spph, build.current_source_publication)
=== added file 'lib/lp/soyuz/tests/test_build_depwait.py'
--- lib/lp/soyuz/tests/test_build_depwait.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/tests/test_build_depwait.py 2011-01-17 21:32:17 +0000
@@ -0,0 +1,118 @@
+# Copyright 2011 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+import transaction
+from zope.component import getUtility
+
+from canonical.testing.layers import LaunchpadFunctionalLayer
+from lp.buildmaster.enums import BuildStatus
+from lp.registry.interfaces.person import IPersonSet
+from lp.soyuz.enums import (
+ ArchivePurpose,
+ PackagePublishingStatus,
+ )
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
+from lp.soyuz.interfaces.component import IComponentSet
+from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
+from lp.testing import (
+ person_logged_in,
+ TestCaseWithFactory,
+ )
+from lp.testing.sampledata import ADMIN_EMAIL
+
+class TestBuildDepWait(TestCaseWithFactory):
+
+ layer = LaunchpadFunctionalLayer
+
+ def setUp(self):
+ super(TestBuildDepWait, self).setUp()
+ self.admin = getUtility(IPersonSet).getByEmail(ADMIN_EMAIL)
+ # Create everything we need to create builds, such as a
+ # DistroArchSeries and a builder.
+ self.pf = self.factory.makeProcessorFamily()
+ pf_proc = self.pf.addProcessor(self.factory.getUniqueString(), '', '')
+ self.distroseries = self.factory.makeDistroSeries()
+ self.das = self.factory.makeDistroArchSeries(
+ distroseries=self.distroseries, processorfamily=self.pf,
+ supports_virtualized=True)
+ self.archive = self.factory.makeArchive(
+ distribution=self.distroseries.distribution,
+ purpose=ArchivePurpose.PRIMARY)
+ with person_logged_in(self.admin):
+ self.publisher = SoyuzTestPublisher()
+ self.publisher.prepareBreezyAutotest()
+ self.distroseries.nominatedarchindep = self.das
+ self.publisher.addFakeChroots(distroseries=self.distroseries)
+ self.builder = self.factory.makeBuilder(processor=pf_proc)
+
+ def test_update_dependancies(self):
+ # Calling .updateDependencies() on a build will update will remove
+ # those which are reachable.
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=self.distroseries, archive=self.archive)
+ [build] = spph.createMissingBuilds()
+ spn = self.factory.getUniqueString()
+ version = "%s.1" % self.factory.getUniqueInteger()
+ with person_logged_in(self.admin):
+ build.status = BuildStatus.MANUALDEPWAIT
+ build.dependencies = unicode(spn)
+ [bpph] = self.publisher.getPubBinaries(
+ binaryname=spn, distroseries=self.distroseries,
+ version=version, builder=self.builder, archive=self.archive,
+ status=PackagePublishingStatus.PUBLISHED)
+ # Commit to make sure stuff hits the database.
+ transaction.commit()
+ build.updateDependencies()
+ self.assertEquals(u'', build.dependencies)
+
+ def test_update_dependancies_respects_component(self):
+ # Since main can only utilise packages that are published in main,
+ # dependencies are not satisfied if they are not in main.
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=self.distroseries, archive=self.archive)
+ [build] = spph.createMissingBuilds()
+ spn = self.factory.getUniqueString()
+ version = "%s.1" % self.factory.getUniqueInteger()
+ with person_logged_in(self.admin):
+ build.status = BuildStatus.MANUALDEPWAIT
+ build.dependencies = unicode(spn)
+ [bpph] = self.publisher.getPubBinaries(
+ binaryname=spn, distroseries=self.distroseries,
+ version=version, builder=self.builder, archive=self.archive,
+ status=PackagePublishingStatus.PUBLISHED, component='universe')
+ # Commit to make sure stuff hits the database.
+ transaction.commit()
+ build.updateDependencies()
+ # Since the dependency is in universe, we still can't see it.
+ self.assertEquals(unicode(spn), build.dependencies)
+ with person_logged_in(self.admin):
+ bpph.component = getUtility(IComponentSet)['main']
+ transaction.commit()
+ # Now that we have moved it main, we can see it.
+ build.updateDependencies()
+ self.assertEquals(u'', build.dependencies)
+
+ def test_retry_dep_waiting(self):
+ # Builds in MANUALDEPWAIT can be automatically retried.
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=self.distroseries, archive=self.archive)
+ [build] = spph.createMissingBuilds()
+ with person_logged_in(self.admin):
+ build.status = BuildStatus.MANUALDEPWAIT
+ # .createMissingBuilds() queues the build for us, and we need to
+ # undo that if we're about to retry it.
+ build.buildqueue_record.destroySelf()
+ build.dependencies = u''
+ # Commit to make sure stuff hits the database.
+ transaction.commit()
+ getUtility(IBinaryPackageBuildSet).retryDepWaiting(self.das)
+ self.assertEquals(BuildStatus.NEEDSBUILD, build.status)
+ self.assertTrue(build.buildqueue_record.lastscore > 0)
=== added file 'lib/lp/soyuz/tests/test_build_privacy.py'
--- lib/lp/soyuz/tests/test_build_privacy.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/tests/test_build_privacy.py 2011-01-17 21:32:17 +0000
@@ -0,0 +1,92 @@
+# Copyright 2011 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+from zope.component import getUtility
+from zope.security.interfaces import Unauthorized
+
+from canonical.testing.layers import LaunchpadFunctionalLayer
+from lp.registry.interfaces.person import IPersonSet
+from lp.soyuz.interfaces.archive import IArchiveSet
+from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
+from lp.testing import (
+ person_logged_in,
+ TestCaseWithFactory,
+ )
+from lp.testing.sampledata import ADMIN_EMAIL
+
+
+class TestBuildPrivacy(TestCaseWithFactory):
+
+ layer = LaunchpadFunctionalLayer
+
+ def setUp(self):
+ super(TestBuildPrivacy, self).setUp()
+ # Add everything we need to create builds.
+ self.admin = getUtility(IPersonSet).getByEmail(ADMIN_EMAIL)
+ pf = self.factory.makeProcessorFamily()
+ pf_proc = pf.addProcessor(self.factory.getUniqueString(), '', '')
+ distroseries = self.factory.makeDistroSeries()
+ das = self.factory.makeDistroArchSeries(
+ distroseries=distroseries, processorfamily=pf,
+ supports_virtualized=True)
+ with person_logged_in(self.admin):
+ publisher = SoyuzTestPublisher()
+ publisher.prepareBreezyAutotest()
+ distroseries.nominatedarchindep = das
+ publisher.addFakeChroots(distroseries=distroseries)
+ self.factory.makeBuilder(processor=pf_proc)
+ self.public_archive = self.factory.makeArchive()
+ self.private_archive = self.factory.makeArchive(private=True)
+ # Create one public and one private build.
+ public_spph = publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=distroseries, archive=self.public_archive)
+ [public_build] = public_spph.createMissingBuilds()
+ private_spph = publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.1" % self.factory.getUniqueInteger(),
+ distroseries=distroseries, archive=self.private_archive)
+ with person_logged_in(self.admin):
+ [private_build] = private_spph.createMissingBuilds()
+ self.expected_title = '%s build of %s %s in %s %s RELEASE' % (
+ das.architecturetag, private_spph.source_package_name,
+ private_spph.source_package_version,
+ distroseries.distribution.name, distroseries.name)
+
+ def _get_build_title(self, build):
+ return build.title
+
+ def test_admin_can_see_private_builds(self):
+ # Admin users can see all builds.
+ with person_logged_in(self.admin):
+ private = getUtility(IArchiveSet).get(self.private_archive.id)
+ [build] = private.getBuildRecords()
+ self.assertEquals(
+ self.expected_title, self._get_build_title(build))
+
+ def test_owner_can_see_own_private_builds(self):
+ # The owner of the private archive is able to see all builds that
+ # publish to that archive.
+ with person_logged_in(self.private_archive.owner):
+ private = getUtility(IArchiveSet).get(self.private_archive.id)
+ [build] = private.getBuildRecords()
+ self.assertEquals(
+ self.expected_title, self._get_build_title(build))
+
+ def test_buildd_admin_cannot_see_private_builds(self):
+ # Admins that look after the builders ("buildd-admins"), can not see
+ # private builds.
+ buildd_admin = getUtility(IPersonSet).getByName(
+ 'launchpad-buildd-admins')
+ with person_logged_in(buildd_admin):
+ private = getUtility(IArchiveSet).get(self.private_archive.id)
+ self.assertRaises(
+ Unauthorized, getattr, private, 'getBuildRecords')
+
+ def test_anonymous_cannot_see_private_builds(self):
+ # An anonymous user can't query the builds for the private archive.
+ private = getUtility(IArchiveSet).get(self.private_archive.id)
+ self.assertRaises(Unauthorized, getattr, private, 'getBuildRecords')
=== modified file 'lib/lp/soyuz/tests/test_build_set.py'
--- lib/lp/soyuz/tests/test_build_set.py 2011-01-17 21:32:16 +0000
+++ lib/lp/soyuz/tests/test_build_set.py 2011-01-17 21:32:17 +0000
@@ -61,6 +61,7 @@
self.builder_one = self.factory.makeBuilder(processor=pf_proc_1)
self.builder_two = self.factory.makeBuilder(processor=pf_proc_2)
self.builds = []
+ self.spphs = []
def setUpBuilds(self):
for i in range(5):
@@ -69,6 +70,7 @@
sourcename=self.factory.getUniqueString(),
version="%s.%s" % (self.factory.getUniqueInteger(), i),
distroseries=self.distroseries, architecturehintlist='any')
+ self.spphs.append(spph)
builds = spph.createMissingBuilds()
with person_logged_in(self.admin):
for b in builds:
@@ -152,3 +154,54 @@
rset = removeSecurityProxy(
getUtility(IBinaryPackageBuildSet))._prefetchBuildData(build_ids)
self.assertEquals(len(rset), 4)
+
+ def test_get_builds_by_source_package_release(self):
+ # We are able to return all of the builds for the source package
+ # release ids passed in.
+ self.setUpBuilds()
+ spphs = self.spphs[:2]
+ ids = [spph.sourcepackagerelease.id for spph in spphs]
+ builds = getUtility(
+ IBinaryPackageBuildSet).getBuildsBySourcePackageRelease(ids)
+ expected_titles = []
+ for spph in spphs:
+ for das in (self.das_one, self.das_two):
+ expected_titles.append(
+ '%s build of %s %s in %s %s RELEASE' % (
+ das.architecturetag, spph.source_package_name,
+ spph.source_package_version,
+ self.distroseries.distribution.name,
+ self.distroseries.name))
+ build_titles = [build.title for build in builds]
+ self.assertEquals(sorted(expected_titles), sorted(build_titles))
+
+ def test_get_builds_by_source_package_release_filtering(self):
+ self.setUpBuilds()
+ ids = [self.spphs[-1].sourcepackagerelease.id]
+ builds = getUtility(
+ IBinaryPackageBuildSet).getBuildsBySourcePackageRelease(
+ ids, buildstate=BuildStatus.FAILEDTOBUILD)
+ expected_titles = []
+ for das in (self.das_one, self.das_two):
+ expected_titles.append(
+ '%s build of %s %s in %s %s RELEASE' % (
+ das.architecturetag, self.spphs[-1].source_package_name,
+ self.spphs[-1].source_package_version,
+ self.distroseries.distribution.name,
+ self.distroseries.name))
+ build_titles = [build.title for build in builds]
+ self.assertEquals(sorted(expected_titles), sorted(build_titles))
+ builds = getUtility(
+ IBinaryPackageBuildSet).getBuildsBySourcePackageRelease(
+ ids, buildstate=BuildStatus.CHROOTWAIT)
+ self.assertEquals([], list(builds))
+
+ def test_no_get_builds_by_source_package_release(self):
+ # If no ids or None are passed into .getBuildsBySourcePackageRelease,
+ # an empty list is returned.
+ builds = getUtility(
+ IBinaryPackageBuildSet).getBuildsBySourcePackageRelease(None)
+ self.assertEquals([], builds)
+ builds = getUtility(
+ IBinaryPackageBuildSet).getBuildsBySourcePackageRelease([])
+ self.assertEquals([], builds)