launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #03019
[Merge] lp:~stevenk/launchpad/dsdj-runner into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/dsdj-runner into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/dsdj-runner/+merge/54159
Add "the business end" to DistroSeriesDifferenceJob is the short description.
The longer description is implement a run() method for DSDJ, add a *lot* of tests for it, create a database user, add relevant permissions for it, implement a cronscript that will run said jobs, also create DSDJs when an SPPH is marked for deletion, and perform some clean up.
(Some of the clean up wasn't strictly necessary, but I was the first implementer of DistributionJob, so I still think things should be 'just so'.)
--
https://code.launchpad.net/~stevenk/launchpad/dsdj-runner/+merge/54159
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/dsdj-runner into lp:launchpad.
=== modified file 'configs/development/launchpad-lazr.conf'
--- configs/development/launchpad-lazr.conf 2011-02-25 19:27:05 +0000
+++ configs/development/launchpad-lazr.conf 2011-03-21 07:49:35 +0000
@@ -115,6 +115,10 @@
timeout: 10
cdimage_file_list_url: file:lib/canonical/launchpad/doc/ubuntu-releases.testdata
+[distroseriesdifferencejob]
+oops_prefix: DSDJ
+error_dir: /var/tmp/soyuz.test
+
[error_reports]
oops_prefix: X
error_dir: /var/tmp/lperr
=== added file 'cronscripts/distroseriesdifference_job.py'
--- cronscripts/distroseriesdifference_job.py 1970-01-01 00:00:00 +0000
+++ cronscripts/distroseriesdifference_job.py 2011-03-21 07:49:35 +0000
@@ -0,0 +1,37 @@
+#!/usr/bin/python -S
+#
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Process DistroSeriesDifferences."""
+
+__metaclass__ = type
+
+import _pythonpath
+
+from lp.services.features import getFeatureFlag
+from lp.services.job.runner import JobCronScript
+from lp.soyuz.model.distroseriesdifferencejob import (
+ FEATURE_FLAG_ENABLE_MODULE,
+ )
+from lp.soyuz.interfaces.distributionjob import (
+ IDistroSeriesDifferenceJobSource,
+ )
+
+
+class RunDistroSeriesDifferenceJob(JobCronScript):
+ """Run DistroSeriesDifferenceJob jobs."""
+
+ config_name = 'distroseriesdifferencejob'
+ source_interface = IDistroSeriesDifferenceJobSource
+
+ def main(self):
+ if not getFeatureFlag(FEATURE_FLAG_ENABLE_MODULE):
+ self.logger.info("Feature flag is not enabled.")
+ return
+ super(RunDistroSeriesDifferenceJob, self).main()
+
+
+if __name__ == '__main__':
+ script = RunDistroSeriesDifferenceJob()
+ script.lock_and_run()
=== modified file 'database/schema/security.cfg'
--- database/schema/security.cfg 2011-03-18 03:56:36 +0000
+++ database/schema/security.cfg 2011-03-21 07:49:35 +0000
@@ -1059,6 +1059,21 @@
public.sourcepackagerelease = SELECT
public.sourcepackagereleasefile = SELECT, INSERT, UPDATE
+[distroseriesdifferencejob]
+type=user
+groups=script
+public.archive = SELECT
+public.distribution = SELECT
+public.distributionjob = SELECT
+public.distroseries = SELECT
+public.distroseriesdifference = SELECT, INSERT, UPDATE
+public.job = SELECT, UPDATE
+public.libraryfilealias = SELECT
+public.libraryfilecontent = SELECT
+public.sourcepackagename = SELECT
+public.sourcepackagepublishinghistory = SELECT
+public.sourcepackagerelease = SELECT
+
[write]
type=group
# Full access except for tables that are exclusively updated by
=== modified file 'lib/canonical/config/schema-lazr.conf'
--- lib/canonical/config/schema-lazr.conf 2011-03-07 20:49:03 +0000
+++ lib/canonical/config/schema-lazr.conf 2011-03-21 07:49:35 +0000
@@ -728,6 +728,19 @@
cdimage_file_list_url: http://releases.ubuntu.com/.manifest
+[distroseriesdifferencejob]
+dbuser: distroseriesdifferencejob
+
+# See [error_reports].
+error_dir: none
+
+# See [error_reports].
+oops_prefix: none
+
+# See [error_reports].
+copy_to_zlog: false
+
+
[error_reports]
# A prefix for "OOPS" codes for this process instance.
# This is used to allow storing the reports from different
=== modified file 'lib/lp/soyuz/configure.zcml'
--- lib/lp/soyuz/configure.zcml 2011-03-10 14:05:51 +0000
+++ lib/lp/soyuz/configure.zcml 2011-03-21 07:49:35 +0000
@@ -901,14 +901,15 @@
</class>
<!-- DistroSeriesDifferenceJobSource -->
+ <securedutility
+ component="lp.soyuz.model.distroseriesdifferencejob.DistroSeriesDifferenceJob"
+ provides="lp.soyuz.interfaces.distributionjob.IDistroSeriesDifferenceJobSource">
+ <allow interface="lp.soyuz.interfaces.distributionjob.IDistroSeriesDifferenceJobSource"/>
+ </securedutility>
<class class="lp.soyuz.model.distroseriesdifferencejob.DistroSeriesDifferenceJob">
+ <allow interface="lp.soyuz.interfaces.distributionjob.IDistroSeriesDifferenceJob" />
<allow interface="lp.soyuz.interfaces.distributionjob.IDistributionJob" />
</class>
- <securedutility
- component="lp.soyuz.model.distroseriesdifferencejob.DistroSeriesDifferenceJob"
- provides="lp.soyuz.interfaces.distroseriesdifferencejob.IDistroSeriesDifferenceJobSource">
- <allow interface="lp.soyuz.interfaces.distroseriesdifferencejob.IDistroSeriesDifferenceJobSource"/>
- </securedutility>
<!-- SyncPackageJobSource -->
<securedutility
=== modified file 'lib/lp/soyuz/interfaces/distributionjob.py'
--- lib/lp/soyuz/interfaces/distributionjob.py 2011-03-10 14:05:51 +0000
+++ lib/lp/soyuz/interfaces/distributionjob.py 2011-03-21 07:49:35 +0000
@@ -6,6 +6,8 @@
__all__ = [
"DistributionJobType",
"IDistributionJob",
+ "IDistroSeriesDifferenceJob",
+ "IDistroSeriesDifferenceJobSource",
"IInitialiseDistroSeriesJob",
"IInitialiseDistroSeriesJobSource",
"ISyncPackageJob",
@@ -133,3 +135,20 @@
include_binaries = Bool(
title=_("Copy binaries"),
required=False, readonly=True)
+
+
+class IDistroSeriesDifferenceJob(IRunnableJob):
+ """A Job that performs actions related to DSDs."""
+
+
+class IDistroSeriesDifferenceJobSource(IJobSource):
+ """An `IJob` for creating `DistroSeriesDifference`s."""
+
+ def createForPackagePublication(distroseries, sourcepackagename):
+ """Create jobs as appropriate for a given status publication.
+
+ :param distroseries: A `DistroSeries` that is assumed to be
+ derived from another one.
+ :param sourcepackagename: A `SourcePackageName` that is being
+ published in `distroseries`.
+ """
=== removed file 'lib/lp/soyuz/interfaces/distroseriesdifferencejob.py'
--- lib/lp/soyuz/interfaces/distroseriesdifferencejob.py 2011-03-10 14:05:51 +0000
+++ lib/lp/soyuz/interfaces/distroseriesdifferencejob.py 1970-01-01 00:00:00 +0000
@@ -1,24 +0,0 @@
-# Copyright 2011 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""`IDistroSeriesDifferenceJob`."""
-
-__metaclass__ = type
-__all__ = [
- 'IDistroSeriesDifferenceJobSource',
- ]
-
-from lp.services.job.interfaces.job import IJobSource
-
-
-class IDistroSeriesDifferenceJobSource(IJobSource):
- """An `IJob` for creating `DistroSeriesDifference`s."""
-
- def createForPackagePublication(distroseries, sourcepackagename):
- """Create jobs as appropriate for a given status publication.
-
- :param distroseries: A `DistroSeries` that is assumed to be
- derived from another one.
- :param sourcepackagename: A `SourcePackageName` that is being
- published in `distroseries`.
- """
=== modified file 'lib/lp/soyuz/model/distroseriesdifferencejob.py'
--- lib/lp/soyuz/model/distroseriesdifferencejob.py 2011-03-11 13:35:48 +0000
+++ lib/lp/soyuz/model/distroseriesdifferencejob.py 2011-03-21 07:49:35 +0000
@@ -8,25 +8,29 @@
'DistroSeriesDifferenceJob',
]
+from zope.component import getUtility
from zope.interface import (
classProvides,
implements,
)
from canonical.launchpad.interfaces.lpstorm import IMasterStore
+from lp.registry.interfaces.distroseriesdifference import (
+ IDistroSeriesDifferenceSource,
+ )
+from lp.registry.model.distroseriesdifference import DistroSeriesDifference
+from lp.registry.model.sourcepackagename import SourcePackageName
from lp.services.features import getFeatureFlag
from lp.services.job.model.job import Job
from lp.soyuz.interfaces.distributionjob import (
DistributionJobType,
- IDistributionJob,
+ IDistroSeriesDifferenceJob,
+ IDistroSeriesDifferenceJobSource,
)
from lp.soyuz.model.distributionjob import (
DistributionJob,
DistributionJobDerived,
)
-from lp.soyuz.interfaces.distroseriesdifferencejob import (
- IDistroSeriesDifferenceJobSource,
- )
FEATURE_FLAG_ENABLE_MODULE = u"soyuz.derived_series_jobs.enabled"
@@ -98,7 +102,7 @@
class DistroSeriesDifferenceJob(DistributionJobDerived):
"""A `Job` type for creating/updating `DistroSeriesDifference`s."""
- implements(IDistributionJob)
+ implements(IDistroSeriesDifferenceJob)
classProvides(IDistroSeriesDifferenceJobSource)
class_job_type = DistributionJobType.DISTROSERIESDIFFERENCE
@@ -108,12 +112,27 @@
"""See `IDistroSeriesDifferenceJobSource`."""
if not getFeatureFlag(FEATURE_FLAG_ENABLE_MODULE):
return
- children = distroseries.getDerivedSeries()
- parent = distroseries.parent_series
- for relative in list(children) + [parent]:
+ jobs = []
+ children = list(distroseries.getDerivedSeries())
+ for relative in children + [distroseries]:
if may_require_job(relative, sourcepackagename):
- create_job(relative, sourcepackagename)
+ jobs.append(create_job(relative, sourcepackagename))
+ return jobs
+
+ @property
+ def sourcepackagename(self):
+ return SourcePackageName.get(self.metadata['sourcepackagename'])
def run(self):
"""See `IRunnableJob`."""
-# TODO: Implement the business end.
+ store = IMasterStore(DistroSeriesDifference)
+ ds_diff = store.find(
+ DistroSeriesDifference,
+ DistroSeriesDifference.derived_series == self.distroseries,
+ DistroSeriesDifference.source_package_name ==
+ self.sourcepackagename).one()
+ if ds_diff is None:
+ ds_diff = getUtility(IDistroSeriesDifferenceSource).new(
+ self.distroseries, self.sourcepackagename)
+ else:
+ ds_diff.update()
=== modified file 'lib/lp/soyuz/model/publishing.py'
--- lib/lp/soyuz/model/publishing.py 2011-03-10 14:05:51 +0000
+++ lib/lp/soyuz/model/publishing.py 2011-03-21 07:49:35 +0000
@@ -85,7 +85,7 @@
BuildSetStatus,
IBinaryPackageBuildSet,
)
-from lp.soyuz.interfaces.distroseriesdifferencejob import (
+from lp.soyuz.interfaces.distributionjob import (
IDistroSeriesDifferenceJobSource,
)
from lp.soyuz.interfaces.publishing import (
@@ -336,6 +336,9 @@
self.datesuperseded = UTC_NOW
self.removed_by = removed_by
self.removal_comment = removal_comment
+ dsd_job_source = getUtility(IDistroSeriesDifferenceJobSource)
+ dsd_job_source.createForPackagePublication(
+ self.distroseries, self.sourcepackagerelease.sourcepackagename)
def requestObsolescence(self):
"""See `IArchivePublisher`."""
=== modified file 'lib/lp/soyuz/tests/test_distroseriesdifferencejob.py'
--- lib/lp/soyuz/tests/test_distroseriesdifferencejob.py 2011-03-11 13:35:48 +0000
+++ lib/lp/soyuz/tests/test_distroseriesdifferencejob.py 2011-03-21 07:49:35 +0000
@@ -5,28 +5,43 @@
__metaclass__ = type
+import os
+import subprocess
+import sys
import transaction
from psycopg2 import ProgrammingError
from zope.component import getUtility
from zope.interface.verify import verifyObject
+from canonical.config import config
+from canonical.launchpad.interfaces.lpstorm import IMasterStore
from canonical.testing.layers import (
LaunchpadZopelessLayer,
ZopelessDatabaseLayer,
)
+from lp.registry.enum import (
+ DistroSeriesDifferenceStatus,
+ DistroSeriesDifferenceType,
+ )
+from lp.registry.model.distroseriesdifference import DistroSeriesDifference
from lp.services.features.testing import FeatureFixture
from lp.services.job.interfaces.job import JobStatus
-from lp.soyuz.interfaces.distroseriesdifferencejob import (
+from lp.soyuz.enums import PackagePublishingStatus
+from lp.soyuz.interfaces.distributionjob import (
IDistroSeriesDifferenceJobSource,
)
from lp.soyuz.model.distroseriesdifferencejob import (
create_job,
+ DistroSeriesDifferenceJob,
FEATURE_FLAG_ENABLE_MODULE,
find_waiting_jobs,
make_metadata,
may_require_job,
)
-from lp.testing import TestCaseWithFactory
+from lp.testing import (
+ person_logged_in,
+ TestCaseWithFactory,
+ )
class TestDistroSeriesDifferenceJobSource(TestCaseWithFactory):
@@ -110,7 +125,7 @@
sourcepackage = self.factory.makeSourcePackage()
distroseries, sourcepackagename = (
sourcepackage.distroseries, sourcepackage.distroseries)
- job = create_job(distroseries, sourcepackagename)
+ create_job(distroseries, sourcepackagename)
other_series = self.factory.makeDistroSeries()
self.assertContentEqual(
[], find_waiting_jobs(other_series, sourcepackagename))
@@ -119,7 +134,7 @@
sourcepackage = self.factory.makeSourcePackage()
distroseries, sourcepackagename = (
sourcepackage.distroseries, sourcepackage.distroseries)
- job = create_job(distroseries, sourcepackagename)
+ create_job(distroseries, sourcepackagename)
other_spn = self.factory.makeSourcePackageName()
self.assertContentEqual(
[], find_waiting_jobs(distroseries, other_spn))
@@ -136,22 +151,31 @@
self.assertContentEqual(
[], find_waiting_jobs(distroseries, sourcepackagename))
- def test_createForPackagedPublication_creates_job_for_parent_series(self):
+ def test_createForPackagedPublication_creates_jobs_for_its_child(self):
derived_series = self.factory.makeDistroSeries(
parent_series=self.makeDerivedDistroSeries())
package = self.factory.makeSourcePackageName()
+ # Create a job for the derived_series parent, which should create
+ # two jobs. One for derived_series, and the other for its child.
self.getJobSource().createForPackagePublication(
- derived_series, package)
- jobs = list(find_waiting_jobs(derived_series.parent_series, package))
- self.assertEqual(1, len(jobs))
+ derived_series.parent_series, package)
+ jobs = (list(
+ find_waiting_jobs(derived_series.parent_series, package)) +
+ list(find_waiting_jobs(derived_series, package)))
+ self.assertEqual(2, len(jobs))
self.assertEqual(package.id, jobs[0].metadata['sourcepackagename'])
+ self.assertEqual(package.id, jobs[1].metadata['sourcepackagename'])
+ # Lastly, a job was not created for the grandparent.
+ jobs = list(
+ find_waiting_jobs(derived_series.parent_series.parent_series,
+ package))
+ self.assertEqual(0, len(jobs))
def test_createForPackagePublication_creates_job_for_derived_series(self):
derived_series = self.makeDerivedDistroSeries()
- parent_series = derived_series.parent_series
package = self.factory.makeSourcePackageName()
self.getJobSource().createForPackagePublication(
- parent_series, package)
+ derived_series, package)
jobs = list(find_waiting_jobs(derived_series, package))
self.assertEqual(1, len(jobs))
self.assertEqual(package.id, jobs[0].metadata['sourcepackagename'])
@@ -163,6 +187,246 @@
self.getJobSource().createForPackagePublication(distroseries, package)
self.assertContentEqual([], find_waiting_jobs(distroseries, package))
+ def test_cronscript(self):
+ derived_series = self.makeDerivedDistroSeries()
+ package = self.factory.makeSourcePackageName()
+ self.getJobSource().createForPackagePublication(
+ derived_series, package)
+ transaction.commit() # The cronscript is a different process.
+ script = os.path.join(
+ config.root, 'cronscripts', 'distroseriesdifference_job.py')
+ args = [sys.executable, script, '-v']
+ process = subprocess.Popen(
+ args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = process.communicate()
+ # The cronscript ran how we expected it to.
+ self.assertEqual(process.returncode, 0)
+ self.assertIn(
+ 'INFO Ran 1 DistroSeriesDifferenceJob jobs.', stderr)
+ # And it did what we expected.
+ jobs = list(find_waiting_jobs(derived_series, package))
+ self.assertEqual(0, len(jobs))
+ store = IMasterStore(DistroSeriesDifference)
+ ds_diff = store.find(
+ DistroSeriesDifference,
+ DistroSeriesDifference.derived_series == derived_series,
+ DistroSeriesDifference.source_package_name == package)
+ self.assertEqual(1, ds_diff.count())
+
+ def test_job_runner_does_not_create_multiple_dsds(self):
+ derived_series = self.makeDerivedDistroSeries()
+ package = self.factory.makeSourcePackageName()
+ job = self.getJobSource().createForPackagePublication(
+ derived_series, package)
+ job[0].start()
+ job[0].run()
+ job[0].job.complete() # So we can create another job.
+ # The first job would have created a DSD for us.
+ store = IMasterStore(DistroSeriesDifference)
+ ds_diff = store.find(
+ DistroSeriesDifference,
+ DistroSeriesDifference.derived_series == derived_series,
+ DistroSeriesDifference.source_package_name == package)
+ self.assertEqual(1, ds_diff.count())
+ # If we run the job again, it will not create another DSD.
+ job = self.getJobSource().createForPackagePublication(
+ derived_series, package)
+ job[0].start()
+ job[0].run()
+ ds_diff = store.find(
+ DistroSeriesDifference,
+ DistroSeriesDifference.derived_series == derived_series,
+ DistroSeriesDifference.source_package_name == package)
+ self.assertEqual(1, ds_diff.count())
+
+class TestDistroSeriesDifferenceJobEndToEnd(TestCaseWithFactory):
+
+ layer = LaunchpadZopelessLayer
+
+ def setUp(self):
+ super(TestDistroSeriesDifferenceJobEndToEnd, self).setUp()
+ self.useFixture(FeatureFixture({FEATURE_FLAG_ENABLE_MODULE: u'on'}))
+ self.store = IMasterStore(DistroSeriesDifference)
+
+ def getJobSource(self):
+ return getUtility(IDistroSeriesDifferenceJobSource)
+
+ def makeDerivedDistroSeries(self):
+ return self.factory.makeDistroSeries(
+ parent_series=self.factory.makeDistroSeries())
+
+ def createPublication(self, source_package_name, versions, distroseries):
+ changelog_lfa = self.factory.makeChangelog(
+ source_package_name.name, versions)
+ transaction.commit() # Yay, librarian.
+ spr = self.factory.makeSourcePackageRelease(
+ sourcepackagename=source_package_name, version=versions[0],
+ changelog=changelog_lfa)
+ return self.factory.makeSourcePackagePublishingHistory(
+ sourcepackagerelease=spr, archive=distroseries.main_archive,
+ distroseries=distroseries,
+ status=PackagePublishingStatus.PUBLISHED)
+
+ def findDSD(self, derived_series, source_package_name):
+ return self.store.find(
+ DistroSeriesDifference,
+ DistroSeriesDifference.derived_series == derived_series,
+ DistroSeriesDifference.source_package_name ==
+ source_package_name)
+
+ def runJob(self, job):
+ transaction.commit() # Switching DB user performs an abort.
+ self.layer.switchDbUser('distroseriesdifferencejob')
+ dsdjob = DistroSeriesDifferenceJob(job)
+ dsdjob.start()
+ dsdjob.run()
+ dsdjob.complete()
+ transaction.commit() # Switching DB user performs an abort.
+ self.layer.switchDbUser('launchpad')
+
+ def test_parent_gets_newer(self):
+ # When a new source package is uploaded to the parent distroseries,
+ # a job is created that updates the relevant DSD.
+ derived_series = self.makeDerivedDistroSeries()
+ source_package_name = self.factory.makeSourcePackageName()
+ self.createPublication(
+ source_package_name, ['1.0-1derived1', '1.0-1'], derived_series)
+ self.createPublication(
+ source_package_name, ['1.0-1'], derived_series.parent_series)
+ # Creating the SPPHs has created jobs for us, so grab it off the
+ # queue.
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ ds_diff = self.findDSD(derived_series, source_package_name)
+ self.assertEqual(1, ds_diff.count())
+ self.assertEqual('1.0-1', ds_diff[0].parent_source_version)
+ self.assertEqual('1.0-1derived1', ds_diff[0].source_version)
+ self.assertEqual('1.0-1', ds_diff[0].base_version)
+ # Now create a 1.0-2 upload to the parent.
+ self.createPublication(
+ source_package_name, ['1.0-2', '1.0-1'],
+ derived_series.parent_series)
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ # And the DSD we have a hold of will have updated.
+ self.assertEqual('1.0-2', ds_diff[0].parent_source_version)
+ self.assertEqual('1.0-1derived1', ds_diff[0].source_version)
+ self.assertEqual('1.0-1', ds_diff[0].base_version)
+
+ def test_child_gets_newer(self):
+ # When a new source is uploaded to the child distroseries, the DSD is
+ # updated.
+ derived_series = self.makeDerivedDistroSeries()
+ source_package_name = self.factory.makeSourcePackageName()
+ self.createPublication(
+ source_package_name, ['1.0-1'], derived_series)
+ self.createPublication(
+ source_package_name, ['1.0-1'], derived_series.parent_series)
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ ds_diff = self.findDSD(derived_series, source_package_name)
+ self.assertEqual(
+ DistroSeriesDifferenceStatus.RESOLVED, ds_diff[0].status)
+ self.createPublication(
+ source_package_name, ['2.0-0derived1', '1.0-1'], derived_series)
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ self.assertEqual(
+ DistroSeriesDifferenceStatus.NEEDS_ATTENTION, ds_diff[0].status)
+ self.assertEqual('1.0-1', ds_diff[0].base_version)
+
+ def test_child_is_synced(self):
+ # If the source package gets 'synced' to the child from the parent,
+ # the job correctly updates the DSD.
+ derived_series = self.makeDerivedDistroSeries()
+ source_package_name = self.factory.makeSourcePackageName()
+ self.createPublication(
+ source_package_name, ['1.0-1derived1', '1.0-1'], derived_series)
+ self.createPublication(
+ source_package_name, ['1.0-2', '1.0-1'],
+ derived_series.parent_series)
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ ds_diff = self.findDSD(derived_series, source_package_name)
+ self.assertEqual('1.0-1', ds_diff[0].base_version)
+ self.createPublication(
+ source_package_name, ['1.0-2', '1.0-1'], derived_series)
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ self.assertEqual(
+ DistroSeriesDifferenceStatus.RESOLVED, ds_diff[0].status)
+
+ def test_only_in_child(self):
+ # If a source package only exists in the child distroseries, the DSD
+ # is created with the right type.
+ derived_series = self.makeDerivedDistroSeries()
+ source_package_name = self.factory.makeSourcePackageName()
+ self.createPublication(
+ source_package_name, ['1.0-0derived1'], derived_series)
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ ds_diff = self.findDSD(derived_series, source_package_name)
+ self.assertEqual(
+ DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES,
+ ds_diff[0].difference_type)
+
+ def test_only_in_parent(self):
+ # If a source package only exists in the parent distroseries, the DSD
+ # is created with the right type.
+ derived_series = self.makeDerivedDistroSeries()
+ source_package_name = self.factory.makeSourcePackageName()
+ self.createPublication(
+ source_package_name, ['1.0-1'],
+ derived_series.parent_series)
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ ds_diff = self.findDSD(derived_series, source_package_name)
+ self.assertEqual(
+ DistroSeriesDifferenceType.MISSING_FROM_DERIVED_SERIES,
+ ds_diff[0].difference_type)
+
+ def test_deleted_in_parent(self):
+ # If a source package is deleted in the parent, a job is created, and
+ # the DSD is updated correctly.
+ derived_series = self.makeDerivedDistroSeries()
+ source_package_name = self.factory.makeSourcePackageName()
+ self.createPublication(
+ source_package_name, ['1.0-1'], derived_series)
+ spph = self.createPublication(
+ source_package_name, ['1.0-1'], derived_series.parent_series)
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ ds_diff = self.findDSD(derived_series, source_package_name)
+ self.assertEqual(
+ DistroSeriesDifferenceStatus.RESOLVED, ds_diff[0].status)
+ spph.requestDeletion(self.factory.makePerson())
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ self.assertEqual(
+ DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES,
+ ds_diff[0].difference_type)
+
+ def test_deleted_in_child(self):
+ # If a source package is deleted in the child, a job is created, and
+ # the DSD is updated correctly.
+ derived_series = self.makeDerivedDistroSeries()
+ source_package_name = self.factory.makeSourcePackageName()
+ spph = self.createPublication(
+ source_package_name, ['1.0-1'], derived_series)
+ self.createPublication(
+ source_package_name, ['1.0-1'], derived_series.parent_series)
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ ds_diff = self.findDSD(derived_series, source_package_name)
+ self.assertEqual(
+ DistroSeriesDifferenceStatus.RESOLVED, ds_diff[0].status)
+ spph.requestDeletion(self.factory.makePerson())
+ jobs = find_waiting_jobs(derived_series, source_package_name)
+ self.runJob(jobs[0])
+ self.assertEqual(
+ DistroSeriesDifferenceType.MISSING_FROM_DERIVED_SERIES,
+ ds_diff[0].difference_type)
+
class TestDistroSeriesDifferenceJobPermissions(TestCaseWithFactory):
"""Database permissions test for `DistroSeriesDifferenceJob`."""
Follow ups