launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #02277
[Merge] lp:~stevenk/launchpad/bpb-currentcomponent-assertion into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/bpb-currentcomponent-assertion into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
#384220 Build sampledata is broken
https://bugs.launchpad.net/bugs/384220
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion/+merge/45210
This branch kills build-views.txt with chemical fire, and converts it to a bunch of (regrettably, large) unit tests. It also does a few bits of drive-by that I noticed.
--
https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion/+merge/45210
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/bpb-currentcomponent-assertion into lp:launchpad.
=== removed file 'lib/lp/soyuz/browser/tests/build-views.txt'
--- lib/lp/soyuz/browser/tests/build-views.txt 2010-10-18 22:24:59 +0000
+++ lib/lp/soyuz/browser/tests/build-views.txt 1970-01-01 00:00:00 +0000
@@ -1,430 +0,0 @@
-= Build Pages =
-
-For the subsequent tests we will use a specific 'pmount' build record
-from the sampledata which happens to be in FAILEDTOBUILD status.
-
- >>> from zope.component import getUtility
- >>> from lp.buildmaster.enums import BuildStatus
- >>> from lp.registry.interfaces.distribution import IDistributionSet
-
- >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
- >>> hoary = ubuntu.getSeries('hoary')
- >>> hoary_pmount = hoary.getSourcePackage('pmount')
-
- >>> hoary_failed_build = hoary_pmount.getBuildRecords(
- ... build_state=BuildStatus.FAILEDTOBUILD)[0]
-
-
-== Build Menu ==
-
-The menu presented in the build page depends on the targeted archive.
-For instance the 'PPA' action-menu link is not enabled for builds
-targeted to the PRIMARY archive.
-
- >>> from lp.soyuz.browser.build import BuildContextMenu
- >>> build_menu = BuildContextMenu(hoary_failed_build)
-
- >>> print build_menu.links
- ['ppa', 'records', 'retry', 'rescore']
-
- >>> build_menu.is_ppa_build
- False
-
- >>> build_menu.ppa().enabled
- False
-
-The 'PPA' action-menu item will be enabled if we target the build to
-Celso's PPA.
-
- >>> from lp.registry.interfaces.person import IPersonSet
-
- >>> cprov = getUtility(IPersonSet).getByName('cprov')
- >>> cprov_failed_build = cprov.archive.getBuildRecords(
- ... build_state=BuildStatus.FAILEDTOBUILD)[0]
-
- >>> build_menu = BuildContextMenu(cprov_failed_build)
-
- >>> print build_menu.links
- ['ppa', 'records', 'retry', 'rescore']
-
- >>> build_menu.is_ppa_build
- True
-
- >>> build_menu.ppa().enabled
- True
-
-
-== Build +index page ==
-
-Setup an 'empty' request:
-
- >>> from canonical.launchpad.webapp.servers import LaunchpadTestRequest
- >>> empty_request = LaunchpadTestRequest(form={})
-
-Let's instantiate the view for +index:
-
- >>> from zope.component import getMultiAdapter
- >>> hoary_failed_build_view = getMultiAdapter(
- ... (hoary_failed_build, empty_request), name="+index")
-
-`BuildView` has some cached properties that are used multiple times in
-the related templates.
-
- >>> print hoary_failed_build_view.is_ppa
- False
-
- >>> print hoary_failed_build_view.buildqueue
- None
-
- >>> print hoary_failed_build_view.component.name
- main
-
-'BuildView.user_can_retry_build' property checks not only the
-user's permissions to retry but also if a build is in a status that it
-can be retried.
-
-The build cannot be retried (see IBuild) because it's targeted to a
-stable distroseries.
-
- >>> hoary_failed_build.can_be_retried
- False
-
- >>> hoary_failed_build_view.user_can_retry_build
- False
-
-The Celso's PPA failed-to-build build record can be retried, since PPA
-distroseries never freeze.
-
- >>> cprov_failed_build.can_be_retried
- True
-
-While the build is now in a state to be rebuilt, the view property
-still checks to ensure the user has the proper permission. Anonymous
-users, obviously, don't have 'launchpad.Edit' permission on this
-build.
-
- >>> cprov_failed_build_view = getMultiAdapter(
- ... (cprov_failed_build, empty_request), name="+index")
-
- >>> cprov_failed_build_view.user_can_retry_build
- False
-
-If accessed by an user with the required permission, Foo Bar in this
-case, the 'user_can_retry_build' property finally returns True.
-
- >>> login("foo.bar@xxxxxxxxxxxxx")
-
- >>> cprov_failed_build_view = getMultiAdapter(
- ... (cprov_failed_build, empty_request), name="+index")
-
- >>> cprov_failed_build_view.user_can_retry_build
- True
-
-Buildd admins can retry any build as long is it's in a state that
-permits it to be re-tried. FAILEDTOBUILD is one of those states:
-
- >>> from lp.soyuz.tests.test_publishing import (
- ... SoyuzTestPublisher)
- >>> from lp.soyuz.enums import (
- ... PackagePublishingStatus)
- >>> test_publisher = SoyuzTestPublisher()
- >>> test_publisher.prepareBreezyAutotest()
- >>> test_source = test_publisher.getPubSource(
- ... status=PackagePublishingStatus.PUBLISHED,
- ... sourcename='sourceone')
- >>> [failed_build] = test_source.createMissingBuilds()
- >>> failed_build.status = BuildStatus.FAILEDTOBUILD
-
- >>> failed_build.can_be_retried
- True
-
-Mr "no privileges" has no rights to retry the build:
-
- >>> login("no-priv@xxxxxxxxxxxxx")
- >>> failed_build_view = getMultiAdapter(
- ... (failed_build, empty_request), name="+index")
- >>> failed_build_view.user_can_retry_build
- False
-
-If he is put in the buildd-admins group, however, he is now able to
-retry it.
-
- >>> buildd_admins = getUtility(IPersonSet).getByName(
- ... "launchpad-buildd-admins")
- >>> nopriv = getUtility(IPersonSet).getByName("no-priv")
- >>> login("foo.bar@xxxxxxxxxxxxx")
- >>> ignored = buildd_admins.addMember(nopriv, nopriv)
-
- >>> login("no-priv@xxxxxxxxxxxxx")
- >>> failed_build_view = getMultiAdapter(
- ... (failed_build, empty_request), name="+index")
- >>> failed_build_view.user_can_retry_build
- True
-
-A person in a team that has rights to upload to a packageset can also retry it.
-
-So, create a user, a team, and the packageset:
-
- >>> login('admin@xxxxxxxxxxxxx')
- >>> from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
- >>> from lp.soyuz.interfaces.packageset import IPackagesetSet
- >>> joe = factory.makePerson(email='joe@xxxxxxxxxxx', password='test')
- >>> desktop = factory.makeTeam(name='desktop', owner=joe)
- >>> main_archive = test_publisher.distroseries.main_archive
- >>> rebuild_ps = getUtility(IPackagesetSet).new(
- ... u'rebuild', u'Test package set', desktop,
- ... distroseries=test_publisher.distroseries)
- >>> rebuild_spn = (failed_build.source_package_release.sourcepackagename,)
- >>> rebuild_ps.add(rebuild_spn)
-
-Joe will not have permission to retry the build until we grant it:
-
- >>> login('joe@xxxxxxxxxxx')
- >>> failed_build_view = getMultiAdapter(
- ... (failed_build, empty_request), name="+index")
- >>> failed_build_view.user_can_retry_build
- False
- >>> login('admin@xxxxxxxxxxxxx')
- >>> perms = getUtility(IArchivePermissionSet).newPackagesetUploader(
- ... main_archive, desktop, rebuild_ps)
- >>> login('joe@xxxxxxxxxxx')
- >>> failed_build_view = getMultiAdapter(
- ... (failed_build, empty_request), name="+index")
- >>> failed_build_view.user_can_retry_build
- True
-
-See pagetests/soyuz/xx-build-record.txt for further information about
-the build-retry permission system.
-
-`BuildView.package_upload` returns the cached `PackageUpload` record
-corresponding to this build. It's None if the binaries for a build were
-not yet collected.
-
- >>> print cprov_failed_build_view.package_upload
- None
-
-Automatically, 'BuildView.has_published_binaries' reflects this condition.
-
- >>> print cprov_failed_build_view.has_published_binaries
- False
-
-First let's create a package upload for this build:
-XXX: noodles 2009-01-16 bug 317863: move this into the STP.
-
- >>> from lp.registry.interfaces.pocket import (
- ... PackagePublishingPocket)
- >>> from lp.soyuz.model.queue import PackageUploadBuild
- >>> build = cprov_failed_build_view.context
- >>> package_upload = build.distro_series.createQueueEntry(
- ... PackagePublishingPocket.UPDATES, 'changes.txt', 'my changes',
- ... build.archive)
- >>> package_upload_build = PackageUploadBuild(
- ... packageupload =package_upload,
- ... build=cprov_failed_build_view.context)
- >>> print package_upload.status.name
- NEW
-
-Now, our build has a package upload and its status is
-NEW. 'has_published_binaries' remains False.
-
- >>> cprov_failed_build_view = create_initialized_view(
- ... cprov_failed_build, '+index')
-
- >>> print cprov_failed_build_view.package_upload.status.name
- NEW
-
- >>> print cprov_failed_build_view.has_published_binaries
- False
-
-The view 'package_upload' is still available after it has been
-accepted and processed. Afterwards 'has_published_binaries' becomes
-True.
-
- >>> login('foo.bar@xxxxxxxxxxxxx')
- >>> package_upload.setDone()
- >>> login("no-priv@xxxxxxxxxxxxx")
-
- >>> cprov_failed_build_view = create_initialized_view(
- ... cprov_failed_build, '+index')
-
- >>> print cprov_failed_build_view.package_upload.status.name
- DONE
-
- >>> print cprov_failed_build_view.has_published_binaries
- True
-
-The BuildIndex view also has a files helper which returns
-all the files from the related binary package releases.
-
- >>> hoary_pmount_build = hoary.getBuildRecords(
- ... build_state=BuildStatus.FULLYBUILT, name='pmount',
- ... arch_tag='hppa')[0]
- >>> hoary_pmount_build_view = create_initialized_view(
- ... hoary_pmount_build, '+index')
- >>> len(hoary_pmount_build_view.files)
- 1
- >>> deb_file = hoary_pmount_build_view.files[0]
- >>> print deb_file.filename
- pmount_1.9-1_all.deb
-
-Files that are still referenced by binary package releases but have
-been deleted will not be included in the view's files.
-
- >>> deb_file.deleted
- False
- >>> from zope.security.proxy import removeSecurityProxy
- >>> removeSecurityProxy(deb_file.context).content = None
- >>> deb_file.deleted
- True
-
- >>> hoary_pmount_build_view = create_initialized_view(
- ... hoary_pmount_build, '+index')
- >>> len(hoary_pmount_build_view.files)
- 0
-
-
-== BuildRescoringView ==
-
-`BuildRescoringView` is used for setting new values to the
-corresponding `BuildQueue.lastscore` record for a `Build`.
-
-It redirects users to the `Build` page when the build cannot be
-rescored.
-
- >>> print cprov_failed_build.can_be_rescored
- False
-
- >>> view = create_initialized_view(
- ... cprov_failed_build, name="+rescore")
-
- >>> view.request.response.getStatus()
- 302
- >>> print view.request.response.getHeader('Location')
- http://launchpad.dev/~cprov/+archive/ppa/+build/26
-
-Canceled 'Rescore' form redirects users back to the Build page.
-
- # Fetch an PENDING build from the sampledata.
- >>> pending_build = ubuntu.getBuildRecords(
- ... build_state=BuildStatus.NEEDSBUILD)[0]
-
- >>> view = create_initialized_view(
- ... pending_build, name="+rescore")
-
- >>> print view.cancel_url
- http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+build/11
-
-The 'priority' field only accepts long integer values.
-
- >>> view = create_initialized_view(
- ... pending_build, name="+rescore", form={
- ... 'field.priority': str(2 ** 31 + 1),
- ... 'field.actions.rescore': 'Rescore',
- ... })
-
- >>> for error in view.errors:
- ... print '%s -> %s' % (error.widget_title, error.doc())
- Priority -> Value is too big
-
- >>> view = create_initialized_view(
- ... pending_build, name="+rescore", form={
- ... 'field.priority': '-' + str(2 ** 31 + 1),
- ... 'field.actions.rescore': 'Rescore',
- ... })
-
- >>> for error in view.errors:
- ... print '%s -> %s' % (error.widget_title, error.doc())
- Priority -> Value is too small
-
-Submitting valid values will update the build 'score' and redirect
-users to the build page with an appropriate notification.
-
- >>> print pending_build.buildqueue_record.lastscore
- 10
-
- >>> view = create_initialized_view(
- ... pending_build, name="+rescore", form={
- ... 'field.priority': '0',
- ... 'field.actions.rescore': 'Rescore',
- ... })
-
- >>> view.request.response.getStatus()
- 302
- >>> print view.request.response.getHeader('Location')
- http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+build/11
-
- >>> for notification in view.request.response.notifications:
- ... print notification.message
- Build rescored to 0.
-
- >>> print pending_build.buildqueue_record.lastscore
- 0
-
-
-== BuildRecordsView ==
-
-The BuildRecordsView can also be used to filter by architecture tag.
-
- >>> view = create_initialized_view(
- ... hoary, name="+builds", form={'build_state': 'all'})
- >>> view.setupBuildList()
- >>> for build in view.complete_builds:
- ... print build.arch_tag
- i386
- ...
- hppa
- ...
-
- >>> view = create_initialized_view(
- ... hoary, name="+builds", form={
- ... 'build_state': 'all',
- ... 'arch_tag': 'hppa',
- ... })
- >>> view.setupBuildList()
- >>> for build in view.complete_builds:
- ... print build.arch_tag
- hppa
-
-The architecture_options property iterates through the available
-architectures of the context constructing a distinct, sorted list
-of options for the template.
-
- >>> view = create_initialized_view(
- ... ubuntu, name="+builds", form={
- ... 'build_state': 'all',
- ... 'arch_tag': 'hppa',
- ... })
- >>> for option in view.architecture_options:
- ... option_str = option['name']
- ... if option['selected'] is not None:
- ... option_str += " (selected)"
- ... print option_str
- All architectures
- hppa (selected)
- i386
-
-
-== Dispatch time estimates ==
-
-A dispatch time estimate is available for pending binary builds that have not
-been suspended.
-
- >>> from lp.services.job.interfaces.job import JobStatus
- >>> pending_build = ubuntu.getBuildRecords(
- ... build_state=BuildStatus.NEEDSBUILD)[0]
-
- >>> view = create_initialized_view(pending_build, name="+index")
- >>> view.dispatch_time_estimate_available
- True
- >>> view.context.status == BuildStatus.NEEDSBUILD
- True
- >>> view.context.buildqueue_record.job.status == JobStatus.WAITING
- True
-
-If we suspend the binary build job, however, no estimate is available.
-
- >>> view.context.buildqueue_record.job.suspend()
- >>> view.context.buildqueue_record.job.status == JobStatus.SUSPENDED
- True
- >>> view.dispatch_time_estimate_available
- False
=== added file 'lib/lp/soyuz/browser/tests/test_build_views.py'
--- lib/lp/soyuz/browser/tests/test_build_views.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/browser/tests/test_build_views.py 2011-01-05 07:44:36 +0000
@@ -0,0 +1,283 @@
+# Copyright 2011 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+from datetime import (
+ datetime,
+ timedelta,
+ )
+import pytz
+from zope.component import (
+ getMultiAdapter,
+ getUtility,
+ )
+from zope.security.proxy import removeSecurityProxy
+
+from canonical.launchpad.webapp import canonical_url
+from canonical.launchpad.webapp.servers import LaunchpadTestRequest
+from canonical.testing.layers import LaunchpadFunctionalLayer
+from lp.buildmaster.enums import BuildStatus
+from lp.registry.interfaces.person import IPersonSet
+from lp.registry.interfaces.pocket import PackagePublishingPocket
+from lp.registry.interfaces.series import SeriesStatus
+from lp.services.job.interfaces.job import JobStatus
+from lp.soyuz.browser.build import BuildContextMenu
+from lp.soyuz.enums import ArchivePurpose
+from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
+from lp.soyuz.interfaces.packageset import IPackagesetSet
+from lp.soyuz.model.queue import PackageUploadBuild
+from lp.testing import (
+ person_logged_in,
+ TestCaseWithFactory,
+ )
+from lp.testing.sampledata import ADMIN_EMAIL
+from lp.testing.views import create_initialized_view
+
+
+class TestBuildViews(TestCaseWithFactory):
+
+ layer = LaunchpadFunctionalLayer
+
+ def setUp(self):
+ super(TestBuildViews, self).setUp()
+ self.empty_request = LaunchpadTestRequest(form={})
+ self.admin = getUtility(IPersonSet).getByEmail(ADMIN_EMAIL)
+
+ def assertBuildViewRetryIsExpected(self, build, person, expected):
+ with person_logged_in(person):
+ build_view = getMultiAdapter(
+ (build, self.empty_request), name="+index")
+ self.assertEquals(build_view.user_can_retry_build, expected)
+
+ def test_build_menu_primary(self):
+ # The menu presented in the build page depends on the targeted
+ # archive. For instance the 'PPA' action-menu link is not enabled
+ # for builds targeted to the PRIMARY archive.
+ archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
+ build = self.factory.makeBinaryPackageBuild(archive=archive)
+ build_menu = BuildContextMenu(build)
+ self.assertEquals(build_menu.links,
+ ['ppa', 'records', 'retry', 'rescore'])
+ self.assertFalse(build_menu.is_ppa_build)
+ self.assertFalse(build_menu.ppa().enabled)
+
+ def test_build_menu_ppa(self):
+ # The 'PPA' action-menu item will be enabled if we target the build
+ # to a PPA.
+ build = self.factory.makeBinaryPackageBuild()
+ build_menu = BuildContextMenu(build)
+ self.assertEquals(build_menu.links,
+ ['ppa', 'records', 'retry', 'rescore'])
+ self.assertTrue(build_menu.is_ppa_build)
+ self.assertTrue(build_menu.ppa().enabled)
+
+ def test_cannot_retry_stable_distroseries(self):
+ # 'BuildView.user_can_retry_build' property checks not only the
+ # user's permissions to retry but also if a build is in a status
+ # that it can be retried.
+ # The build cannot be retried (see IBuild) because it's targeted to a
+ # released distroseries.
+ archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
+ build = self.factory.makeBinaryPackageBuild(
+ archive=archive, status=BuildStatus.FAILEDTOBUILD)
+ distroseries = build.distro_arch_series.distroseries
+ with person_logged_in(self.admin):
+ distroseries.status = SeriesStatus.CURRENT
+ build_view = getMultiAdapter(
+ (build, self.empty_request), name="+index")
+ self.assertFalse(build_view.is_ppa)
+ self.assertEquals(build_view.buildqueue, None)
+ self.assertEquals(build_view.component.name, 'multiverse')
+ self.assertFalse(build.can_be_retried)
+ self.assertFalse(build_view.user_can_retry_build)
+
+ def test_retry_ppa_builds(self):
+ # PPA builds can always be retried, no matter what status the
+ # distroseries has.
+ build = self.factory.makeBinaryPackageBuild(
+ status=BuildStatus.FAILEDTOBUILD)
+ build_view = getMultiAdapter(
+ (build, self.empty_request), name="+index")
+ self.assertTrue(build.can_be_retried)
+ # Anonymous, therefore supposed to be disallowed
+ self.assertFalse(build_view.user_can_retry_build)
+ self.assertBuildViewRetryIsExpected(build, build.archive.owner, True)
+
+ def test_buildd_admins_retry_builds(self):
+ # Buildd admins can retry any build as long is it's in a state that
+ # permits it to be re-tried.
+ archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
+ build = self.factory.makeBinaryPackageBuild(
+ archive=archive, status=BuildStatus.FAILEDTOBUILD)
+ with person_logged_in(self.admin):
+ self.assertTrue(build.can_be_retried)
+ nopriv = getUtility(IPersonSet).getByName("no-priv")
+ # Mr no privledges can't retry
+ self.assertBuildViewRetryIsExpected(build, nopriv, False)
+ # But he can as a member of launchpad-buildd-admins
+ buildd_admins = getUtility(IPersonSet).getByName(
+ "launchpad-buildd-admins")
+ with person_logged_in(self.admin):
+ buildd_admins.addMember(nopriv, nopriv)
+ self.assertBuildViewRetryIsExpected(build, nopriv, True)
+
+ def test_packageset_upload_retry(self):
+ # A person in a team that has rights to upload to a packageset can
+ # also retry failed builds of contained source packages.
+ team = self.factory.makeTeam()
+ archive = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
+ build = self.factory.makeBinaryPackageBuild(
+ archive=archive, status=BuildStatus.FAILEDTOBUILD)
+ with person_logged_in(self.admin):
+ packageset = getUtility(IPackagesetSet).new(
+ u'rebuild', u'test', team,
+ distroseries=build.distro_arch_series.distroseries)
+ packageset.add((build.source_package_release.sourcepackagename,))
+ # The team doesn't have permission until we grant it
+ self.assertBuildViewRetryIsExpected(build, team.teamowner, False)
+ with person_logged_in(self.admin):
+ getUtility(IArchivePermissionSet).newPackagesetUploader(
+ archive, team, packageset)
+ self.assertBuildViewRetryIsExpected(build, team.teamowner, True)
+
+ def test_build_view_package_upload(self):
+ # `BuildView.package_upload` returns the cached `PackageUpload`
+ # record corresponding to this build. It's None if the binaries for
+ # a build were not yet collected.
+ build = self.factory.makeBinaryPackageBuild()
+ build_view = getMultiAdapter(
+ (build, self.empty_request), name="+index")
+ self.assertEquals(build_view.package_upload, None)
+ self.assertFalse(build_view.has_published_binaries)
+ package_upload = build.distro_series.createQueueEntry(
+ PackagePublishingPocket.UPDATES, 'changes.txt', 'my changes',
+ build.archive)
+ package_upload_build = PackageUploadBuild(
+ packageupload =package_upload, build=build)
+ self.assertEquals(package_upload.status.name, 'NEW')
+ build_view = getMultiAdapter(
+ (build, self.empty_request), name="+index")
+ self.assertEquals(build_view.package_upload.status.name, 'NEW')
+ self.assertFalse(build_view.has_published_binaries)
+ with person_logged_in(self.admin):
+ package_upload.setDone()
+ build_view = getMultiAdapter(
+ (build, self.empty_request), name="+index")
+ self.assertEquals(build_view.package_upload.status.name, 'DONE')
+ self.assertTrue(build_view.has_published_binaries)
+
+ def test_build_view_files_helper(self):
+ # The BuildIndex view also has a files helper which returns
+ # all the files from the related binary package releases.
+ build = self.factory.makeBinaryPackageBuild(
+ status=BuildStatus.FULLYBUILT)
+ bpr = self.factory.makeBinaryPackageRelease(build=build)
+ bprf = self.factory.makeBinaryPackageFile(binarypackagerelease=bpr)
+ build_view = create_initialized_view(build, '+index')
+ deb_file = build_view.files[0]
+ self.assertEquals(deb_file.filename, bprf.libraryfile.filename)
+ # Deleted files won't be included
+ self.assertFalse(deb_file.deleted)
+ removeSecurityProxy(deb_file.context).content = None
+ self.assertTrue(deb_file.deleted)
+ build_view = create_initialized_view(build, '+index')
+ self.assertEquals(len(build_view.files), 0)
+
+ def test_build_rescoring_view(self):
+ # `BuildRescoringView` is used for setting new values to the
+ # corresponding `BuildQueue.lastscore` record for a `Build`.
+ # It redirects users to the `Build` page when the build cannot be
+ # rescored.
+ build = self.factory.makeBinaryPackageBuild(
+ status=BuildStatus.FAILEDTOBUILD)
+ self.assertFalse(build.can_be_rescored)
+ view = create_initialized_view(build, name='+rescore')
+ self.assertEquals(view.request.response.getStatus(), 302)
+ self.assertEquals(view.request.response.getHeader('Location'),
+ canonical_url(build))
+ pending_build = self.factory.makeBinaryPackageBuild()
+ view = create_initialized_view(pending_build, name='+rescore')
+ self.assertEquals(view.cancel_url, canonical_url(pending_build))
+
+ def test_rescore_value_too_large(self):
+ build = self.factory.makeBinaryPackageBuild()
+ view = create_initialized_view(
+ build, name="+rescore", form={
+ 'field.priority': str(2 ** 31 + 1),
+ 'field.actions.rescore': 'Rescore'})
+ self.assertEquals(view.errors[0].widget_title, "Priority")
+ self.assertEquals(view.errors[0].doc(), "Value is too big")
+
+ def test_rescore_value_too_small(self):
+ build = self.factory.makeBinaryPackageBuild()
+ view = create_initialized_view(
+ build, name="+rescore", form={
+ 'field.priority': '-' + str(2 ** 31 + 1),
+ 'field.actions.rescore': 'Rescore'})
+ self.assertEquals(view.errors[0].widget_title, "Priority")
+ self.assertEquals(view.errors[0].doc(), "Value is too small")
+
+ def test_rescore(self):
+ pending_build = self.factory.makeBinaryPackageBuild()
+ pending_build.queueBuild()
+ with person_logged_in(self.admin):
+ view = create_initialized_view(
+ pending_build, name="+rescore", form={
+ 'field.priority': '0',
+ 'field.actions.rescore': 'Rescore'})
+ notification = view.request.response.notifications[0]
+ self.assertEquals(notification.message, "Build rescored to 0.")
+ self.assertEquals(pending_build.buildqueue_record.lastscore, 0)
+
+ def test_build_records_view(self):
+ # The BuildRecordsView can also be used to filter by architecture tag.
+ distroseries = self.factory.makeDistroSeries()
+ arch_list = []
+ for i in range(5):
+ das = self.factory.makeDistroArchSeries(distroseries=distroseries)
+ arch_list.append(das.architecturetag)
+ build = self.factory.makeBinaryPackageBuild(
+ distroarchseries=das, archive=distroseries.main_archive,
+ status=BuildStatus.FULLYBUILT)
+ with person_logged_in(self.admin):
+ build.date_started = (
+ datetime.now(pytz.UTC) - timedelta(hours=1))
+ build.date_finished = datetime.now(pytz.UTC)
+ view = create_initialized_view(
+ distroseries, name="+builds", form={'build_state': 'all'})
+ view.setupBuildList()
+ build_arches = [build.arch_tag for build in view.complete_builds]
+ self.assertEquals(arch_list.sort(), build_arches.sort())
+ view = create_initialized_view(
+ distroseries, name="+builds", form={
+ 'build_state': 'all', 'arch_tag': arch_list[0]})
+ view.setupBuildList()
+ self.assertEquals(len(view.complete_builds), 1)
+ self.assertEquals(view.complete_builds[0].arch_tag, arch_list[0])
+ # There is an extra entry for 'All architectures'
+ self.assertEquals(len(view.architecture_options), len(arch_list) + 1)
+ selected = []
+ option_arches = []
+ for option in view.architecture_options:
+ option_arches.append(option['name'])
+ if option['selected'] is not None:
+ selected.append(option['name'])
+ self.assertEquals(option_arches.sort(), arch_list.sort())
+ self.assertTrue(len(selected), 1)
+ self.assertEquals(selected, [arch_list[0]])
+
+ def test_dispatch_estimate(self):
+ # A dispatch time estimate is available for pending binary builds
+ # that have not been suspended.
+ build = self.factory.makeBinaryPackageBuild()
+ build.queueBuild()
+ view = create_initialized_view(build, name="+index")
+ job = view.context.buildqueue_record.job
+ self.assertTrue(view.dispatch_time_estimate_available)
+ self.assertEquals(view.context.status, BuildStatus.NEEDSBUILD)
+ self.assertEquals(job.status, JobStatus.WAITING)
+ # If we suspend the job, there is no estimate available
+ job.suspend()
+ self.assertEquals(job.status, JobStatus.SUSPENDED)
+ self.assertFalse(view.dispatch_time_estimate_available)
=== modified file 'lib/lp/soyuz/browser/tests/test_builder_views.py'
--- lib/lp/soyuz/browser/tests/test_builder_views.py 2010-10-27 14:25:19 +0000
+++ lib/lp/soyuz/browser/tests/test_builder_views.py 2011-01-05 07:44:36 +0000
@@ -11,6 +11,7 @@
from lp.soyuz.browser.builder import BuilderEditView
from lp.testing import TestCaseWithFactory
from lp.testing.fakemethod import FakeMethod
+from lp.testing.sampledata import ADMIN_EMAIL
class TestBuilderEditView(TestCaseWithFactory):
@@ -21,7 +22,7 @@
super(TestBuilderEditView, self).setUp()
# Login as an admin to ensure access to the view's context
# object.
- login('admin@xxxxxxxxxxxxx')
+ login(ADMIN_EMAIL)
self.builder = removeSecurityProxy(self.factory.makeBuilder())
def initialize_view(self):
=== modified file 'lib/lp/soyuz/model/binarypackagebuild.py'
--- lib/lp/soyuz/model/binarypackagebuild.py 2010-11-11 11:55:53 +0000
+++ lib/lp/soyuz/model/binarypackagebuild.py 2011-01-05 07:44:36 +0000
@@ -941,7 +941,7 @@
def getBuildsByArchIds(self, distribution, arch_ids, status=None,
name=None, pocket=None):
"""See `IBinaryPackageBuildSet`."""
- # If not distroarchseries was found return empty list
+ # If no distroarchseries were passed in, return an empty list
if not arch_ids:
return EmptyResultSet()