~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/soyuz/scripts/tests/test_populatearchive.py

  • Committer: Launchpad Patch Queue Manager
  • Date: 2010-07-16 17:15:56 UTC
  • mfrom: (11017.2.12 test-package-cloner)
  • Revision ID: launchpad@pqm.canonical.com-20100716171556-lqd8diiac9n493rq
[r=rockstar][ui=none] Make PackageCloner create builds,
        and add some tests for it.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
from lp.buildmaster.interfaces.buildbase import BuildStatus
22
22
from lp.registry.interfaces.distribution import IDistributionSet
23
23
from lp.registry.interfaces.person import IPersonSet
24
 
from lp.registry.interfaces.pocket import PackagePublishingPocket
25
24
from lp.services.job.interfaces.job import JobStatus
26
25
from lp.soyuz.interfaces.archive import ArchivePurpose, IArchiveSet
27
26
from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
28
 
from lp.soyuz.interfaces.packagecopyrequest import (
29
 
    IPackageCopyRequestSet, PackageCopyStatus)
30
27
from lp.soyuz.interfaces.publishing import PackagePublishingStatus
31
 
from lp.soyuz.model.processor import ProcessorFamilySet
32
28
from lp.soyuz.scripts.ftpmaster import PackageLocationError, SoyuzScriptError
33
29
from lp.soyuz.scripts.populate_archive import ArchivePopulator
34
30
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
41
37
    return pub.sourcepackagerelease.sourcepackagename
42
38
 
43
39
 
44
 
class PackageInfo:
45
 
 
46
 
    def __init__(self, name, version,
47
 
                 status=PackagePublishingStatus.PUBLISHED, component="main",
48
 
                 arch_hint=None):
49
 
        self.name = name
50
 
        self.version = version
51
 
        self.status = status
52
 
        self.component = component
53
 
        self.arch_hint = arch_hint
54
 
 
55
 
 
56
40
class TestPopulateArchiveScript(TestCaseWithFactory):
57
41
    """Test the copy-package.py script."""
58
42
 
86
70
        stdout, stderr = process.communicate()
87
71
        return (process.returncode, stdout, stderr)
88
72
 
 
73
    def getScript(self, test_args=None):
 
74
        """Return an ArchivePopulator instance."""
 
75
        if test_args is None:
 
76
            test_args = []
 
77
        script = ArchivePopulator("test copy archives", test_args=test_args)
 
78
        script.logger = QuietFakeLogger()
 
79
        script.txn = self.layer.txn
 
80
        return script
 
81
 
89
82
    def testCopyArchiveCreation(self):
90
83
        """Start archive population, check data before and after.
91
84
 
151
144
 
152
145
        self.assertEqual(build_spns, self.expected_build_spns)
153
146
 
154
 
    def createSourceDistroSeries(self):
155
 
        """Create a DistroSeries suitable for copying.
156
 
 
157
 
        Creates a distroseries with a DistroArchSeries and nominatedarchindep,
158
 
        which makes it suitable for copying because it will create some builds.
159
 
        """
160
 
        distro_name = "foobuntu"
161
 
        distro = self.factory.makeDistribution(name=distro_name)
162
 
        distroseries_name = "maudlin"
163
 
        distroseries = self.factory.makeDistroSeries(
164
 
            distribution=distro, name=distroseries_name)
165
 
        das = self.factory.makeDistroArchSeries(
166
 
            distroseries=distroseries, architecturetag="i386",
167
 
            processorfamily=ProcessorFamilySet().getByName("x86"),
168
 
            supports_virtualized=True)
169
 
        distroseries.nominatedarchindep = das
170
 
        return distroseries
171
 
 
172
 
    def createTargetOwner(self):
173
 
        """Create a person suitable to own a copy archive."""
174
 
        person_name = "copy-archive-owner"
175
 
        owner = self.factory.makePerson(name=person_name)
176
 
        return owner
177
 
 
178
 
    def getTargetArchiveName(self, distribution):
179
 
        """Get a suitable name for a copy archive.
180
 
 
181
 
        It also checks that the archive doesn't currently exist.
182
 
        """
183
 
        archive_name = "msa%s" % int(time.time())
184
 
        copy_archive = getUtility(IArchiveSet).getByDistroPurpose(
185
 
            distribution, ArchivePurpose.COPY, archive_name)
186
 
        # This is a sanity check: a copy archive with this name should not
187
 
        # exist yet.
188
 
        self.assertIs(None, copy_archive)
189
 
        return archive_name
190
 
 
191
 
    def createSourcePublication(self, info, distroseries):
192
 
        """Create a SourcePackagePublishingHistory based on a PackageInfo."""
193
 
        if info.arch_hint is None:
194
 
            arch_hint = "any"
195
 
        else:
196
 
            arch_hint = info.arch_hint
197
 
 
198
 
        self.factory.makeSourcePackagePublishingHistory(
199
 
            sourcepackagename=self.factory.getOrMakeSourcePackageName(
200
 
                name=info.name),
201
 
            distroseries=distroseries, component=self.factory.makeComponent(
202
 
                info.component),
203
 
            version=info.version, architecturehintlist=arch_hint,
204
 
            archive=distroseries.distribution.main_archive,
205
 
            status=info.status, pocket=PackagePublishingPocket.RELEASE)
206
 
 
207
 
    def createSourcePublications(self, package_infos, distroseries):
208
 
        """Create a source publication for each item in package_infos."""
209
 
        for package_info in package_infos:
210
 
            self.createSourcePublication(package_info, distroseries)
211
 
 
212
 
    def getScript(self, test_args=None):
213
 
        """Return an ArchivePopulator instance."""
214
 
        if test_args is None:
215
 
            test_args = []
216
 
        script = ArchivePopulator("test copy archives", test_args=test_args)
217
 
        script.logger = QuietFakeLogger()
218
 
        script.txn = self.layer.txn
219
 
        return script
220
 
 
221
 
    def copyArchive(self, distroseries, archive_name, owner,
222
 
        architectures=None, component="main", from_user=None,
223
 
        from_archive=None, packageset_names=None, nonvirtualized=False):
224
 
        """Run the copy-archive script."""
225
 
        extra_args = [
226
 
            '--from-distribution', distroseries.distribution.name,
227
 
            '--from-suite', distroseries.name,
228
 
            '--to-distribution', distroseries.distribution.name,
229
 
            '--to-suite', distroseries.name,
230
 
            '--to-archive', archive_name,
231
 
            '--to-user', owner.name,
232
 
            '--reason',
233
 
            '"copy archive from %s"' % datetime.ctime(datetime.utcnow()),
234
 
            '--component', component,
235
 
            ]
236
 
 
237
 
        if from_user is not None:
238
 
            extra_args.extend(["--from-user", from_user])
239
 
 
240
 
        if from_archive is not None:
241
 
            extra_args.extend(["--from-archive", from_archive])
242
 
 
243
 
        if architectures is None:
244
 
            architectures = ["386"]
245
 
 
246
 
        if nonvirtualized:
247
 
            extra_args.extend(["--nonvirtualized"])
248
 
 
249
 
        for architecture in architectures:
250
 
            extra_args.extend(['-a', architecture])
251
 
 
252
 
        if packageset_names is None:
253
 
            packageset_names = []
254
 
 
255
 
        for packageset_name in packageset_names:
256
 
            extra_args.extend(['--package-set', packageset_name])
257
 
 
258
 
        script = self.getScript(test_args=extra_args)
259
 
        script.mainTask()
260
 
 
261
 
        # Make sure the copy archive with the desired name was
262
 
        # created
263
 
        copy_archive = getUtility(IArchiveSet).getByDistroPurpose(
264
 
            distroseries.distribution, ArchivePurpose.COPY, archive_name)
265
 
        self.assertTrue(copy_archive is not None)
266
 
 
267
 
        # Ascertain that the new copy archive was created with the 'enabled'
268
 
        # flag turned off.
269
 
        self.assertFalse(copy_archive.enabled)
270
 
 
271
 
        # Assert the virtualization is correct.
272
 
        virtual = not nonvirtualized
273
 
        self.assertEqual(copy_archive.require_virtualized, virtual)
274
 
 
275
 
        return copy_archive
276
 
 
277
 
    def checkCopiedSources(self, archive, distroseries, expected):
278
 
        """Check the sources published in an archive against an expected set.
279
 
 
280
 
        Given an archive and a target distroseries the sources published in
281
 
        that distroseries are checked against a set of PackageInfo to
282
 
        ensure that the correct package names and versions are published.
283
 
        """
284
 
        expected_set = set([(info.name, info.version) for info in expected])
285
 
        sources = archive.getPublishedSources(
286
 
            distroseries=distroseries, status=self.pending_statuses)
287
 
        actual_set = set()
288
 
        for source in sources:
289
 
            source = removeSecurityProxy(source)
290
 
            actual_set.add(
291
 
                (source.source_package_name, source.source_package_version))
292
 
        self.assertEqual(expected_set, actual_set)
293
 
 
294
 
    def createSourceDistribution(self, package_infos):
295
 
        """Create a distribution to be the source of a copy archive."""
296
 
        distroseries = self.createSourceDistroSeries()
297
 
        self.createSourcePublications(package_infos, distroseries)
298
 
        return distroseries
299
 
 
300
 
    def makeCopyArchive(self, package_infos, component="main",
301
 
                        nonvirtualized=False):
302
 
        """Make a copy archive based on a new distribution."""
303
 
        owner = self.createTargetOwner()
304
 
        distroseries = self.createSourceDistribution(package_infos)
305
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
306
 
        copy_archive = self.copyArchive(
307
 
            distroseries, archive_name, owner, component=component,
308
 
            nonvirtualized=nonvirtualized)
309
 
        return (copy_archive, distroseries)
310
 
 
311
 
    def checkBuilds(self, archive, package_infos):
312
 
        """Check the build records pending in an archive.
313
 
 
314
 
        Given a set of PackageInfo objects check that each has a build
315
 
        created for it.
316
 
        """
317
 
        expected_builds = list(
318
 
            [(info.name, info.version) for info in package_infos])
319
 
        builds = list(
320
 
            getUtility(IBinaryPackageBuildSet).getBuildsForArchive(
321
 
            archive, status=BuildStatus.NEEDSBUILD))
322
 
        actual_builds = list()
323
 
        for build in builds:
324
 
            naked_build = removeSecurityProxy(build)
325
 
            spr = naked_build.source_package_release
326
 
            actual_builds.append((spr.name, spr.version))
327
 
        self.assertEqual(sorted(expected_builds), sorted(actual_builds))
328
 
 
329
 
    def testCopyArchiveRunScript(self):
330
 
        """Check that we can exec the script to copy an archive."""
331
 
        package_info = PackageInfo(
332
 
            "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED)
333
 
        owner = self.createTargetOwner()
334
 
        distroseries = self.createSourceDistribution([package_info])
335
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
336
 
        # We must commit as we are going to exec a script that will run
337
 
        # in a different transaction and must be able to see the
338
 
        # objects we just created.
339
 
        self.layer.commit()
340
 
 
341
 
        extra_args = [
342
 
            '--from-distribution', distroseries.distribution.name,
343
 
            '--from-suite', distroseries.name,
344
 
            '--to-distribution', distroseries.distribution.name,
345
 
            '--to-suite', distroseries.name,
346
 
            '--to-archive', archive_name,
347
 
            '--to-user', owner.name,
348
 
            '--reason',
349
 
            '"copy archive from %s"' % datetime.ctime(datetime.utcnow()),
350
 
            '--component', "main",
351
 
            '-a', '386',
352
 
            ]
353
 
        (exitcode, out, err) = self.runWrapperScript(extra_args)
354
 
        # Check for zero exit code.
355
 
        self.assertEqual(
356
 
            exitcode, 0, "\n=> %s\n=> %s\n=> %s\n" % (exitcode, out, err))
357
 
        # Make sure the copy archive with the desired name was
358
 
        # created
359
 
        copy_archive = getUtility(IArchiveSet).getByDistroPurpose(
360
 
            distroseries.distribution, ArchivePurpose.COPY, archive_name)
361
 
        self.assertTrue(copy_archive is not None)
362
 
 
363
 
        # Ascertain that the new copy archive was created with the 'enabled'
364
 
        # flag turned off.
365
 
        self.assertFalse(copy_archive.enabled)
366
 
 
367
 
        # Also, make sure that the builds for the new copy archive will be
368
 
        # carried out on non-virtual builders.
369
 
        self.assertTrue(copy_archive.require_virtualized)
370
 
        self.checkCopiedSources(
371
 
            copy_archive, distroseries, [package_info])
372
 
 
373
 
    def testCopyArchiveCreateCopiesPublished(self):
374
 
        """Test that PUBLISHED sources are copied."""
375
 
        package_info = PackageInfo(
376
 
            "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED)
377
 
        copy_archive, distroseries = self.makeCopyArchive([package_info])
378
 
        self.checkCopiedSources(
379
 
            copy_archive, distroseries, [package_info])
380
 
 
381
 
    def testCopyArchiveCreateCopiesPending(self):
382
 
        """Test that PENDING sources are copied."""
383
 
        package_info = PackageInfo(
384
 
            "bzr", "2.1", status=PackagePublishingStatus.PENDING)
385
 
        copy_archive, distroseries = self.makeCopyArchive([package_info])
386
 
        self.checkCopiedSources(
387
 
            copy_archive, distroseries, [package_info])
388
 
 
389
 
    def testCopyArchiveCreateDoesntCopySuperseded(self):
390
 
        """Test that SUPERSEDED sources are not copied."""
391
 
        package_info = PackageInfo(
392
 
            "bzr", "2.1", status=PackagePublishingStatus.SUPERSEDED)
393
 
        copy_archive, distroseries = self.makeCopyArchive([package_info])
394
 
        self.checkCopiedSources(
395
 
            copy_archive, distroseries, [])
396
 
 
397
 
    def testCopyArchiveCreateDoesntCopyDeleted(self):
398
 
        """Test that DELETED sources are not copied."""
399
 
        package_info = PackageInfo(
400
 
            "bzr", "2.1", status=PackagePublishingStatus.DELETED)
401
 
        copy_archive, distroseries = self.makeCopyArchive([package_info])
402
 
        self.checkCopiedSources(
403
 
            copy_archive, distroseries, [])
404
 
 
405
 
    def testCopyArchiveCreateDoesntCopyObsolete(self):
406
 
        """Test that OBSOLETE sources are not copied."""
407
 
        package_info = PackageInfo(
408
 
            "bzr", "2.1", status=PackagePublishingStatus.OBSOLETE)
409
 
        copy_archive, distroseries = self.makeCopyArchive([package_info])
410
 
        self.checkCopiedSources(
411
 
            copy_archive, distroseries, [])
412
 
 
413
 
    def testCopyArchiveCreatesBuilds(self):
414
 
        """Test that a copy archive creates builds for the copied packages."""
415
 
        package_info = PackageInfo(
416
 
            "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED)
417
 
        copy_archive, distroseries = self.makeCopyArchive([package_info])
418
 
        self.checkBuilds(copy_archive, [package_info])
419
 
 
420
 
    def testCopyArchiveArchTagNotAvailableInSource(self):
421
 
        """Test creating a copy archive for an arch not in the source.
422
 
 
423
 
        If we request a copy to an architecture that doesn't have
424
 
        a DistroArchSeries in the source then we won't get any builds
425
 
        created in the copy archive.
426
 
        """
427
 
        family = self.factory.makeProcessorFamily(name="armel")
428
 
        self.factory.makeProcessor(family=family, name="armel")
429
 
        package_info = PackageInfo(
430
 
            "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED)
431
 
        owner = self.createTargetOwner()
432
 
        # Creates an archive with just x86
433
 
        distroseries = self.createSourceDistribution([package_info])
434
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
435
 
        # Different architecture, so there won't be any builds
436
 
        copy_archive = self.copyArchive(
437
 
            distroseries, archive_name, owner, architectures=["armel"])
438
 
        self.checkBuilds(copy_archive, [])
439
 
 
440
 
        # Also, make sure the package copy request status was updated.
441
 
        [pcr] = getUtility(
442
 
            IPackageCopyRequestSet).getByTargetArchive(copy_archive)
443
 
        self.assertTrue(pcr.status == PackageCopyStatus.COMPLETE)
444
 
 
445
 
        # This date is set when the copy request makes the transition to
446
 
        # the "in progress" state.
447
 
        self.assertTrue(pcr.date_started is not None)
448
 
        # This date is set when the copy request makes the transition to
449
 
        # the "completed" state.
450
 
        self.assertTrue(pcr.date_completed is not None)
451
 
        self.assertTrue(pcr.date_started <= pcr.date_completed)
452
 
 
453
 
    def testMultipleArchTagsWithSubsetInSource(self):
454
 
        """Try copy archive population with multiple architecture tags.
455
 
 
456
 
        The user may specify a number of given architecture tags on the
457
 
        command line.
458
 
        The script should create build records only for the specified
459
 
        architecture tags that are supported by the destination distro series.
460
 
 
461
 
        In this (test) case the script should create the build records for the
462
 
        '386' architecture.
463
 
        """
464
 
        family = self.factory.makeProcessorFamily(name="armel")
465
 
        self.factory.makeProcessor(family=family, name="armel")
466
 
        package_info = PackageInfo(
467
 
            "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED)
468
 
        owner = self.createTargetOwner()
469
 
        # Creates an archive with just x86
470
 
        distroseries = self.createSourceDistribution([package_info])
471
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
472
 
        # There is only a DAS for i386, so armel won't produce any
473
 
        # builds
474
 
        copy_archive = self.copyArchive(
475
 
            distroseries, archive_name, owner,
476
 
            architectures=["386", "armel"])
477
 
        self.checkBuilds(copy_archive, [package_info])
478
 
 
479
 
    def testCopyArchiveCreatesSubsetOfBuilds(self):
480
 
        """Create a copy archive with a subset of the architectures.
481
 
 
482
 
        We copy from an archive with multiple architecture DistroArchSeries,
483
 
        but request only one of those architectures in the target,
484
 
        so we only get builds for that one architecture.
485
 
        """
486
 
        package_info = PackageInfo(
487
 
            "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED)
488
 
        owner = self.createTargetOwner()
489
 
        distroseries = self.createSourceDistribution([package_info])
490
 
        self.factory.makeDistroArchSeries(
491
 
            distroseries=distroseries, architecturetag="amd64",
492
 
            processorfamily=ProcessorFamilySet().getByName("amd64"),
493
 
            supports_virtualized=True)
494
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
495
 
        copy_archive = self.copyArchive(
496
 
            distroseries, archive_name, owner,
497
 
            architectures=["386"])
498
 
        # We only get a single build, as we only requested 386, not
499
 
        # amd64 too
500
 
        self.checkBuilds(copy_archive, [package_info])
501
 
 
502
 
    def testNoBuildsForArchAll(self):
503
 
        # If we have a copy for an architecture that is not the
504
 
        # nominatedarchindep architecture, then we don't want to create
505
 
        # builds for arch-all packages, as they can't be built at all
506
 
        # and createMissingBuilds blows up when it checks that.
507
 
        package_info = PackageInfo(
508
 
            "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED,
509
 
            arch_hint="all")
510
 
        owner = self.createTargetOwner()
511
 
        distroseries = self.createSourceDistribution([package_info])
512
 
        self.factory.makeDistroArchSeries(
513
 
            distroseries=distroseries, architecturetag="amd64",
514
 
            processorfamily=ProcessorFamilySet().getByName("amd64"),
515
 
            supports_virtualized=True)
516
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
517
 
        copy_archive = self.copyArchive(
518
 
            distroseries, archive_name, owner,
519
 
            architectures=["amd64"])
520
 
        # We don't get any builds since amd64 is not the
521
 
        # nomindatedarchindep, i386 is.
522
 
        self.assertEqual(
523
 
            distroseries.nominatedarchindep.architecturetag, "i386")
524
 
        self.checkBuilds(copy_archive, [])
525
 
 
526
 
    def testMultipleArchTags(self):
527
 
        """Test copying an archive with multiple architectures.
528
 
 
529
 
        We create a source with two architectures, and then request
530
 
        a copy of both, so we get a build for each of those architectures.
531
 
        """
532
 
        package_info = PackageInfo(
533
 
            "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED)
534
 
        owner = self.createTargetOwner()
535
 
        distroseries = self.createSourceDistribution([package_info])
536
 
        self.factory.makeDistroArchSeries(
537
 
            distroseries=distroseries, architecturetag="amd64",
538
 
            processorfamily=ProcessorFamilySet().getByName("amd64"),
539
 
            supports_virtualized=True)
540
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
541
 
        copy_archive = self.copyArchive(
542
 
            distroseries, archive_name, owner,
543
 
            architectures=["386", "amd64"])
544
 
        self.checkBuilds(copy_archive, [package_info, package_info])
545
 
 
546
 
    def testCopyArchiveCopiesRightComponents(self):
547
 
        """Test that packages from the right components are copied.
548
 
 
549
 
        When copying you specify a component, that component should
550
 
        limit the packages copied. We create a source in main and one in
551
 
        universe, and then copy with --component main, and expect to see
552
 
        only main in the copy.
553
 
        """
554
 
        package_info_universe = PackageInfo(
555
 
                "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED,
556
 
                component="universe")
557
 
        package_info_main = PackageInfo(
558
 
                "apt", "2.2", status=PackagePublishingStatus.PUBLISHED,
559
 
                component="main")
560
 
        package_infos_both = [package_info_universe, package_info_main]
561
 
        copy_archive, distroseries = self.makeCopyArchive(
562
 
            package_infos_both, component="main")
563
 
        self.checkBuilds(copy_archive, [package_info_main])
564
 
 
565
 
    def testCopyArchiveSubsetsBasedOnPackageset(self):
566
 
        """Test that --package-set limits the sources copied."""
567
 
        package_infos = [
568
 
            PackageInfo(
569
 
                "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED),
570
 
            PackageInfo(
571
 
                "apt", "2.2", status=PackagePublishingStatus.PUBLISHED),
572
 
            ]
573
 
        owner = self.createTargetOwner()
574
 
        distroseries = self.createSourceDistribution(package_infos)
575
 
        packageset_name = u"apt-packageset"
576
 
        spn = self.factory.getOrMakeSourcePackageName(name="apt")
577
 
        self.factory.makePackageset(
578
 
            name=packageset_name, distroseries=distroseries, packages=(spn,))
579
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
580
 
        copy_archive = self.copyArchive(
581
 
            distroseries, archive_name, owner,
582
 
            packageset_names=[packageset_name])
583
 
        self.checkCopiedSources(
584
 
            copy_archive, distroseries, [package_infos[1]])
585
 
 
586
 
    def testCopyArchiveUnionsPackagesets(self):
587
 
        """Test that package sets are unioned when copying archives."""
588
 
        package_infos = [
589
 
            PackageInfo(
590
 
                "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED),
591
 
            PackageInfo(
592
 
                "apt", "2.2", status=PackagePublishingStatus.PUBLISHED),
593
 
            PackageInfo(
594
 
                "gcc", "4.5", status=PackagePublishingStatus.PUBLISHED),
595
 
            ]
596
 
        owner = self.createTargetOwner()
597
 
        distroseries = self.createSourceDistribution(package_infos)
598
 
        apt_packageset_name = u"apt-packageset"
599
 
        apt_spn = self.factory.getOrMakeSourcePackageName(name="apt")
600
 
        gcc_packageset_name = u"gcc-packageset"
601
 
        gcc_spn = self.factory.getOrMakeSourcePackageName(name="gcc")
602
 
        self.factory.makePackageset(
603
 
            name=apt_packageset_name, distroseries=distroseries,
604
 
            packages=(apt_spn,))
605
 
        self.factory.makePackageset(
606
 
            name=gcc_packageset_name, distroseries=distroseries,
607
 
            packages=(gcc_spn,))
608
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
609
 
        copy_archive = self.copyArchive(
610
 
            distroseries, archive_name, owner,
611
 
            packageset_names=[apt_packageset_name, gcc_packageset_name])
612
 
        self.checkCopiedSources(
613
 
            copy_archive, distroseries, package_infos[1:])
614
 
 
615
 
    def testCopyArchiveRecursivelyCopiesPackagesets(self):
616
 
        """Test that package set copies include subsets."""
617
 
        package_infos = [
618
 
            PackageInfo(
619
 
                "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED),
620
 
            PackageInfo(
621
 
                "apt", "2.2", status=PackagePublishingStatus.PUBLISHED),
622
 
            PackageInfo(
623
 
                "gcc", "4.5", status=PackagePublishingStatus.PUBLISHED),
624
 
            ]
625
 
        owner = self.createTargetOwner()
626
 
        distroseries = self.createSourceDistribution(package_infos)
627
 
        apt_packageset_name = u"apt-packageset"
628
 
        apt_spn = self.factory.getOrMakeSourcePackageName(name="apt")
629
 
        gcc_packageset_name = u"gcc-packageset"
630
 
        gcc_spn = self.factory.getOrMakeSourcePackageName(name="gcc")
631
 
        apt_packageset = self.factory.makePackageset(
632
 
            name=apt_packageset_name, distroseries=distroseries,
633
 
            packages=(apt_spn,))
634
 
        gcc_packageset = self.factory.makePackageset(
635
 
            name=gcc_packageset_name, distroseries=distroseries,
636
 
            packages=(gcc_spn,))
637
 
        apt_packageset.add((gcc_packageset,))
638
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
639
 
        copy_archive = self.copyArchive(
640
 
            distroseries, archive_name, owner,
641
 
            packageset_names=[apt_packageset_name])
642
 
        self.checkCopiedSources(
643
 
            copy_archive, distroseries, package_infos[1:])
644
 
 
645
 
    def testCopyFromPPA(self):
646
 
        """Test we can create a copy archive with a PPA as the source."""
647
 
        ppa_owner_name = "ppa-owner"
648
 
        ppa_name = "ppa"
649
 
        ppa_owner = self.factory.makePerson(name=ppa_owner_name)
650
 
        distroseries = self.createSourceDistroSeries()
651
 
        ppa = self.factory.makeArchive(
652
 
            name=ppa_name, purpose=ArchivePurpose.PPA,
653
 
            distribution=distroseries.distribution, owner=ppa_owner)
654
 
        package_info = PackageInfo(
655
 
                "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED,
656
 
                component="universe")
657
 
        self.factory.makeSourcePackagePublishingHistory(
658
 
            sourcepackagename=self.factory.getOrMakeSourcePackageName(
659
 
                name=package_info.name),
660
 
            distroseries=distroseries, component=self.factory.makeComponent(
661
 
                package_info.component),
662
 
            version=package_info.version, archive=ppa,
663
 
            status=package_info.status, architecturehintlist='any',
664
 
            pocket=PackagePublishingPocket.RELEASE)
665
 
        owner = self.createTargetOwner()
666
 
        archive_name = self.getTargetArchiveName(distroseries.distribution)
667
 
        copy_archive = self.copyArchive(
668
 
            distroseries, archive_name, owner, from_user=ppa_owner_name,
669
 
            from_archive=ppa_name, component=package_info.component)
670
 
        self.checkCopiedSources(
671
 
            copy_archive, distroseries, [package_info])
672
 
 
673
147
    def runScript(
674
148
        self, archive_name=None, suite='hoary', user='salgado',
675
149
        exists_before=None, exists_after=None, exception_type=None,
676
150
        exception_text=None, extra_args=None, copy_archive_name=None,
677
 
        reason=None, output_substr=None):
 
151
        reason=None, output_substr=None, nonvirtualized=False):
678
152
        """Run the script to test.
679
153
 
680
154
        :type archive_name: `str`
748
222
            reason = "copy archive, %s" % datetime.ctime(datetime.utcnow())
749
223
            script_args.extend(['--reason', reason])
750
224
 
 
225
        if nonvirtualized:
 
226
            script_args.append('--nonvirtualized')
 
227
 
751
228
        if extra_args is not None:
752
229
            script_args.extend(extra_args)
753
230
 
847
324
            exception_text="Could not find packageset No such package set"
848
325
            " (in the specified distro series): '%s'." % unknown_packageset)
849
326
 
 
327
    def testNonvirtualized(self):
 
328
        """--nonvirtualized means the archive won't require virtualization."""
 
329
        copy_archive = self.runScript(
 
330
            archive_name="copy-archive-test", exists_before=False,
 
331
            exists_after=True, nonvirtualized=True,
 
332
            extra_args=['-a', '386'])
 
333
        self.assertFalse(copy_archive.require_virtualized)
 
334
 
850
335
    def testPackagesetDelta(self):
851
336
        """Try to calculate the delta between two source package sets."""
852
337
        hoary = getUtility(IDistributionSet)['ubuntu']['hoary']