11
11
from canonical.testing import LaunchpadZopelessLayer
12
12
from lp.registry.interfaces.pocket import PackagePublishingPocket
13
from lp.services.features.testing import FeatureFixture
14
from lp.services.job.interfaces.job import JobStatus
15
from lp.soyuz.enums import (
19
from lp.soyuz.model.distroseriesdifferencejob import (
20
FEATURE_FLAG_ENABLE_MODULE,
13
22
from lp.soyuz.interfaces.archive import CannotCopy
14
from lp.soyuz.interfaces.distributionjob import (
23
from lp.soyuz.interfaces.packagecopyjob import (
16
IPackageCopyJobSource,
25
IPlainPackageCopyJobSource,
18
27
from lp.soyuz.interfaces.publishing import PackagePublishingStatus
28
from lp.soyuz.interfaces.sourcepackageformat import (
29
ISourcePackageFormatSelectionSet,
31
from lp.soyuz.model.packagecopyjob import specify_dsd_package
19
32
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
20
33
from lp.testing import (
26
class PackageCopyJobTests(TestCaseWithFactory):
27
"""Test case for PackageCopyJob."""
39
class PlainPackageCopyJobTests(TestCaseWithFactory):
40
"""Test case for PlainPackageCopyJob."""
29
42
layer = LaunchpadZopelessLayer
44
def makeJob(self, dsd):
45
"""Create a `PlainPackageCopyJob` that would resolve `dsd`."""
46
source_packages = [specify_dsd_package(dsd)]
47
source_archive = dsd.parent_series.main_archive
48
target_archive = dsd.derived_series.main_archive
49
target_distroseries = dsd.derived_series
50
target_pocket = self.factory.getAnyPocket()
51
return getUtility(IPlainPackageCopyJobSource).create(
52
source_packages, source_archive, target_archive,
53
target_distroseries, target_pocket)
55
def runJob(self, job):
56
"""Helper to switch to the right DB user and run the job."""
57
self.layer.txn.commit()
58
self.layer.switchDbUser('sync_packages')
31
61
def test_create(self):
32
62
# A PackageCopyJob can be created and stores its arguments.
33
63
distroseries = self.factory.makeDistroSeries()
34
64
archive1 = self.factory.makeArchive(distroseries.distribution)
35
65
archive2 = self.factory.makeArchive(distroseries.distribution)
36
source = getUtility(IPackageCopyJobSource)
66
source = getUtility(IPlainPackageCopyJobSource)
37
67
job = source.create(
38
68
source_packages=[("foo", "1.0-1"), ("bar", "2.4")],
39
69
source_archive=archive1, target_archive=archive2,
66
95
include_binaries=False)
67
96
self.assertContentEqual([job], source.getActiveJobs(archive2))
98
def test_getActiveJobs_gets_oldest_first(self):
99
# getActiveJobs returns the oldest available job first.
100
dsd = self.factory.makeDistroSeriesDifference()
101
target_archive = dsd.derived_series.main_archive
102
jobs = [self.makeJob(dsd) for counter in xrange(2)]
103
source = getUtility(IPlainPackageCopyJobSource)
104
self.assertEqual(jobs[0], source.getActiveJobs(target_archive)[0])
106
def test_getActiveJobs_only_returns_waiting_jobs(self):
107
# getActiveJobs ignores jobs that aren't in the WAITING state.
108
job = self.makeJob(self.factory.makeDistroSeriesDifference())
109
removeSecurityProxy(job).job._status = JobStatus.RUNNING
110
source = getUtility(IPlainPackageCopyJobSource)
111
self.assertContentEqual([], source.getActiveJobs(job.target_archive))
69
113
def test_run_unknown_package(self):
70
114
# A job properly records failure.
71
115
distroseries = self.factory.makeDistroSeries()
72
116
archive1 = self.factory.makeArchive(distroseries.distribution)
73
117
archive2 = self.factory.makeArchive(distroseries.distribution)
74
source = getUtility(IPackageCopyJobSource)
118
source = getUtility(IPlainPackageCopyJobSource)
75
119
job = source.create(
76
120
source_packages=[("foo", "1.0-1")], source_archive=archive1,
77
121
target_archive=archive2, target_distroseries=distroseries,
78
122
target_pocket=PackagePublishingPocket.RELEASE,
79
123
include_binaries=False)
80
self.assertRaises(CannotCopy, job.run)
124
self.assertRaises(CannotCopy, self.runJob, job)
82
126
def test_target_ppa_non_release_pocket(self):
83
127
# When copying to a PPA archive the target must be the release pocket.
84
128
distroseries = self.factory.makeDistroSeries()
85
129
archive1 = self.factory.makeArchive(distroseries.distribution)
86
130
archive2 = self.factory.makeArchive(distroseries.distribution)
87
source = getUtility(IPackageCopyJobSource)
131
source = getUtility(IPlainPackageCopyJobSource)
88
132
job = source.create(
89
133
source_packages=[], source_archive=archive1,
90
134
target_archive=archive2, target_distroseries=distroseries,
91
135
target_pocket=PackagePublishingPocket.UPDATES,
92
136
include_binaries=False)
93
self.assertRaises(CannotCopy, job.run)
137
self.assertRaises(CannotCopy, self.runJob, job)
95
139
def test_run(self):
96
140
# A proper test run synchronizes packages.
143
self.useFixture(FeatureFixture({FEATURE_FLAG_ENABLE_MODULE: 'on'}))
97
145
publisher = SoyuzTestPublisher()
98
146
publisher.prepareBreezyAutotest()
99
147
distroseries = publisher.breezy_autotest
101
archive1 = self.factory.makeArchive(distroseries.distribution)
102
archive2 = self.factory.makeArchive(distroseries.distribution)
149
# Synchronise from breezy-autotest to a brand new distro derived
151
breezy_archive = self.factory.makeArchive(
152
distroseries.distribution, purpose=ArchivePurpose.PRIMARY)
153
dsp = self.factory.makeDistroSeriesParent(parent_series=distroseries)
154
target_series = dsp.derived_series
155
target_archive = self.factory.makeArchive(
156
target_series.distribution, purpose=ArchivePurpose.PRIMARY)
157
getUtility(ISourcePackageFormatSelectionSet).add(
158
target_series, SourcePackageFormat.FORMAT_1_0)
104
160
source_package = publisher.getPubSource(
105
161
distroseries=distroseries, sourcename="libc",
106
162
version="2.8-1", status=PackagePublishingStatus.PUBLISHED,
163
archive=breezy_archive)
109
source = getUtility(IPackageCopyJobSource)
165
source = getUtility(IPlainPackageCopyJobSource)
110
166
job = source.create(
111
source_packages=[("libc", "2.8-1")], source_archive=archive1,
112
target_archive=archive2, target_distroseries=distroseries,
167
source_packages=[("libc", "2.8-1")], source_archive=breezy_archive,
168
target_archive=target_archive, target_distroseries=target_series,
113
169
target_pocket=PackagePublishingPocket.RELEASE,
114
170
include_binaries=False)
115
171
self.assertContentEqual(
123
179
self.layer.switchDbUser('sync_packages')
126
published_sources = archive2.getPublishedSources()
182
published_sources = target_archive.getPublishedSources()
127
183
spr = published_sources.one().sourcepackagerelease
128
184
self.assertEquals("libc", spr.name)
129
185
self.assertEquals("2.8-1", spr.version)
187
# Switch back to a db user that has permission to clean up
189
self.layer.switchDbUser('launchpad_main')
131
191
def test_getOopsVars(self):
132
192
distroseries = self.factory.makeDistroSeries()
133
193
archive1 = self.factory.makeArchive(distroseries.distribution)
134
194
archive2 = self.factory.makeArchive(distroseries.distribution)
135
source = getUtility(IPackageCopyJobSource)
195
source = getUtility(IPlainPackageCopyJobSource)
136
196
job = source.create(
137
197
source_packages=[("foo", "1.0-1")], source_archive=archive1,
138
198
target_archive=archive2, target_distroseries=distroseries,
141
201
oops_vars = job.getOopsVars()
142
202
naked_job = removeSecurityProxy(job)
144
('distribution_id', distroseries.distribution.id), oops_vars)
145
self.assertIn(('distroseries_id', distroseries.id), oops_vars)
147
('distribution_job_id', naked_job.context.id), oops_vars)
204
('source_archive_id', archive1.id), oops_vars)
206
('target_archive_id', archive2.id), oops_vars)
208
('target_distroseries_id', distroseries.id), oops_vars)
210
('package_copy_job_id', naked_job.context.id), oops_vars)
212
('package_copy_job_type', naked_job.context.job_type.title),
149
215
def test_smoke(self):
150
216
publisher = SoyuzTestPublisher()
174
240
copied_source_package = archive2.getPublishedSources(
175
241
name="libc", version="2.8-1", exact_match=True).first()
176
242
self.assertIsNot(copied_source_package, None)
244
def test___repr__(self):
245
distroseries = self.factory.makeDistroSeries()
246
archive1 = self.factory.makeArchive(distroseries.distribution)
247
archive2 = self.factory.makeArchive(distroseries.distribution)
248
source = getUtility(IPlainPackageCopyJobSource)
250
source_packages=[("foo", "1.0-1"), ("bar", "2.4")],
251
source_archive=archive1, target_archive=archive2,
252
target_distroseries=distroseries,
253
target_pocket=PackagePublishingPocket.RELEASE,
254
include_binaries=True)
256
("<PlainPackageCopyJob to copy 2 package(s) from "
257
"{distroseries.distribution.name}/{archive1.name} to "
258
"{distroseries.distribution.name}/{archive2.name}, "
259
"RELEASE pocket, in {distroseries.distribution.name} "
260
"{distroseries.name}, including binaries>").format(
261
distroseries=distroseries, archive1=archive1,
265
def test_getPendingJobsPerPackage_finds_jobs(self):
266
# getPendingJobsPerPackage finds jobs, and the packages they
268
dsd = self.factory.makeDistroSeriesDifference()
269
job = self.makeJob(dsd)
270
job_source = getUtility(IPlainPackageCopyJobSource)
272
{specify_dsd_package(dsd): job},
273
job_source.getPendingJobsPerPackage(dsd.derived_series))
275
def test_getPendingJobsPerPackage_ignores_other_distroseries(self):
276
# getPendingJobsPerPackage only looks for jobs on the indicated
278
dsd = self.factory.makeDistroSeriesDifference()
280
other_series = self.factory.makeDistroSeries()
281
job_source = getUtility(IPlainPackageCopyJobSource)
283
{}, job_source.getPendingJobsPerPackage(other_series))
285
def test_getPendingJobsPerPackage_only_returns_pending_jobs(self):
286
# getPendingJobsPerPackage ignores jobs that have already been
288
dsd = self.factory.makeDistroSeriesDifference()
289
package = specify_dsd_package(dsd)
290
job = self.makeJob(dsd)
291
job_source = getUtility(IPlainPackageCopyJobSource)
293
for status in JobStatus.items:
294
removeSecurityProxy(job).job._status = status
295
result = job_source.getPendingJobsPerPackage(dsd.derived_series)
297
found_by_state[status] = result[package]
299
JobStatus.WAITING: job,
300
JobStatus.RUNNING: job,
301
JobStatus.SUSPENDED: job,
303
self.assertEqual(expected, found_by_state)
305
def test_getPendingJobsPerPackage_distinguishes_jobs(self):
306
# getPendingJobsPerPackage associates the right job with the
308
derived_series = self.factory.makeDistroSeries()
310
self.factory.makeDistroSeriesDifference(
311
derived_series=derived_series)
312
for counter in xrange(2)]
313
jobs = map(self.makeJob, dsds)
314
job_source = getUtility(IPlainPackageCopyJobSource)
316
dict(zip(map(specify_dsd_package, dsds), jobs)),
317
job_source.getPendingJobsPerPackage(derived_series))
319
def test_getPendingJobsPerPackage_picks_oldest_job_for_dsd(self):
320
# If there are multiple jobs for one package,
321
# getPendingJobsPerPackage picks the oldest.
322
dsd = self.factory.makeDistroSeriesDifference()
323
jobs = [self.makeJob(dsd) for counter in xrange(2)]
324
job_source = getUtility(IPlainPackageCopyJobSource)
326
{specify_dsd_package(dsd): jobs[0]},
327
job_source.getPendingJobsPerPackage(dsd.derived_series))
329
def test_getPendingJobsPerPackage_ignores_dsds_without_jobs(self):
330
# getPendingJobsPerPackage produces no dict entry for packages
331
# that have no pending jobs, even if they do have DSDs.
332
dsd = self.factory.makeDistroSeriesDifference()
333
job_source = getUtility(IPlainPackageCopyJobSource)
335
{}, job_source.getPendingJobsPerPackage(dsd.derived_series))