Merge lp:~james-w/launchpad/test-package-cloner into lp:launchpad
- test-package-cloner
- Merge into devel
Status: | Merged |
---|---|
Merged at revision: | 11142 |
Proposed branch: | lp:~james-w/launchpad/test-package-cloner |
Merge into: | lp:launchpad |
Prerequisite: | lp:~james-w/launchpad/copy-archive-package-sets |
Diff against target: |
1506 lines (+745/-619) 4 files modified
lib/lp/soyuz/model/packagecloner.py (+63/-5) lib/lp/soyuz/scripts/populate_archive.py (+2/-78) lib/lp/soyuz/scripts/tests/test_populatearchive.py (+21/-536) lib/lp/soyuz/tests/test_packagecloner.py (+659/-0) |
To merge this branch: | bzr merge lp:~james-w/launchpad/test-package-cloner |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paul Hummer (community) | code | Approve | |
Review via email: mp+28405@code.launchpad.net |
Commit message
Make PackageCloner create builds, and add some tests for it.
Description of the change
Summary
This moves creating builds from populate_archive.py to PackageCloner.
In addition it also adds to direct tests for the latter, moving most of the tests
that were testing its behaviour from using the script to do so to testing directly.
Pre-implementation notes
Checked with Julian that he was fine with PackageCloner doing this.
Implementation details
Nothing particularly interesting here, just a lot of code movement.
Tests
./bin/test -s lp.soyuz.
./bin/test -s lp.soyuz.tests -m test_packagecloner
Demo and Q/A
None
lint
Linting changed files:
lib/lp/
lib/lp/
lib/lp/
lib/lp/
== Pyflakes notices ==
lib/lp/
112: local variable 'ignore_this' is assigned to but never used
279: local variable 'ignore_result' is assigned to but never used
Thanks,
James
James Westby (james-w) wrote : | # |
On Thu, 24 Jun 2010 16:18:27 -0000, Paul Hummer <email address hidden> wrote:
> Review: Approve code
> James, thanks for doing this. Do you need someone to land this for you?
No, I have that power if you can toggle the status for me.
Thanks,
James
Preview Diff
1 | === modified file 'lib/lp/soyuz/model/packagecloner.py' |
2 | --- lib/lp/soyuz/model/packagecloner.py 2010-07-02 03:47:49 +0000 |
3 | +++ lib/lp/soyuz/model/packagecloner.py 2010-07-16 03:28:56 +0000 |
4 | @@ -11,11 +11,15 @@ |
5 | ] |
6 | |
7 | |
8 | +import transaction |
9 | + |
10 | from zope.component import getUtility |
11 | from zope.interface import implements |
12 | +from zope.security.proxy import removeSecurityProxy |
13 | |
14 | from canonical.database.constants import UTC_NOW |
15 | from canonical.database.sqlbase import quote, sqlvalues |
16 | +from lp.soyuz.interfaces.archivearch import IArchiveArchSet |
17 | from lp.soyuz.interfaces.publishing import PackagePublishingStatus |
18 | from lp.soyuz.interfaces.packagecloner import IPackageCloner |
19 | from canonical.launchpad.webapp.interfaces import ( |
20 | @@ -50,7 +54,8 @@ |
21 | |
22 | implements(IPackageCloner) |
23 | |
24 | - def clonePackages(self, origin, destination, distroarchseries_list=None): |
25 | + def clonePackages(self, origin, destination, distroarchseries_list=None, |
26 | + proc_families=None): |
27 | """Copies packages from origin to destination package location. |
28 | |
29 | Binary packages are only copied for the `DistroArchSeries` pairs |
30 | @@ -64,6 +69,7 @@ |
31 | distroarchseries instances. |
32 | @param distroarchseries_list: the binary packages will be copied |
33 | for the distroarchseries pairs specified (if any). |
34 | + @param the processor families to create builds for. |
35 | """ |
36 | # First clone the source packages. |
37 | self._clone_source_packages(origin, destination) |
38 | @@ -75,6 +81,49 @@ |
39 | self._clone_binary_packages( |
40 | origin, destination, origin_das, destination_das) |
41 | |
42 | + if proc_families is None: |
43 | + proc_families = [] |
44 | + |
45 | + self._create_missing_builds( |
46 | + destination.distroseries, destination.archive, proc_families) |
47 | + |
48 | + def _create_missing_builds(self, distroseries, archive, proc_families): |
49 | + """Create builds for all cloned source packages. |
50 | + |
51 | + :param distroseries: the distro series for which to create builds. |
52 | + :param archive: the archive for which to create builds. |
53 | + :param proc_families: the list of processor families for |
54 | + which to create builds. |
55 | + """ |
56 | + # Avoid circular imports. |
57 | + from lp.soyuz.interfaces.publishing import active_publishing_status |
58 | + |
59 | + # Listify the architectures to avoid hitting this MultipleJoin |
60 | + # multiple times. |
61 | + architectures = list(distroseries.architectures) |
62 | + |
63 | + # Filter the list of DistroArchSeries so that only the ones |
64 | + # specified in proc_families remain |
65 | + architectures = [architecture for architecture in architectures |
66 | + if architecture.processorfamily in proc_families] |
67 | + |
68 | + if len(architectures) == 0: |
69 | + return |
70 | + |
71 | + # Both, PENDING and PUBLISHED sources will be considered for |
72 | + # as PUBLISHED. It's part of the assumptions made in: |
73 | + # https://launchpad.net/soyuz/+spec/build-unpublished-source |
74 | + sources_published = archive.getPublishedSources( |
75 | + distroseries=distroseries, status=active_publishing_status) |
76 | + |
77 | + def get_spn(pub): |
78 | + """Return the source package name for a publishing record.""" |
79 | + return pub.sourcepackagerelease.sourcepackagename.name |
80 | + |
81 | + for pubrec in sources_published: |
82 | + pubrec.createMissingBuilds(architectures_available=architectures) |
83 | + # Commit to avoid MemoryError: bug 304459 |
84 | + transaction.commit() |
85 | |
86 | def _clone_binary_packages(self, origin, destination, origin_das, |
87 | destination_das): |
88 | @@ -153,6 +202,17 @@ |
89 | """ % sqlvalues( |
90 | PackagePublishingStatus.SUPERSEDED, UTC_NOW)) |
91 | |
92 | + def get_family(archivearch): |
93 | + """Extract the processor family from an `IArchiveArch`.""" |
94 | + return removeSecurityProxy(archivearch).processorfamily |
95 | + |
96 | + proc_families = [ |
97 | + get_family(archivearch) for archivearch |
98 | + in getUtility(IArchiveArchSet).getByArchive(destination.archive)] |
99 | + |
100 | + self._create_missing_builds( |
101 | + destination.distroseries, destination.archive, proc_families) |
102 | + |
103 | def _compute_packageset_delta(self, origin): |
104 | """Given a source/target archive find obsolete or missing packages. |
105 | |
106 | @@ -219,7 +279,7 @@ |
107 | PackagePublishingStatus.PENDING, |
108 | PackagePublishingStatus.PUBLISHED, |
109 | origin.distroseries, origin.pocket) |
110 | - |
111 | + |
112 | if origin.component is not None: |
113 | find_origin_only_packages += ( |
114 | " AND secsrc.component = %s" % quote(origin.component)) |
115 | @@ -288,7 +348,7 @@ |
116 | PackagePublishingStatus.PENDING, |
117 | PackagePublishingStatus.PUBLISHED, |
118 | destination.distroseries, destination.pocket) |
119 | - |
120 | + |
121 | if destination.component is not None: |
122 | pop_query += ( |
123 | " AND secsrc.component = %s" % quote(destination.component)) |
124 | @@ -389,5 +449,3 @@ |
125 | logger.info('New packages: %d' % len(new_info)) |
126 | for info in new_info: |
127 | logger.info('* %s (%s)' % info) |
128 | - |
129 | - |
130 | |
131 | === modified file 'lib/lp/soyuz/scripts/populate_archive.py' |
132 | --- lib/lp/soyuz/scripts/populate_archive.py 2010-07-02 03:47:49 +0000 |
133 | +++ lib/lp/soyuz/scripts/populate_archive.py 2010-07-16 03:28:56 +0000 |
134 | @@ -248,10 +248,6 @@ |
135 | """Extract the processor family from an `IArchiveArch`.""" |
136 | return removeSecurityProxy(archivearch).processorfamily |
137 | |
138 | - proc_families = [ |
139 | - get_family(archivearch) for archivearch |
140 | - in getUtility(IArchiveArchSet).getByArchive(copy_archive)] |
141 | - |
142 | # Now instantiate the package copy request that will capture the |
143 | # archive population parameters in the database. |
144 | pcr = getUtility(IPackageCopyRequestSet).new( |
145 | @@ -269,12 +265,8 @@ |
146 | if merge_copy_flag: |
147 | pkg_cloner.mergeCopy(the_origin, the_destination) |
148 | else: |
149 | - pkg_cloner.clonePackages(the_origin, the_destination) |
150 | - |
151 | - # Create builds for the cloned packages. |
152 | - self._createMissingBuilds( |
153 | - the_destination.distroseries, the_destination.archive, |
154 | - proc_families) |
155 | + pkg_cloner.clonePackages( |
156 | + the_origin, the_destination, proc_families=proc_families) |
157 | |
158 | # Mark the package copy request as completed. |
159 | pcr.markAsCompleted() |
160 | @@ -399,71 +391,3 @@ |
161 | "--nonvirtualized", dest="nonvirtualized", default=False, |
162 | action="store_true", |
163 | help='Create the archive as nonvirtual if specified.') |
164 | - |
165 | - def _createMissingBuilds( |
166 | - self, distroseries, archive, proc_families): |
167 | - """Create builds for all cloned source packages. |
168 | - |
169 | - :param distroseries: the distro series for which to create builds. |
170 | - :param archive: the archive for which to create builds. |
171 | - :param proc_families: the list of processor families for |
172 | - which to create builds. |
173 | - """ |
174 | - # Avoid circular imports. |
175 | - from lp.soyuz.interfaces.publishing import active_publishing_status |
176 | - |
177 | - self.logger.info("Processing %s." % distroseries.name) |
178 | - |
179 | - # Listify the architectures to avoid hitting this MultipleJoin |
180 | - # multiple times. |
181 | - architectures = list(distroseries.architectures) |
182 | - |
183 | - # Filter the list of DistroArchSeries so that only the ones |
184 | - # specified on the command line remain. |
185 | - architectures = [architecture for architecture in architectures |
186 | - if architecture.processorfamily in proc_families] |
187 | - |
188 | - if len(architectures) == 0: |
189 | - self.logger.info( |
190 | - "No DistroArchSeries left for %s, done." % distroseries.name) |
191 | - return |
192 | - |
193 | - self.logger.info( |
194 | - "Supported architectures: %s." % |
195 | - " ".join(arch_series.architecturetag |
196 | - for arch_series in architectures)) |
197 | - |
198 | - # Both, PENDING and PUBLISHED sources will be considered for |
199 | - # as PUBLISHED. It's part of the assumptions made in: |
200 | - # https://launchpad.net/soyuz/+spec/build-unpublished-source |
201 | - sources_published = archive.getPublishedSources( |
202 | - distroseries=distroseries, status=active_publishing_status) |
203 | - |
204 | - self.logger.info( |
205 | - "Found %d source(s) published." % sources_published.count()) |
206 | - |
207 | - def get_spn(pub): |
208 | - """Return the source package name for a publishing record.""" |
209 | - return pub.sourcepackagerelease.sourcepackagename.name |
210 | - |
211 | - archindep_unavailable = distroseries.nominatedarchindep not in ( |
212 | - architectures) |
213 | - |
214 | - for pubrec in sources_published: |
215 | - if (pubrec.sourcepackagerelease.architecturehintlist == "all" |
216 | - and archindep_unavailable): |
217 | - self.logger.info( |
218 | - "Skipping %s, arch-all package can't be built since %s " |
219 | - "is not requested" % ( |
220 | - get_spn(pubrec), |
221 | - distroseries.nominatedarchindep.architecturetag)) |
222 | - continue |
223 | - |
224 | - builds = pubrec.createMissingBuilds( |
225 | - architectures_available=architectures, logger=self.logger) |
226 | - if len(builds) == 0: |
227 | - self.logger.info("%s has no builds." % get_spn(pubrec)) |
228 | - else: |
229 | - self.logger.info( |
230 | - "%s has %s build(s)." % (get_spn(pubrec), len(builds))) |
231 | - self.txn.commit() |
232 | |
233 | === modified file 'lib/lp/soyuz/scripts/tests/test_populatearchive.py' |
234 | --- lib/lp/soyuz/scripts/tests/test_populatearchive.py 2010-07-02 03:47:49 +0000 |
235 | +++ lib/lp/soyuz/scripts/tests/test_populatearchive.py 2010-07-16 03:28:56 +0000 |
236 | @@ -21,14 +21,10 @@ |
237 | from lp.buildmaster.interfaces.buildbase import BuildStatus |
238 | from lp.registry.interfaces.distribution import IDistributionSet |
239 | from lp.registry.interfaces.person import IPersonSet |
240 | -from lp.registry.interfaces.pocket import PackagePublishingPocket |
241 | from lp.services.job.interfaces.job import JobStatus |
242 | from lp.soyuz.interfaces.archive import ArchivePurpose, IArchiveSet |
243 | from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet |
244 | -from lp.soyuz.interfaces.packagecopyrequest import ( |
245 | - IPackageCopyRequestSet, PackageCopyStatus) |
246 | from lp.soyuz.interfaces.publishing import PackagePublishingStatus |
247 | -from lp.soyuz.model.processor import ProcessorFamilySet |
248 | from lp.soyuz.scripts.ftpmaster import PackageLocationError, SoyuzScriptError |
249 | from lp.soyuz.scripts.populate_archive import ArchivePopulator |
250 | from lp.soyuz.tests.test_publishing import SoyuzTestPublisher |
251 | @@ -41,18 +37,6 @@ |
252 | return pub.sourcepackagerelease.sourcepackagename |
253 | |
254 | |
255 | -class PackageInfo: |
256 | - |
257 | - def __init__(self, name, version, |
258 | - status=PackagePublishingStatus.PUBLISHED, component="main", |
259 | - arch_hint=None): |
260 | - self.name = name |
261 | - self.version = version |
262 | - self.status = status |
263 | - self.component = component |
264 | - self.arch_hint = arch_hint |
265 | - |
266 | - |
267 | class TestPopulateArchiveScript(TestCaseWithFactory): |
268 | """Test the copy-package.py script.""" |
269 | |
270 | @@ -86,6 +70,15 @@ |
271 | stdout, stderr = process.communicate() |
272 | return (process.returncode, stdout, stderr) |
273 | |
274 | + def getScript(self, test_args=None): |
275 | + """Return an ArchivePopulator instance.""" |
276 | + if test_args is None: |
277 | + test_args = [] |
278 | + script = ArchivePopulator("test copy archives", test_args=test_args) |
279 | + script.logger = QuietFakeLogger() |
280 | + script.txn = self.layer.txn |
281 | + return script |
282 | + |
283 | def testCopyArchiveCreation(self): |
284 | """Start archive population, check data before and after. |
285 | |
286 | @@ -151,530 +144,11 @@ |
287 | |
288 | self.assertEqual(build_spns, self.expected_build_spns) |
289 | |
290 | - def createSourceDistroSeries(self): |
291 | - """Create a DistroSeries suitable for copying. |
292 | - |
293 | - Creates a distroseries with a DistroArchSeries and nominatedarchindep, |
294 | - which makes it suitable for copying because it will create some builds. |
295 | - """ |
296 | - distro_name = "foobuntu" |
297 | - distro = self.factory.makeDistribution(name=distro_name) |
298 | - distroseries_name = "maudlin" |
299 | - distroseries = self.factory.makeDistroSeries( |
300 | - distribution=distro, name=distroseries_name) |
301 | - das = self.factory.makeDistroArchSeries( |
302 | - distroseries=distroseries, architecturetag="i386", |
303 | - processorfamily=ProcessorFamilySet().getByName("x86"), |
304 | - supports_virtualized=True) |
305 | - distroseries.nominatedarchindep = das |
306 | - return distroseries |
307 | - |
308 | - def createTargetOwner(self): |
309 | - """Create a person suitable to own a copy archive.""" |
310 | - person_name = "copy-archive-owner" |
311 | - owner = self.factory.makePerson(name=person_name) |
312 | - return owner |
313 | - |
314 | - def getTargetArchiveName(self, distribution): |
315 | - """Get a suitable name for a copy archive. |
316 | - |
317 | - It also checks that the archive doesn't currently exist. |
318 | - """ |
319 | - archive_name = "msa%s" % int(time.time()) |
320 | - copy_archive = getUtility(IArchiveSet).getByDistroPurpose( |
321 | - distribution, ArchivePurpose.COPY, archive_name) |
322 | - # This is a sanity check: a copy archive with this name should not |
323 | - # exist yet. |
324 | - self.assertIs(None, copy_archive) |
325 | - return archive_name |
326 | - |
327 | - def createSourcePublication(self, info, distroseries): |
328 | - """Create a SourcePackagePublishingHistory based on a PackageInfo.""" |
329 | - if info.arch_hint is None: |
330 | - arch_hint = "any" |
331 | - else: |
332 | - arch_hint = info.arch_hint |
333 | - |
334 | - self.factory.makeSourcePackagePublishingHistory( |
335 | - sourcepackagename=self.factory.getOrMakeSourcePackageName( |
336 | - name=info.name), |
337 | - distroseries=distroseries, component=self.factory.makeComponent( |
338 | - info.component), |
339 | - version=info.version, architecturehintlist=arch_hint, |
340 | - archive=distroseries.distribution.main_archive, |
341 | - status=info.status, pocket=PackagePublishingPocket.RELEASE) |
342 | - |
343 | - def createSourcePublications(self, package_infos, distroseries): |
344 | - """Create a source publication for each item in package_infos.""" |
345 | - for package_info in package_infos: |
346 | - self.createSourcePublication(package_info, distroseries) |
347 | - |
348 | - def getScript(self, test_args=None): |
349 | - """Return an ArchivePopulator instance.""" |
350 | - if test_args is None: |
351 | - test_args = [] |
352 | - script = ArchivePopulator("test copy archives", test_args=test_args) |
353 | - script.logger = QuietFakeLogger() |
354 | - script.txn = self.layer.txn |
355 | - return script |
356 | - |
357 | - def copyArchive(self, distroseries, archive_name, owner, |
358 | - architectures=None, component="main", from_user=None, |
359 | - from_archive=None, packageset_names=None, nonvirtualized=False): |
360 | - """Run the copy-archive script.""" |
361 | - extra_args = [ |
362 | - '--from-distribution', distroseries.distribution.name, |
363 | - '--from-suite', distroseries.name, |
364 | - '--to-distribution', distroseries.distribution.name, |
365 | - '--to-suite', distroseries.name, |
366 | - '--to-archive', archive_name, |
367 | - '--to-user', owner.name, |
368 | - '--reason', |
369 | - '"copy archive from %s"' % datetime.ctime(datetime.utcnow()), |
370 | - '--component', component, |
371 | - ] |
372 | - |
373 | - if from_user is not None: |
374 | - extra_args.extend(["--from-user", from_user]) |
375 | - |
376 | - if from_archive is not None: |
377 | - extra_args.extend(["--from-archive", from_archive]) |
378 | - |
379 | - if architectures is None: |
380 | - architectures = ["386"] |
381 | - |
382 | - if nonvirtualized: |
383 | - extra_args.extend(["--nonvirtualized"]) |
384 | - |
385 | - for architecture in architectures: |
386 | - extra_args.extend(['-a', architecture]) |
387 | - |
388 | - if packageset_names is None: |
389 | - packageset_names = [] |
390 | - |
391 | - for packageset_name in packageset_names: |
392 | - extra_args.extend(['--package-set', packageset_name]) |
393 | - |
394 | - script = self.getScript(test_args=extra_args) |
395 | - script.mainTask() |
396 | - |
397 | - # Make sure the copy archive with the desired name was |
398 | - # created |
399 | - copy_archive = getUtility(IArchiveSet).getByDistroPurpose( |
400 | - distroseries.distribution, ArchivePurpose.COPY, archive_name) |
401 | - self.assertTrue(copy_archive is not None) |
402 | - |
403 | - # Ascertain that the new copy archive was created with the 'enabled' |
404 | - # flag turned off. |
405 | - self.assertFalse(copy_archive.enabled) |
406 | - |
407 | - # Assert the virtualization is correct. |
408 | - virtual = not nonvirtualized |
409 | - self.assertEqual(copy_archive.require_virtualized, virtual) |
410 | - |
411 | - return copy_archive |
412 | - |
413 | - def checkCopiedSources(self, archive, distroseries, expected): |
414 | - """Check the sources published in an archive against an expected set. |
415 | - |
416 | - Given an archive and a target distroseries the sources published in |
417 | - that distroseries are checked against a set of PackageInfo to |
418 | - ensure that the correct package names and versions are published. |
419 | - """ |
420 | - expected_set = set([(info.name, info.version) for info in expected]) |
421 | - sources = archive.getPublishedSources( |
422 | - distroseries=distroseries, status=self.pending_statuses) |
423 | - actual_set = set() |
424 | - for source in sources: |
425 | - source = removeSecurityProxy(source) |
426 | - actual_set.add( |
427 | - (source.source_package_name, source.source_package_version)) |
428 | - self.assertEqual(expected_set, actual_set) |
429 | - |
430 | - def createSourceDistribution(self, package_infos): |
431 | - """Create a distribution to be the source of a copy archive.""" |
432 | - distroseries = self.createSourceDistroSeries() |
433 | - self.createSourcePublications(package_infos, distroseries) |
434 | - return distroseries |
435 | - |
436 | - def makeCopyArchive(self, package_infos, component="main", |
437 | - nonvirtualized=False): |
438 | - """Make a copy archive based on a new distribution.""" |
439 | - owner = self.createTargetOwner() |
440 | - distroseries = self.createSourceDistribution(package_infos) |
441 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
442 | - copy_archive = self.copyArchive( |
443 | - distroseries, archive_name, owner, component=component, |
444 | - nonvirtualized=nonvirtualized) |
445 | - return (copy_archive, distroseries) |
446 | - |
447 | - def checkBuilds(self, archive, package_infos): |
448 | - """Check the build records pending in an archive. |
449 | - |
450 | - Given a set of PackageInfo objects check that each has a build |
451 | - created for it. |
452 | - """ |
453 | - expected_builds = list( |
454 | - [(info.name, info.version) for info in package_infos]) |
455 | - builds = list( |
456 | - getUtility(IBinaryPackageBuildSet).getBuildsForArchive( |
457 | - archive, status=BuildStatus.NEEDSBUILD)) |
458 | - actual_builds = list() |
459 | - for build in builds: |
460 | - naked_build = removeSecurityProxy(build) |
461 | - spr = naked_build.source_package_release |
462 | - actual_builds.append((spr.name, spr.version)) |
463 | - self.assertEqual(sorted(expected_builds), sorted(actual_builds)) |
464 | - |
465 | - def testCopyArchiveRunScript(self): |
466 | - """Check that we can exec the script to copy an archive.""" |
467 | - package_info = PackageInfo( |
468 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
469 | - owner = self.createTargetOwner() |
470 | - distroseries = self.createSourceDistribution([package_info]) |
471 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
472 | - # We must commit as we are going to exec a script that will run |
473 | - # in a different transaction and must be able to see the |
474 | - # objects we just created. |
475 | - self.layer.commit() |
476 | - |
477 | - extra_args = [ |
478 | - '--from-distribution', distroseries.distribution.name, |
479 | - '--from-suite', distroseries.name, |
480 | - '--to-distribution', distroseries.distribution.name, |
481 | - '--to-suite', distroseries.name, |
482 | - '--to-archive', archive_name, |
483 | - '--to-user', owner.name, |
484 | - '--reason', |
485 | - '"copy archive from %s"' % datetime.ctime(datetime.utcnow()), |
486 | - '--component', "main", |
487 | - '-a', '386', |
488 | - ] |
489 | - (exitcode, out, err) = self.runWrapperScript(extra_args) |
490 | - # Check for zero exit code. |
491 | - self.assertEqual( |
492 | - exitcode, 0, "\n=> %s\n=> %s\n=> %s\n" % (exitcode, out, err)) |
493 | - # Make sure the copy archive with the desired name was |
494 | - # created |
495 | - copy_archive = getUtility(IArchiveSet).getByDistroPurpose( |
496 | - distroseries.distribution, ArchivePurpose.COPY, archive_name) |
497 | - self.assertTrue(copy_archive is not None) |
498 | - |
499 | - # Ascertain that the new copy archive was created with the 'enabled' |
500 | - # flag turned off. |
501 | - self.assertFalse(copy_archive.enabled) |
502 | - |
503 | - # Also, make sure that the builds for the new copy archive will be |
504 | - # carried out on non-virtual builders. |
505 | - self.assertTrue(copy_archive.require_virtualized) |
506 | - self.checkCopiedSources( |
507 | - copy_archive, distroseries, [package_info]) |
508 | - |
509 | - def testCopyArchiveCreateCopiesPublished(self): |
510 | - """Test that PUBLISHED sources are copied.""" |
511 | - package_info = PackageInfo( |
512 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
513 | - copy_archive, distroseries = self.makeCopyArchive([package_info]) |
514 | - self.checkCopiedSources( |
515 | - copy_archive, distroseries, [package_info]) |
516 | - |
517 | - def testCopyArchiveCreateCopiesPending(self): |
518 | - """Test that PENDING sources are copied.""" |
519 | - package_info = PackageInfo( |
520 | - "bzr", "2.1", status=PackagePublishingStatus.PENDING) |
521 | - copy_archive, distroseries = self.makeCopyArchive([package_info]) |
522 | - self.checkCopiedSources( |
523 | - copy_archive, distroseries, [package_info]) |
524 | - |
525 | - def testCopyArchiveCreateDoesntCopySuperseded(self): |
526 | - """Test that SUPERSEDED sources are not copied.""" |
527 | - package_info = PackageInfo( |
528 | - "bzr", "2.1", status=PackagePublishingStatus.SUPERSEDED) |
529 | - copy_archive, distroseries = self.makeCopyArchive([package_info]) |
530 | - self.checkCopiedSources( |
531 | - copy_archive, distroseries, []) |
532 | - |
533 | - def testCopyArchiveCreateDoesntCopyDeleted(self): |
534 | - """Test that DELETED sources are not copied.""" |
535 | - package_info = PackageInfo( |
536 | - "bzr", "2.1", status=PackagePublishingStatus.DELETED) |
537 | - copy_archive, distroseries = self.makeCopyArchive([package_info]) |
538 | - self.checkCopiedSources( |
539 | - copy_archive, distroseries, []) |
540 | - |
541 | - def testCopyArchiveCreateDoesntCopyObsolete(self): |
542 | - """Test that OBSOLETE sources are not copied.""" |
543 | - package_info = PackageInfo( |
544 | - "bzr", "2.1", status=PackagePublishingStatus.OBSOLETE) |
545 | - copy_archive, distroseries = self.makeCopyArchive([package_info]) |
546 | - self.checkCopiedSources( |
547 | - copy_archive, distroseries, []) |
548 | - |
549 | - def testCopyArchiveCreatesBuilds(self): |
550 | - """Test that a copy archive creates builds for the copied packages.""" |
551 | - package_info = PackageInfo( |
552 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
553 | - copy_archive, distroseries = self.makeCopyArchive([package_info]) |
554 | - self.checkBuilds(copy_archive, [package_info]) |
555 | - |
556 | - def testCopyArchiveArchTagNotAvailableInSource(self): |
557 | - """Test creating a copy archive for an arch not in the source. |
558 | - |
559 | - If we request a copy to an architecture that doesn't have |
560 | - a DistroArchSeries in the source then we won't get any builds |
561 | - created in the copy archive. |
562 | - """ |
563 | - family = self.factory.makeProcessorFamily(name="armel") |
564 | - self.factory.makeProcessor(family=family, name="armel") |
565 | - package_info = PackageInfo( |
566 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
567 | - owner = self.createTargetOwner() |
568 | - # Creates an archive with just x86 |
569 | - distroseries = self.createSourceDistribution([package_info]) |
570 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
571 | - # Different architecture, so there won't be any builds |
572 | - copy_archive = self.copyArchive( |
573 | - distroseries, archive_name, owner, architectures=["armel"]) |
574 | - self.checkBuilds(copy_archive, []) |
575 | - |
576 | - # Also, make sure the package copy request status was updated. |
577 | - [pcr] = getUtility( |
578 | - IPackageCopyRequestSet).getByTargetArchive(copy_archive) |
579 | - self.assertTrue(pcr.status == PackageCopyStatus.COMPLETE) |
580 | - |
581 | - # This date is set when the copy request makes the transition to |
582 | - # the "in progress" state. |
583 | - self.assertTrue(pcr.date_started is not None) |
584 | - # This date is set when the copy request makes the transition to |
585 | - # the "completed" state. |
586 | - self.assertTrue(pcr.date_completed is not None) |
587 | - self.assertTrue(pcr.date_started <= pcr.date_completed) |
588 | - |
589 | - def testMultipleArchTagsWithSubsetInSource(self): |
590 | - """Try copy archive population with multiple architecture tags. |
591 | - |
592 | - The user may specify a number of given architecture tags on the |
593 | - command line. |
594 | - The script should create build records only for the specified |
595 | - architecture tags that are supported by the destination distro series. |
596 | - |
597 | - In this (test) case the script should create the build records for the |
598 | - '386' architecture. |
599 | - """ |
600 | - family = self.factory.makeProcessorFamily(name="armel") |
601 | - self.factory.makeProcessor(family=family, name="armel") |
602 | - package_info = PackageInfo( |
603 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
604 | - owner = self.createTargetOwner() |
605 | - # Creates an archive with just x86 |
606 | - distroseries = self.createSourceDistribution([package_info]) |
607 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
608 | - # There is only a DAS for i386, so armel won't produce any |
609 | - # builds |
610 | - copy_archive = self.copyArchive( |
611 | - distroseries, archive_name, owner, |
612 | - architectures=["386", "armel"]) |
613 | - self.checkBuilds(copy_archive, [package_info]) |
614 | - |
615 | - def testCopyArchiveCreatesSubsetOfBuilds(self): |
616 | - """Create a copy archive with a subset of the architectures. |
617 | - |
618 | - We copy from an archive with multiple architecture DistroArchSeries, |
619 | - but request only one of those architectures in the target, |
620 | - so we only get builds for that one architecture. |
621 | - """ |
622 | - package_info = PackageInfo( |
623 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
624 | - owner = self.createTargetOwner() |
625 | - distroseries = self.createSourceDistribution([package_info]) |
626 | - self.factory.makeDistroArchSeries( |
627 | - distroseries=distroseries, architecturetag="amd64", |
628 | - processorfamily=ProcessorFamilySet().getByName("amd64"), |
629 | - supports_virtualized=True) |
630 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
631 | - copy_archive = self.copyArchive( |
632 | - distroseries, archive_name, owner, |
633 | - architectures=["386"]) |
634 | - # We only get a single build, as we only requested 386, not |
635 | - # amd64 too |
636 | - self.checkBuilds(copy_archive, [package_info]) |
637 | - |
638 | - def testNoBuildsForArchAll(self): |
639 | - # If we have a copy for an architecture that is not the |
640 | - # nominatedarchindep architecture, then we don't want to create |
641 | - # builds for arch-all packages, as they can't be built at all |
642 | - # and createMissingBuilds blows up when it checks that. |
643 | - package_info = PackageInfo( |
644 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED, |
645 | - arch_hint="all") |
646 | - owner = self.createTargetOwner() |
647 | - distroseries = self.createSourceDistribution([package_info]) |
648 | - self.factory.makeDistroArchSeries( |
649 | - distroseries=distroseries, architecturetag="amd64", |
650 | - processorfamily=ProcessorFamilySet().getByName("amd64"), |
651 | - supports_virtualized=True) |
652 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
653 | - copy_archive = self.copyArchive( |
654 | - distroseries, archive_name, owner, |
655 | - architectures=["amd64"]) |
656 | - # We don't get any builds since amd64 is not the |
657 | - # nomindatedarchindep, i386 is. |
658 | - self.assertEqual( |
659 | - distroseries.nominatedarchindep.architecturetag, "i386") |
660 | - self.checkBuilds(copy_archive, []) |
661 | - |
662 | - def testMultipleArchTags(self): |
663 | - """Test copying an archive with multiple architectures. |
664 | - |
665 | - We create a source with two architectures, and then request |
666 | - a copy of both, so we get a build for each of those architectures. |
667 | - """ |
668 | - package_info = PackageInfo( |
669 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
670 | - owner = self.createTargetOwner() |
671 | - distroseries = self.createSourceDistribution([package_info]) |
672 | - self.factory.makeDistroArchSeries( |
673 | - distroseries=distroseries, architecturetag="amd64", |
674 | - processorfamily=ProcessorFamilySet().getByName("amd64"), |
675 | - supports_virtualized=True) |
676 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
677 | - copy_archive = self.copyArchive( |
678 | - distroseries, archive_name, owner, |
679 | - architectures=["386", "amd64"]) |
680 | - self.checkBuilds(copy_archive, [package_info, package_info]) |
681 | - |
682 | - def testCopyArchiveCopiesRightComponents(self): |
683 | - """Test that packages from the right components are copied. |
684 | - |
685 | - When copying you specify a component, that component should |
686 | - limit the packages copied. We create a source in main and one in |
687 | - universe, and then copy with --component main, and expect to see |
688 | - only main in the copy. |
689 | - """ |
690 | - package_info_universe = PackageInfo( |
691 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED, |
692 | - component="universe") |
693 | - package_info_main = PackageInfo( |
694 | - "apt", "2.2", status=PackagePublishingStatus.PUBLISHED, |
695 | - component="main") |
696 | - package_infos_both = [package_info_universe, package_info_main] |
697 | - copy_archive, distroseries = self.makeCopyArchive( |
698 | - package_infos_both, component="main") |
699 | - self.checkBuilds(copy_archive, [package_info_main]) |
700 | - |
701 | - def testCopyArchiveSubsetsBasedOnPackageset(self): |
702 | - """Test that --package-set limits the sources copied.""" |
703 | - package_infos = [ |
704 | - PackageInfo( |
705 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
706 | - PackageInfo( |
707 | - "apt", "2.2", status=PackagePublishingStatus.PUBLISHED), |
708 | - ] |
709 | - owner = self.createTargetOwner() |
710 | - distroseries = self.createSourceDistribution(package_infos) |
711 | - packageset_name = u"apt-packageset" |
712 | - spn = self.factory.getOrMakeSourcePackageName(name="apt") |
713 | - self.factory.makePackageset( |
714 | - name=packageset_name, distroseries=distroseries, packages=(spn,)) |
715 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
716 | - copy_archive = self.copyArchive( |
717 | - distroseries, archive_name, owner, |
718 | - packageset_names=[packageset_name]) |
719 | - self.checkCopiedSources( |
720 | - copy_archive, distroseries, [package_infos[1]]) |
721 | - |
722 | - def testCopyArchiveUnionsPackagesets(self): |
723 | - """Test that package sets are unioned when copying archives.""" |
724 | - package_infos = [ |
725 | - PackageInfo( |
726 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
727 | - PackageInfo( |
728 | - "apt", "2.2", status=PackagePublishingStatus.PUBLISHED), |
729 | - PackageInfo( |
730 | - "gcc", "4.5", status=PackagePublishingStatus.PUBLISHED), |
731 | - ] |
732 | - owner = self.createTargetOwner() |
733 | - distroseries = self.createSourceDistribution(package_infos) |
734 | - apt_packageset_name = u"apt-packageset" |
735 | - apt_spn = self.factory.getOrMakeSourcePackageName(name="apt") |
736 | - gcc_packageset_name = u"gcc-packageset" |
737 | - gcc_spn = self.factory.getOrMakeSourcePackageName(name="gcc") |
738 | - self.factory.makePackageset( |
739 | - name=apt_packageset_name, distroseries=distroseries, |
740 | - packages=(apt_spn,)) |
741 | - self.factory.makePackageset( |
742 | - name=gcc_packageset_name, distroseries=distroseries, |
743 | - packages=(gcc_spn,)) |
744 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
745 | - copy_archive = self.copyArchive( |
746 | - distroseries, archive_name, owner, |
747 | - packageset_names=[apt_packageset_name, gcc_packageset_name]) |
748 | - self.checkCopiedSources( |
749 | - copy_archive, distroseries, package_infos[1:]) |
750 | - |
751 | - def testCopyArchiveRecursivelyCopiesPackagesets(self): |
752 | - """Test that package set copies include subsets.""" |
753 | - package_infos = [ |
754 | - PackageInfo( |
755 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
756 | - PackageInfo( |
757 | - "apt", "2.2", status=PackagePublishingStatus.PUBLISHED), |
758 | - PackageInfo( |
759 | - "gcc", "4.5", status=PackagePublishingStatus.PUBLISHED), |
760 | - ] |
761 | - owner = self.createTargetOwner() |
762 | - distroseries = self.createSourceDistribution(package_infos) |
763 | - apt_packageset_name = u"apt-packageset" |
764 | - apt_spn = self.factory.getOrMakeSourcePackageName(name="apt") |
765 | - gcc_packageset_name = u"gcc-packageset" |
766 | - gcc_spn = self.factory.getOrMakeSourcePackageName(name="gcc") |
767 | - apt_packageset = self.factory.makePackageset( |
768 | - name=apt_packageset_name, distroseries=distroseries, |
769 | - packages=(apt_spn,)) |
770 | - gcc_packageset = self.factory.makePackageset( |
771 | - name=gcc_packageset_name, distroseries=distroseries, |
772 | - packages=(gcc_spn,)) |
773 | - apt_packageset.add((gcc_packageset,)) |
774 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
775 | - copy_archive = self.copyArchive( |
776 | - distroseries, archive_name, owner, |
777 | - packageset_names=[apt_packageset_name]) |
778 | - self.checkCopiedSources( |
779 | - copy_archive, distroseries, package_infos[1:]) |
780 | - |
781 | - def testCopyFromPPA(self): |
782 | - """Test we can create a copy archive with a PPA as the source.""" |
783 | - ppa_owner_name = "ppa-owner" |
784 | - ppa_name = "ppa" |
785 | - ppa_owner = self.factory.makePerson(name=ppa_owner_name) |
786 | - distroseries = self.createSourceDistroSeries() |
787 | - ppa = self.factory.makeArchive( |
788 | - name=ppa_name, purpose=ArchivePurpose.PPA, |
789 | - distribution=distroseries.distribution, owner=ppa_owner) |
790 | - package_info = PackageInfo( |
791 | - "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED, |
792 | - component="universe") |
793 | - self.factory.makeSourcePackagePublishingHistory( |
794 | - sourcepackagename=self.factory.getOrMakeSourcePackageName( |
795 | - name=package_info.name), |
796 | - distroseries=distroseries, component=self.factory.makeComponent( |
797 | - package_info.component), |
798 | - version=package_info.version, archive=ppa, |
799 | - status=package_info.status, architecturehintlist='any', |
800 | - pocket=PackagePublishingPocket.RELEASE) |
801 | - owner = self.createTargetOwner() |
802 | - archive_name = self.getTargetArchiveName(distroseries.distribution) |
803 | - copy_archive = self.copyArchive( |
804 | - distroseries, archive_name, owner, from_user=ppa_owner_name, |
805 | - from_archive=ppa_name, component=package_info.component) |
806 | - self.checkCopiedSources( |
807 | - copy_archive, distroseries, [package_info]) |
808 | - |
809 | def runScript( |
810 | self, archive_name=None, suite='hoary', user='salgado', |
811 | exists_before=None, exists_after=None, exception_type=None, |
812 | exception_text=None, extra_args=None, copy_archive_name=None, |
813 | - reason=None, output_substr=None): |
814 | + reason=None, output_substr=None, nonvirtualized=False): |
815 | """Run the script to test. |
816 | |
817 | :type archive_name: `str` |
818 | @@ -748,6 +222,9 @@ |
819 | reason = "copy archive, %s" % datetime.ctime(datetime.utcnow()) |
820 | script_args.extend(['--reason', reason]) |
821 | |
822 | + if nonvirtualized: |
823 | + script_args.append('--nonvirtualized') |
824 | + |
825 | if extra_args is not None: |
826 | script_args.extend(extra_args) |
827 | |
828 | @@ -847,6 +324,14 @@ |
829 | exception_text="Could not find packageset No such package set" |
830 | " (in the specified distro series): '%s'." % unknown_packageset) |
831 | |
832 | + def testNonvirtualized(self): |
833 | + """--nonvirtualized means the archive won't require virtualization.""" |
834 | + copy_archive = self.runScript( |
835 | + archive_name="copy-archive-test", exists_before=False, |
836 | + exists_after=True, nonvirtualized=True, |
837 | + extra_args=['-a', '386']) |
838 | + self.assertFalse(copy_archive.require_virtualized) |
839 | + |
840 | def testPackagesetDelta(self): |
841 | """Try to calculate the delta between two source package sets.""" |
842 | hoary = getUtility(IDistributionSet)['ubuntu']['hoary'] |
843 | |
844 | === added file 'lib/lp/soyuz/tests/test_packagecloner.py' |
845 | --- lib/lp/soyuz/tests/test_packagecloner.py 1970-01-01 00:00:00 +0000 |
846 | +++ lib/lp/soyuz/tests/test_packagecloner.py 2010-07-16 03:28:56 +0000 |
847 | @@ -0,0 +1,659 @@ |
848 | +# Copyright 2009 Canonical Ltd. This software is licensed under the |
849 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
850 | + |
851 | +__metaclass__ = type |
852 | + |
853 | +from zope.component import getUtility |
854 | +from zope.security.proxy import removeSecurityProxy |
855 | + |
856 | +from canonical.testing import LaunchpadZopelessLayer |
857 | + |
858 | +from lp.buildmaster.interfaces.buildbase import BuildStatus |
859 | +from lp.registry.interfaces.pocket import PackagePublishingPocket |
860 | +from lp.soyuz.adapters.packagelocation import PackageLocation |
861 | +from lp.soyuz.interfaces.archive import ArchivePurpose |
862 | +from lp.soyuz.interfaces.archivearch import IArchiveArchSet |
863 | +from lp.soyuz.interfaces.component import IComponentSet |
864 | +from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet |
865 | +from lp.soyuz.interfaces.packagecloner import IPackageCloner |
866 | +from lp.soyuz.interfaces.publishing import ( |
867 | + IPublishingSet, PackagePublishingStatus) |
868 | +from lp.soyuz.model.processor import ProcessorFamilySet |
869 | +from lp.testing import TestCaseWithFactory |
870 | + |
871 | + |
872 | +class PackageInfo: |
873 | + |
874 | + def __init__(self, name, version, |
875 | + status=PackagePublishingStatus.PUBLISHED, component="main"): |
876 | + self.name = name |
877 | + self.version = version |
878 | + self.status = status |
879 | + self.component = component |
880 | + |
881 | + |
882 | +class PackageClonerTests(TestCaseWithFactory): |
883 | + |
884 | + layer = LaunchpadZopelessLayer |
885 | + |
886 | + def checkCopiedSources(self, archive, distroseries, expected): |
887 | + """Check the sources published in an archive against an expected set. |
888 | + |
889 | + Given an archive and a target distroseries the sources published in |
890 | + that distroseries are checked against a set of PackageInfo to |
891 | + ensure that the correct package names and versions are published. |
892 | + """ |
893 | + expected_set = set([(info.name, info.version) for info in expected]) |
894 | + sources = archive.getPublishedSources( |
895 | + distroseries=distroseries, |
896 | + status=(PackagePublishingStatus.PENDING, |
897 | + PackagePublishingStatus.PUBLISHED)) |
898 | + actual_set = set() |
899 | + for source in sources: |
900 | + source = removeSecurityProxy(source) |
901 | + actual_set.add( |
902 | + (source.source_package_name, source.source_package_version)) |
903 | + self.assertEqual(expected_set, actual_set) |
904 | + |
905 | + def createSourceDistribution(self, package_infos): |
906 | + """Create a distribution to be the source of a copy archive.""" |
907 | + distroseries = self.createSourceDistroSeries() |
908 | + self.createSourcePublications(package_infos, distroseries) |
909 | + return distroseries |
910 | + |
911 | + def createSourceDistroSeries(self): |
912 | + """Create a DistroSeries suitable for copying. |
913 | + |
914 | + Creates a distroseries with a DistroArchSeries and nominatedarchindep, |
915 | + which makes it suitable for copying because it will create some builds. |
916 | + """ |
917 | + distro_name = "foobuntu" |
918 | + distro = self.factory.makeDistribution(name=distro_name) |
919 | + distroseries_name = "maudlin" |
920 | + distroseries = self.factory.makeDistroSeries( |
921 | + distribution=distro, name=distroseries_name) |
922 | + das = self.factory.makeDistroArchSeries( |
923 | + distroseries=distroseries, architecturetag="i386", |
924 | + processorfamily=ProcessorFamilySet().getByName("x86"), |
925 | + supports_virtualized=True) |
926 | + distroseries.nominatedarchindep = das |
927 | + return distroseries |
928 | + |
929 | + def getTargetArchive(self, distribution): |
930 | + """Get a target archive for copying in to.""" |
931 | + return self.factory.makeArchive( |
932 | + name="test-copy-archive", purpose=ArchivePurpose.COPY, |
933 | + distribution=distribution) |
934 | + |
935 | + def createSourcePublication(self, info, distroseries): |
936 | + """Create a SourcePackagePublishingHistory based on a PackageInfo.""" |
937 | + archive = distroseries.distribution.main_archive |
938 | + sources = archive.getPublishedSources( |
939 | + distroseries=distroseries, |
940 | + status=(PackagePublishingStatus.PENDING, |
941 | + PackagePublishingStatus.PUBLISHED), |
942 | + name=info.name, exact_match=True) |
943 | + for src in sources: |
944 | + src.supersede() |
945 | + self.factory.makeSourcePackagePublishingHistory( |
946 | + sourcepackagename=self.factory.getOrMakeSourcePackageName( |
947 | + name=info.name), |
948 | + distroseries=distroseries, component=self.factory.makeComponent( |
949 | + info.component), |
950 | + version=info.version, architecturehintlist='any', |
951 | + archive=archive, status=info.status, |
952 | + pocket=PackagePublishingPocket.RELEASE) |
953 | + |
954 | + def createSourcePublications(self, package_infos, distroseries): |
955 | + """Create a source publication for each item in package_infos.""" |
956 | + for package_info in package_infos: |
957 | + self.createSourcePublication(package_info, distroseries) |
958 | + |
959 | + def makeCopyArchive(self, package_infos, component="main", |
960 | + source_pocket=None, target_pocket=None, |
961 | + proc_families=None): |
962 | + """Make a copy archive based on a new distribution.""" |
963 | + distroseries = self.createSourceDistribution(package_infos) |
964 | + copy_archive = self.getTargetArchive(distroseries.distribution) |
965 | + to_component = getUtility(IComponentSet).ensure(component) |
966 | + self.copyArchive( |
967 | + copy_archive, distroseries, from_pocket=source_pocket, |
968 | + to_pocket=target_pocket, to_component=to_component, |
969 | + proc_families=proc_families) |
970 | + return (copy_archive, distroseries) |
971 | + |
972 | + def checkBuilds(self, archive, package_infos): |
973 | + """Check the build records pending in an archive. |
974 | + |
975 | + Given a set of PackageInfo objects check that each has a build |
976 | + created for it. |
977 | + """ |
978 | + expected_builds = list( |
979 | + [(info.name, info.version) for info in package_infos]) |
980 | + builds = list( |
981 | + getUtility(IBinaryPackageBuildSet).getBuildsForArchive( |
982 | + archive, status=BuildStatus.NEEDSBUILD)) |
983 | + actual_builds = list() |
984 | + for build in builds: |
985 | + naked_build = removeSecurityProxy(build) |
986 | + spr = naked_build.source_package_release |
987 | + actual_builds.append((spr.name, spr.version)) |
988 | + self.assertEqual(sorted(expected_builds), sorted(actual_builds)) |
989 | + |
990 | + def copyArchive(self, to_archive, to_distroseries, from_archive=None, |
991 | + from_distroseries=None, from_pocket=None, to_pocket=None, |
992 | + to_component=None, packagesets=None, proc_families=None): |
993 | + """Use a PackageCloner to copy an archive.""" |
994 | + if from_distroseries is None: |
995 | + from_distroseries = to_distroseries |
996 | + if from_archive is None: |
997 | + from_archive = from_distroseries.distribution.main_archive |
998 | + if from_pocket is None: |
999 | + from_pocket = PackagePublishingPocket.RELEASE |
1000 | + if to_pocket is None: |
1001 | + to_pocket = PackagePublishingPocket.RELEASE |
1002 | + if packagesets is None: |
1003 | + packagesets = [] |
1004 | + origin = PackageLocation( |
1005 | + from_archive, from_distroseries.distribution, from_distroseries, |
1006 | + from_pocket) |
1007 | + destination = PackageLocation( |
1008 | + to_archive, to_distroseries.distribution, to_distroseries, |
1009 | + to_pocket) |
1010 | + origin.packagesets = packagesets |
1011 | + if to_component is not None: |
1012 | + destination.component = to_component |
1013 | + cloner = getUtility(IPackageCloner) |
1014 | + cloner.clonePackages( |
1015 | + origin, destination, distroarchseries_list=None, |
1016 | + proc_families=proc_families) |
1017 | + return cloner |
1018 | + |
1019 | + def testCopiesPublished(self): |
1020 | + """Test that PUBLISHED sources are copied.""" |
1021 | + package_info = PackageInfo( |
1022 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1023 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1024 | + self.checkCopiedSources( |
1025 | + copy_archive, distroseries, [package_info]) |
1026 | + |
1027 | + def testCopiesPending(self): |
1028 | + """Test that PENDING sources are copied.""" |
1029 | + package_info = PackageInfo( |
1030 | + "bzr", "2.1", status=PackagePublishingStatus.PENDING) |
1031 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1032 | + self.checkCopiedSources( |
1033 | + copy_archive, distroseries, [package_info]) |
1034 | + |
1035 | + def testDoesntCopySuperseded(self): |
1036 | + """Test that SUPERSEDED sources are not copied.""" |
1037 | + package_info = PackageInfo( |
1038 | + "bzr", "2.1", status=PackagePublishingStatus.SUPERSEDED) |
1039 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1040 | + self.checkCopiedSources( |
1041 | + copy_archive, distroseries, []) |
1042 | + |
1043 | + def testDoesntCopyDeleted(self): |
1044 | + """Test that DELETED sources are not copied.""" |
1045 | + package_info = PackageInfo( |
1046 | + "bzr", "2.1", status=PackagePublishingStatus.DELETED) |
1047 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1048 | + self.checkCopiedSources( |
1049 | + copy_archive, distroseries, []) |
1050 | + |
1051 | + def testDoesntCopyObsolete(self): |
1052 | + """Test that OBSOLETE sources are not copied.""" |
1053 | + package_info = PackageInfo( |
1054 | + "bzr", "2.1", status=PackagePublishingStatus.OBSOLETE) |
1055 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1056 | + self.checkCopiedSources( |
1057 | + copy_archive, distroseries, []) |
1058 | + |
1059 | + def testCopiesAllComponents(self): |
1060 | + """Test that packages from all components are copied. |
1061 | + |
1062 | + When copying you specify a component, but that component doesn't |
1063 | + limit the packages copied. We create a source in main and one in |
1064 | + universe, and then copy with --component main, and expect to see |
1065 | + both sources in the copy. |
1066 | + """ |
1067 | + package_infos = [ |
1068 | + PackageInfo( |
1069 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED, |
1070 | + component="universe"), |
1071 | + PackageInfo( |
1072 | + "apt", "2.2", status=PackagePublishingStatus.PUBLISHED, |
1073 | + component="main")] |
1074 | + copy_archive, distroseries = self.makeCopyArchive(package_infos, |
1075 | + component="main") |
1076 | + self.checkCopiedSources(copy_archive, distroseries, package_infos) |
1077 | + |
1078 | + def testSubsetsBasedOnPackageset(self): |
1079 | + """Test that --package-set limits the sources copied.""" |
1080 | + package_infos = [ |
1081 | + PackageInfo( |
1082 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1083 | + PackageInfo( |
1084 | + "apt", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1085 | + ] |
1086 | + distroseries = self.createSourceDistribution(package_infos) |
1087 | + spn = self.factory.getOrMakeSourcePackageName(name="apt") |
1088 | + packageset = self.factory.makePackageset( |
1089 | + distroseries=distroseries, packages=(spn,)) |
1090 | + copy_archive = self.getTargetArchive(distroseries.distribution) |
1091 | + self.copyArchive(copy_archive, distroseries, packagesets=[packageset]) |
1092 | + self.checkCopiedSources( |
1093 | + copy_archive, distroseries, [package_infos[1]]) |
1094 | + |
1095 | + def testUnionsPackagesets(self): |
1096 | + """Test that package sets are unioned when copying archives.""" |
1097 | + package_infos = [ |
1098 | + PackageInfo( |
1099 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1100 | + PackageInfo( |
1101 | + "apt", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1102 | + PackageInfo( |
1103 | + "gcc", "4.5", status=PackagePublishingStatus.PUBLISHED), |
1104 | + ] |
1105 | + distroseries = self.createSourceDistribution(package_infos) |
1106 | + apt_spn = self.factory.getOrMakeSourcePackageName(name="apt") |
1107 | + gcc_spn = self.factory.getOrMakeSourcePackageName(name="gcc") |
1108 | + apt_packageset = self.factory.makePackageset( |
1109 | + distroseries=distroseries, packages=(apt_spn,)) |
1110 | + gcc_packageset = self.factory.makePackageset( |
1111 | + distroseries=distroseries, packages=(gcc_spn,)) |
1112 | + copy_archive = self.getTargetArchive(distroseries.distribution) |
1113 | + self.copyArchive( |
1114 | + copy_archive, distroseries, |
1115 | + packagesets=[apt_packageset, gcc_packageset]) |
1116 | + self.checkCopiedSources( |
1117 | + copy_archive, distroseries, package_infos[1:]) |
1118 | + |
1119 | + def testRecursivelyCopiesPackagesets(self): |
1120 | + """Test that package set copies include subsets.""" |
1121 | + package_infos = [ |
1122 | + PackageInfo( |
1123 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1124 | + PackageInfo( |
1125 | + "apt", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1126 | + PackageInfo( |
1127 | + "gcc", "4.5", status=PackagePublishingStatus.PUBLISHED), |
1128 | + ] |
1129 | + distroseries = self.createSourceDistribution(package_infos) |
1130 | + apt_spn = self.factory.getOrMakeSourcePackageName(name="apt") |
1131 | + gcc_spn = self.factory.getOrMakeSourcePackageName(name="gcc") |
1132 | + apt_packageset = self.factory.makePackageset( |
1133 | + distroseries=distroseries, packages=(apt_spn,)) |
1134 | + gcc_packageset = self.factory.makePackageset( |
1135 | + distroseries=distroseries, packages=(gcc_spn,)) |
1136 | + apt_packageset.add((gcc_packageset,)) |
1137 | + copy_archive = self.getTargetArchive(distroseries.distribution) |
1138 | + self.copyArchive( |
1139 | + copy_archive, distroseries, packagesets=[apt_packageset]) |
1140 | + self.checkCopiedSources( |
1141 | + copy_archive, distroseries, package_infos[1:]) |
1142 | + |
1143 | + def testCloneFromPPA(self): |
1144 | + """Test we can create a copy archive with a PPA as the source.""" |
1145 | + distroseries = self.createSourceDistroSeries() |
1146 | + ppa = self.factory.makeArchive( |
1147 | + purpose=ArchivePurpose.PPA, |
1148 | + distribution=distroseries.distribution) |
1149 | + package_info = PackageInfo( |
1150 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED, |
1151 | + component="universe") |
1152 | + self.factory.makeSourcePackagePublishingHistory( |
1153 | + sourcepackagename=self.factory.getOrMakeSourcePackageName( |
1154 | + name=package_info.name), |
1155 | + distroseries=distroseries, component=self.factory.makeComponent( |
1156 | + package_info.component), |
1157 | + version=package_info.version, archive=ppa, |
1158 | + status=package_info.status, architecturehintlist='any', |
1159 | + pocket=PackagePublishingPocket.RELEASE) |
1160 | + copy_archive = self.getTargetArchive(distroseries.distribution) |
1161 | + self.copyArchive(copy_archive, distroseries, from_archive=ppa) |
1162 | + self.checkCopiedSources( |
1163 | + copy_archive, distroseries, [package_info]) |
1164 | + |
1165 | + def testCreatesNoBuildsWithNoProcFamilies(self): |
1166 | + """Test that no builds are created if we specify no proc families.""" |
1167 | + package_info = PackageInfo( |
1168 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1169 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1170 | + self.checkBuilds(copy_archive, []) |
1171 | + |
1172 | + def testCreatesBuilds(self): |
1173 | + """Test that a copy archive creates builds for the copied packages.""" |
1174 | + package_info = PackageInfo( |
1175 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1176 | + # This is the processor family for the DAS that the source has, |
1177 | + # so we expect to get builds. |
1178 | + proc_families = [ProcessorFamilySet().getByName("x86")] |
1179 | + copy_archive, distroseries = self.makeCopyArchive( |
1180 | + [package_info], proc_families=proc_families) |
1181 | + self.checkBuilds(copy_archive, [package_info]) |
1182 | + |
1183 | + def testNoBuildsIfProcFamilyNotInSource(self): |
1184 | + """Test that no builds are created for a proc family without a DAS.""" |
1185 | + package_info = PackageInfo( |
1186 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1187 | + # This is a processor family without a DAS in the source, so |
1188 | + # we expect no builds. |
1189 | + family = self.factory.makeProcessorFamily(name="armel") |
1190 | + self.factory.makeProcessor(family=family, name="armel") |
1191 | + proc_families = [family] |
1192 | + copy_archive, distroseries = self.makeCopyArchive( |
1193 | + [package_info], proc_families=proc_families) |
1194 | + self.checkBuilds(copy_archive, []) |
1195 | + |
1196 | + def testBuildsOnlyForProcFamiliesInSource(self): |
1197 | + """Test that builds are only created for proc families in source.""" |
1198 | + package_info = PackageInfo( |
1199 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1200 | + # One of these processor families has a DAS in the source, so |
1201 | + # we expect one set of builds |
1202 | + family = self.factory.makeProcessorFamily(name="armel") |
1203 | + self.factory.makeProcessor(family=family, name="armel") |
1204 | + proc_families = [family, ProcessorFamilySet().getByName("x86")] |
1205 | + copy_archive, distroseries = self.makeCopyArchive( |
1206 | + [package_info], proc_families=proc_families) |
1207 | + self.checkBuilds(copy_archive, [package_info]) |
1208 | + |
1209 | + def testCreatesSubsetOfBuilds(self): |
1210 | + """Test that builds are only created for requested families.""" |
1211 | + package_info = PackageInfo( |
1212 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1213 | + distroseries = self.createSourceDistribution([package_info]) |
1214 | + # Create a DAS for a second family |
1215 | + self.factory.makeDistroArchSeries( |
1216 | + distroseries=distroseries, architecturetag="amd64", |
1217 | + processorfamily=ProcessorFamilySet().getByName("amd64"), |
1218 | + supports_virtualized=True) |
1219 | + # The request builds for only one of the families, so we |
1220 | + # expect just one build for each source |
1221 | + proc_families = [ProcessorFamilySet().getByName("x86")] |
1222 | + copy_archive = self.getTargetArchive(distroseries.distribution) |
1223 | + self.copyArchive( |
1224 | + copy_archive, distroseries, proc_families=proc_families) |
1225 | + self.checkBuilds(copy_archive, [package_info]) |
1226 | + |
1227 | + def testCreatesMultipleBuilds(self): |
1228 | + """Test that multiple families result in mutiple builds.""" |
1229 | + package_info = PackageInfo( |
1230 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1231 | + distroseries = self.createSourceDistribution([package_info]) |
1232 | + # Create a DAS for a second family |
1233 | + amd64_family = ProcessorFamilySet().getByName("amd64") |
1234 | + self.factory.makeDistroArchSeries( |
1235 | + distroseries=distroseries, architecturetag="amd64", |
1236 | + processorfamily=amd64_family, supports_virtualized=True) |
1237 | + # The request builds for both families, so we expect two builds |
1238 | + # per source. |
1239 | + proc_families = [ProcessorFamilySet().getByName("x86"), amd64_family] |
1240 | + copy_archive = self.getTargetArchive(distroseries.distribution) |
1241 | + self.copyArchive( |
1242 | + copy_archive, distroseries, proc_families=proc_families) |
1243 | + self.checkBuilds(copy_archive, [package_info, package_info]) |
1244 | + |
1245 | + |
1246 | + def diffArchives(self, target_archive, target_distroseries, |
1247 | + source_archive=None, source_distroseries=None): |
1248 | + """Run a packageSetDiff of two archives.""" |
1249 | + if source_distroseries is None: |
1250 | + source_distroseries = target_distroseries |
1251 | + if source_archive is None: |
1252 | + source_archive = source_distroseries.distribution.main_archive |
1253 | + source_location = PackageLocation( |
1254 | + source_archive, source_distroseries.distribution, |
1255 | + source_distroseries, PackagePublishingPocket.RELEASE) |
1256 | + target_location = PackageLocation( |
1257 | + target_archive, target_distroseries.distribution, |
1258 | + target_distroseries, PackagePublishingPocket.RELEASE) |
1259 | + cloner = getUtility(IPackageCloner) |
1260 | + return cloner.packageSetDiff(source_location, target_location) |
1261 | + |
1262 | + def checkPackageDiff(self, expected_changed, expected_new, actual, |
1263 | + archive): |
1264 | + """Check that the diff of two archives is as expected.""" |
1265 | + actual_changed_keys, actual_new_keys = actual |
1266 | + expected_changed_tuples = [(e.name, e.version) |
1267 | + for e in expected_changed] |
1268 | + expected_new_tuples = [(e.name, e.version) for e in expected_new] |
1269 | + def get_tuples(source_keys): |
1270 | + tuples = [] |
1271 | + for source_key in source_keys: |
1272 | + source = getUtility(IPublishingSet).getByIdAndArchive( |
1273 | + source_key, archive, source=True) |
1274 | + self.assertNotEqual(source, None, "Got a non-existant " |
1275 | + "source publishing record: %d" % source_key) |
1276 | + naked_source = removeSecurityProxy(source) |
1277 | + tuples.append( |
1278 | + (naked_source.source_package_name, |
1279 | + naked_source.source_package_version)) |
1280 | + return tuples |
1281 | + actual_changed_tuples = get_tuples(actual_changed_keys) |
1282 | + actual_new_tuples = get_tuples(actual_new_keys) |
1283 | + self.assertEqual(expected_changed_tuples, actual_changed_tuples) |
1284 | + self.assertEqual(expected_new_tuples, actual_new_tuples) |
1285 | + |
1286 | + def testPackageSetDiffWithNothingNew(self): |
1287 | + """Test packageSetDiff.""" |
1288 | + package_info = PackageInfo( |
1289 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1290 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1291 | + diff = self.diffArchives(copy_archive, distroseries) |
1292 | + self.checkPackageDiff( |
1293 | + [], [], diff, distroseries.distribution.main_archive) |
1294 | + |
1295 | + def testPackageSetDiffWithNewPackages(self): |
1296 | + package_info = PackageInfo( |
1297 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1298 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1299 | + package_infos = [ |
1300 | + PackageInfo( |
1301 | + "apt", "1.2", status=PackagePublishingStatus.PUBLISHED), |
1302 | + PackageInfo( |
1303 | + "gcc", "4.5", status=PackagePublishingStatus.PENDING), |
1304 | + ] |
1305 | + self.createSourcePublications(package_infos, distroseries) |
1306 | + diff = self.diffArchives(copy_archive, distroseries) |
1307 | + self.checkPackageDiff( |
1308 | + [], package_infos, diff, distroseries.distribution.main_archive) |
1309 | + |
1310 | + def testPackageSetDiffWithChangedPackages(self): |
1311 | + package_infos = [ |
1312 | + PackageInfo( |
1313 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1314 | + PackageInfo( |
1315 | + "apt", "1.2", status=PackagePublishingStatus.PUBLISHED), |
1316 | + ] |
1317 | + copy_archive, distroseries = self.makeCopyArchive(package_infos) |
1318 | + package_infos = [ |
1319 | + PackageInfo( |
1320 | + "bzr", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1321 | + PackageInfo( |
1322 | + "apt", "1.3", status=PackagePublishingStatus.PENDING), |
1323 | + ] |
1324 | + self.createSourcePublications(package_infos, distroseries) |
1325 | + diff = self.diffArchives(copy_archive, distroseries) |
1326 | + self.checkPackageDiff( |
1327 | + package_infos, [], diff, distroseries.distribution.main_archive) |
1328 | + |
1329 | + def testPackageSetDiffWithBoth(self): |
1330 | + package_infos = [ |
1331 | + PackageInfo( |
1332 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1333 | + PackageInfo( |
1334 | + "apt", "1.2", status=PackagePublishingStatus.PUBLISHED), |
1335 | + ] |
1336 | + copy_archive, distroseries = self.makeCopyArchive(package_infos) |
1337 | + package_infos = [ |
1338 | + PackageInfo( |
1339 | + "bzr", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1340 | + PackageInfo( |
1341 | + "gcc", "1.3", status=PackagePublishingStatus.PENDING), |
1342 | + ] |
1343 | + self.createSourcePublications(package_infos, distroseries) |
1344 | + diff = self.diffArchives(copy_archive, distroseries) |
1345 | + self.checkPackageDiff( |
1346 | + [package_infos[0]], [package_infos[1]], diff, |
1347 | + distroseries.distribution.main_archive) |
1348 | + |
1349 | + |
1350 | + def mergeCopy(self, target_archive, target_distroseries, |
1351 | + source_archive=None, source_distroseries=None): |
1352 | + if source_distroseries is None: |
1353 | + source_distroseries = target_distroseries |
1354 | + if source_archive is None: |
1355 | + source_archive = source_distroseries.distribution.main_archive |
1356 | + source_location = PackageLocation( |
1357 | + source_archive, source_distroseries.distribution, |
1358 | + source_distroseries, PackagePublishingPocket.RELEASE) |
1359 | + target_location = PackageLocation( |
1360 | + target_archive, target_distroseries.distribution, |
1361 | + target_distroseries, PackagePublishingPocket.RELEASE) |
1362 | + cloner = getUtility(IPackageCloner) |
1363 | + return cloner.mergeCopy(source_location, target_location) |
1364 | + |
1365 | + def testMergeCopyNoChanges(self): |
1366 | + package_info = PackageInfo( |
1367 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1368 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1369 | + self.mergeCopy(copy_archive, distroseries) |
1370 | + self.checkCopiedSources( |
1371 | + copy_archive, distroseries, [package_info]) |
1372 | + |
1373 | + def testMergeCopyWithNewPackages(self): |
1374 | + package_info = PackageInfo( |
1375 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED) |
1376 | + copy_archive, distroseries = self.makeCopyArchive([package_info]) |
1377 | + package_infos = [ |
1378 | + PackageInfo( |
1379 | + "apt", "1.2", status=PackagePublishingStatus.PUBLISHED), |
1380 | + PackageInfo( |
1381 | + "gcc", "4.5", status=PackagePublishingStatus.PENDING), |
1382 | + ] |
1383 | + self.createSourcePublications(package_infos, distroseries) |
1384 | + self.mergeCopy(copy_archive, distroseries) |
1385 | + self.checkCopiedSources( |
1386 | + copy_archive, distroseries, [package_info] + package_infos) |
1387 | + |
1388 | + def testMergeCopyWithChangedPackages(self): |
1389 | + package_infos = [ |
1390 | + PackageInfo( |
1391 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1392 | + PackageInfo( |
1393 | + "apt", "1.2", status=PackagePublishingStatus.PUBLISHED), |
1394 | + ] |
1395 | + copy_archive, distroseries = self.makeCopyArchive(package_infos) |
1396 | + package_infos = [ |
1397 | + PackageInfo( |
1398 | + "bzr", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1399 | + PackageInfo( |
1400 | + "apt", "1.3", status=PackagePublishingStatus.PENDING), |
1401 | + ] |
1402 | + self.createSourcePublications(package_infos, distroseries) |
1403 | + self.mergeCopy(copy_archive, distroseries) |
1404 | + # Critically there is only one record for each info, as the |
1405 | + # others have been obsoleted. |
1406 | + self.checkCopiedSources( |
1407 | + copy_archive, distroseries, package_infos) |
1408 | + |
1409 | + def testMergeCopyWithBoth(self): |
1410 | + package_infos = [ |
1411 | + PackageInfo( |
1412 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1413 | + PackageInfo( |
1414 | + "apt", "1.2", status=PackagePublishingStatus.PUBLISHED), |
1415 | + ] |
1416 | + copy_archive, distroseries = self.makeCopyArchive(package_infos) |
1417 | + package_infos2 = [ |
1418 | + PackageInfo( |
1419 | + "bzr", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1420 | + PackageInfo( |
1421 | + "gcc", "1.3", status=PackagePublishingStatus.PENDING), |
1422 | + ] |
1423 | + self.createSourcePublications(package_infos2, distroseries) |
1424 | + self.mergeCopy(copy_archive, distroseries) |
1425 | + # Again bzr is obsoleted, gcc is added and apt remains. |
1426 | + self.checkCopiedSources( |
1427 | + copy_archive, distroseries, [package_infos[1]] + package_infos2) |
1428 | + |
1429 | + def setArchiveArchitectures(self, archive, proc_families): |
1430 | + """Associate the archive with the processor families.""" |
1431 | + aa_set = getUtility(IArchiveArchSet) |
1432 | + for proc_family in proc_families: |
1433 | + aa_set.new(archive, proc_family) |
1434 | + |
1435 | + def testMergeCopyCreatesBuilds(self): |
1436 | + package_infos = [ |
1437 | + PackageInfo( |
1438 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1439 | + PackageInfo( |
1440 | + "apt", "1.2", status=PackagePublishingStatus.PUBLISHED), |
1441 | + ] |
1442 | + proc_families = [ProcessorFamilySet().getByName("x86")] |
1443 | + copy_archive, distroseries = self.makeCopyArchive( |
1444 | + package_infos, proc_families=proc_families) |
1445 | + self.setArchiveArchitectures(copy_archive, proc_families) |
1446 | + package_infos2 = [ |
1447 | + PackageInfo( |
1448 | + "bzr", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1449 | + PackageInfo( |
1450 | + "gcc", "1.3", status=PackagePublishingStatus.PENDING), |
1451 | + ] |
1452 | + self.createSourcePublications(package_infos2, distroseries) |
1453 | + self.mergeCopy(copy_archive, distroseries) |
1454 | + # We get all builds, as superseding bzr doesn't cancel the |
1455 | + # build |
1456 | + self.checkBuilds(copy_archive, package_infos + package_infos2) |
1457 | + |
1458 | + def testMergeCopyCreatesNoBuildsWhenNoArchitectures(self): |
1459 | + package_infos = [ |
1460 | + PackageInfo( |
1461 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1462 | + ] |
1463 | + # We specify no processor families at creation time |
1464 | + copy_archive, distroseries = self.makeCopyArchive( |
1465 | + package_infos, proc_families=[]) |
1466 | + package_infos2 = [ |
1467 | + PackageInfo( |
1468 | + "bzr", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1469 | + ] |
1470 | + self.createSourcePublications(package_infos2, distroseries) |
1471 | + self.mergeCopy(copy_archive, distroseries) |
1472 | + # And so we get no builds at merge time |
1473 | + self.checkBuilds(copy_archive, []) |
1474 | + |
1475 | + def testMergeCopyCreatesBuildsForMultipleArchitectures(self): |
1476 | + package_infos = [ |
1477 | + PackageInfo( |
1478 | + "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), |
1479 | + PackageInfo( |
1480 | + "apt", "1.2", status=PackagePublishingStatus.PUBLISHED), |
1481 | + ] |
1482 | + distroseries = self.createSourceDistribution(package_infos) |
1483 | + # Create a DAS for a second family |
1484 | + amd64_family = ProcessorFamilySet().getByName("amd64") |
1485 | + self.factory.makeDistroArchSeries( |
1486 | + distroseries=distroseries, architecturetag="amd64", |
1487 | + processorfamily=amd64_family, supports_virtualized=True) |
1488 | + # The request builds for both families, so we expect two builds |
1489 | + # per source. |
1490 | + proc_families = [ProcessorFamilySet().getByName("x86"), amd64_family] |
1491 | + copy_archive = self.getTargetArchive(distroseries.distribution) |
1492 | + self.setArchiveArchitectures(copy_archive, proc_families) |
1493 | + self.copyArchive( |
1494 | + copy_archive, distroseries, proc_families=proc_families) |
1495 | + package_infos2 = [ |
1496 | + PackageInfo( |
1497 | + "bzr", "2.2", status=PackagePublishingStatus.PUBLISHED), |
1498 | + PackageInfo( |
1499 | + "gcc", "1.3", status=PackagePublishingStatus.PENDING), |
1500 | + ] |
1501 | + self.createSourcePublications(package_infos2, distroseries) |
1502 | + self.mergeCopy(copy_archive, distroseries) |
1503 | + # We get all builds twice, one for each architecture. |
1504 | + self.checkBuilds( |
1505 | + copy_archive, |
1506 | + package_infos + package_infos + package_infos2 + package_infos2) |
James, thanks for doing this. Do you need someone to land this for you?