~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/archivepublisher/tests/test_dominator.py

  • Committer: Guilherme Salgado
  • Date: 2010-07-23 08:50:49 UTC
  • mfrom: (11206 launchpad)
  • mto: This revision was merged to the branch mainline in revision 11220.
  • Revision ID: salgado@canonical.com-20100723085049-4m2tmvujxsw2ns40
mergeĀ mainline

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
__metaclass__ = type
7
7
 
8
8
import datetime
9
 
import pytz
10
 
 
11
 
from zope.component import getUtility
12
9
 
13
10
from lp.archivepublisher.domination import Dominator
14
11
from lp.archivepublisher.publishing import Publisher
15
12
from canonical.database.sqlbase import flush_database_updates
16
13
from lp.registry.interfaces.series import SeriesStatus
17
 
from lp.soyuz.interfaces.component import IComponentSet
18
 
from lp.registry.interfaces.person import IPersonSet
19
 
from lp.registry.interfaces.pocket import PackagePublishingPocket
20
14
from lp.soyuz.interfaces.publishing import PackagePublishingStatus
21
15
from lp.soyuz.tests.test_publishing import TestNativePublishingBase
22
16
 
24
18
class TestDominator(TestNativePublishingBase):
25
19
    """Test Dominator class."""
26
20
 
 
21
    def createSourceAndBinaries(self, version):
 
22
        """Create a source and binaries with the given version."""
 
23
        source = self.getPubSource(
 
24
            version=version,
 
25
            status=PackagePublishingStatus.PUBLISHED)
 
26
        binaries = self.getPubBinaries(
 
27
            pub_source=source,
 
28
            status=PackagePublishingStatus.PUBLISHED)
 
29
        return (source, binaries)
 
30
 
27
31
    def createSimpleDominationContext(self):
28
32
        """Create simple domination context.
29
33
 
39
43
 
40
44
        Note that as an optimization the binaries list is already unpacked.
41
45
        """
42
 
        foo_10_source = self.getPubSource(
43
 
            version='1.0', architecturehintlist='i386',
44
 
            status=PackagePublishingStatus.PUBLISHED)
45
 
        foo_10_binaries = self.getPubBinaries(
46
 
            pub_source=foo_10_source,
47
 
            status=PackagePublishingStatus.PUBLISHED)
48
 
 
49
 
        foo_11_source = self.getPubSource(
50
 
            version='1.1', architecturehintlist='i386',
51
 
            status=PackagePublishingStatus.PUBLISHED)
52
 
        foo_11_binaries = self.getPubBinaries(
53
 
            pub_source=foo_11_source,
54
 
            status=PackagePublishingStatus.PUBLISHED)
55
 
 
56
 
        dominant_source = foo_11_source
57
 
        dominant_binaries = [pub for pub in foo_11_binaries]
58
 
 
59
 
        dominated_source = foo_10_source
60
 
        dominated_binaries = [pub for pub in foo_10_binaries]
61
 
 
62
 
        return (dominant_source, dominant_binaries[0],
63
 
                dominated_source, dominated_binaries[0])
64
 
 
65
 
    def testSourceDomination(self):
66
 
        """Test source domination procedure."""
 
46
        foo_10_source, foo_10_binaries = self.createSourceAndBinaries('1.0')
 
47
        foo_11_source, foo_11_binaries = self.createSourceAndBinaries('1.1')
 
48
        return (foo_11_source, foo_11_binaries[0],
 
49
                foo_10_source, foo_10_binaries[0])
 
50
 
 
51
    def dominateAndCheck(self, dominant, dominated, supersededby):
67
52
        dominator = Dominator(self.logger, self.ubuntutest.main_archive)
68
53
 
69
 
        [dominant_source, dominant_binary, dominated_source,
70
 
         dominated_binary] = self.createSimpleDominationContext()
71
 
 
72
 
        # The _dominate* test methods require a dictionary where the source
 
54
        # The _dominate* test methods require a dictionary where the
73
55
        # package name is the key. The key's value is a list of
74
56
        # source or binary packages representing dominant, the first element
75
57
        # and dominated, the subsequents.
76
 
        source_input = {'foo': [dominant_source, dominated_source]}
 
58
        pubs = {'foo': [dominant, dominated]}
77
59
 
78
 
        dominator._dominateSource(source_input)
 
60
        dominator._dominatePublications(pubs)
79
61
        flush_database_updates()
80
62
 
81
63
        # The dominant version remains correctly published.
82
 
        dominant = self.checkSourcePublication(
83
 
            dominant_source, PackagePublishingStatus.PUBLISHED)
 
64
        self.checkPublication(dominant, PackagePublishingStatus.PUBLISHED)
84
65
        self.assertTrue(dominant.supersededby is None)
85
66
        self.assertTrue(dominant.datesuperseded is None)
86
67
 
87
68
        # The dominated version is correctly dominated.
88
 
        dominated = self.checkSourcePublication(
89
 
            dominated_source, PackagePublishingStatus.SUPERSEDED)
90
 
        self.assertEqual(
91
 
            dominated.supersededby, dominant.sourcepackagerelease)
92
 
        self.checkPastDate(dominated.datesuperseded)
93
 
 
94
 
    def testEmptySourceDomination(self):
95
 
        """Source domination asserts for not empty input list."""
96
 
        dominator = Dominator(self.logger, self.ubuntutest.main_archive)
97
 
        source_input = {'foo': []}
98
 
        self.assertRaises(
99
 
            AssertionError, dominator._dominateSource, source_input)
100
 
 
101
 
    def testBinariesDomination(self):
102
 
        """Test overall binary domination procedure."""
103
 
        dominator = Dominator(self.logger, self.ubuntutest.main_archive)
104
 
 
105
 
        [dominant_source, dominant, dominated_source,
106
 
         dominated] = self.createSimpleDominationContext()
107
 
 
108
 
        # See comment about domination input format and ordering above.
109
 
        binary_input = {'foo-bin': [dominant, dominated]}
110
 
 
111
 
        dominator._dominateBinaries(binary_input)
112
 
        flush_database_updates()
113
 
 
114
 
        # Dominant version remains correctly published.
115
 
        dominant = self.checkBinaryPublication(
116
 
            dominant, PackagePublishingStatus.PUBLISHED)
117
 
        self.assertTrue(dominant.supersededby is None)
118
 
        self.assertTrue(dominant.datesuperseded is None)
119
 
 
120
 
        # Dominated version is correctly dominated.
121
 
        dominated = self.checkBinaryPublication(
122
 
            dominated, PackagePublishingStatus.SUPERSEDED)
123
 
        self.assertEqual(
124
 
            dominated.supersededby, dominant.binarypackagerelease.build)
125
 
        self.checkPastDate(dominated.datesuperseded)
126
 
 
127
 
    def testEmptyBinaryDomination(self):
128
 
        """Binaries domination asserts not empty input list."""
129
 
        dominator = Dominator(self.logger, self.ubuntutest.main_archive)
130
 
        binary_input = {'foo-bin': []}
131
 
        self.assertRaises(
132
 
            AssertionError, dominator._dominateBinaries, binary_input)
133
 
 
134
 
    def testBinaryDomination(self):
135
 
        """Test binary domination unit procedure."""
136
 
        dominator = Dominator(self.logger, self.ubuntutest.main_archive)
137
 
 
138
 
        [dominant_source, dominant, dominated_source,
139
 
         dominated] = self.createSimpleDominationContext()
140
 
 
141
 
        dominator._dominateBinary(dominated, dominant)
142
 
        flush_database_updates()
143
 
 
144
 
        dominated = self.checkBinaryPublication(
145
 
            dominated, PackagePublishingStatus.SUPERSEDED)
146
 
        self.assertEqual(
147
 
            dominated.supersededby, dominant.binarypackagerelease.build)
148
 
        self.checkPastDate(dominated.datesuperseded)
149
 
 
150
 
    def testBinaryDominationAssertsPendingOrPublished(self):
151
 
        """Test binary domination asserts coherent dominated status.
152
 
 
153
 
        Normally _dominateBinary only accepts domination candidates in
154
 
        PUBLISHED or PENDING status, a exception is opened for architecture
155
 
        independent binaries because during the iteration they might have
156
 
        been already SUPERSEDED with its first publication, when it happens
157
 
        the candidate is skipped, i.e. it's not dominated again.
158
 
 
159
 
        (remembering the architecture independent binaries get superseded
160
 
        atomically)
161
 
        """
162
 
        dominator = Dominator(self.logger, self.ubuntutest.main_archive)
163
 
 
164
 
        [dominant_source, dominant, dominated_source,
165
 
         dominated] = self.createSimpleDominationContext()
166
 
 
167
 
        # Let's modify the domination candidate, so it will look wrong to
168
 
        # _dominateBinary which will raise because it's a architecture
169
 
        # specific binary publication not in PENDING or PUBLISHED state.
170
 
        dominated.status = PackagePublishingStatus.SUPERSEDED
171
 
        manual_domination_date = datetime.datetime(
172
 
            2006, 12, 25, tzinfo=pytz.timezone("UTC"))
173
 
        dominated.datesuperseded = manual_domination_date
174
 
        flush_database_updates()
175
 
 
176
 
        # An error like that in production clearly indicates that something
177
 
        # is wrong in the Dominator look-up methods.
178
 
        self.assertRaises(
179
 
            AssertionError, dominator._dominateBinary, dominated, dominant)
180
 
 
181
 
        # The refused publishing record remains the same.
182
 
        dominated = self.checkBinaryPublication(
183
 
            dominated, PackagePublishingStatus.SUPERSEDED)
184
 
        self.assertEqual(dominated.datesuperseded, manual_domination_date)
185
 
 
186
 
        # Let's make it a architecture independent binary, so the domination
187
 
        # can be executed, but the record will be skipped.
188
 
        dominated.binarypackagerelease.architecturespecific = False
189
 
        flush_database_updates()
190
 
 
191
 
        dominator._dominateBinary(dominated, dominant)
192
 
        flush_database_updates()
193
 
        dominated = self.checkBinaryPublication(
194
 
            dominated, PackagePublishingStatus.SUPERSEDED)
195
 
        self.assertEqual(dominated.datesuperseded, manual_domination_date)
196
 
 
197
 
    def testOtherBinaryPublications(self):
198
 
        """Check the basis of architecture independent binary domination.
199
 
 
200
 
        We use _getOtherBinaryPublications to identify other publications of
201
 
        the same binarypackagerelease in other architectures (architecture
202
 
        independent binaries), they will be dominated during a single step.
203
 
 
204
 
        See overall details in `testDominationOfOldArchIndepBinaries`.
205
 
        """
206
 
        dominator = Dominator(self.logger, self.ubuntutest.main_archive)
207
 
 
208
 
        # Create architecture independent publications for foo-bin_1.0
209
 
        # in i386 & hppa.
210
 
        pub_source_archindep = self.getPubSource(
211
 
            version='1.0', status=PackagePublishingStatus.PUBLISHED,
212
 
            architecturehintlist='all')
213
 
        pub_binaries_archindep = self.getPubBinaries(
214
 
            pub_source=pub_source_archindep,
215
 
            status=PackagePublishingStatus.PUBLISHED)
216
 
        [hppa_pub, i386_pub] = pub_binaries_archindep
217
 
 
218
 
        # We will also copy the binary publications to a PPA archive
219
 
        # to check if the lookup is indeed restricted to the dominated
220
 
        # archive. See bug #237845 for further information.
221
 
        cprov = getUtility(IPersonSet).getByName('cprov')
222
 
        i386_pub.copyTo(
223
 
            self.breezy_autotest,
224
 
            PackagePublishingPocket.RELEASE,
225
 
            cprov.archive)
226
 
        cprov_foo_binaries = cprov.archive.getAllPublishedBinaries(name='foo')
227
 
        self.assertEqual(cprov_foo_binaries.count(), 2)
228
 
 
229
 
        # Manually supersede the hppa binary.
230
 
        hppa_pub.status = PackagePublishingStatus.SUPERSEDED
231
 
        flush_database_updates()
232
 
 
233
 
        # Check if we can reach the i386 publication using
234
 
        # _getOtherBinaryPublications over the hppa binary.
235
 
        [found] = list(dominator._getOtherBinaryPublications(hppa_pub))
236
 
        self.assertEqual(i386_pub, found)
237
 
 
238
 
        # Create architecture specific publications for foo-bin_1.1 in
239
 
        # i386 & hppa.
240
 
        pub_source_archdep = self.getPubSource(
241
 
            version='1.1', status=PackagePublishingStatus.PUBLISHED,
242
 
            architecturehintlist='any')
243
 
        pub_binaries_archdep = self.getPubBinaries(
244
 
            pub_source=pub_source_archdep)
245
 
        [hppa_pub, i386_pub] = pub_binaries_archdep
246
 
 
247
 
        # Manually supersede the hppa publication.
248
 
        hppa_pub.status = PackagePublishingStatus.SUPERSEDED
249
 
        flush_database_updates()
250
 
 
251
 
        # Check if there is no other publication of the hppa binary package
252
 
        # release.
253
 
        self.assertEqual(
254
 
            dominator._getOtherBinaryPublications(hppa_pub).count(),
255
 
            0)
256
 
 
257
 
    def testDominationOfOldArchIndepBinaries(self):
258
 
        """Check domination of architecture independent binaries.
259
 
 
260
 
        When a architecture independent binary is dominated it should also
261
 
        'carry' the same publications in other architectures independently
262
 
        of whether or not the new binary was successfully built to a specific
263
 
        architecture.
264
 
 
265
 
        See bug #48760 for further information about this aspect.
266
 
        """
267
 
        publisher = Publisher(
268
 
            self.logger, self.config, self.disk_pool,
269
 
            self.ubuntutest.main_archive)
270
 
 
271
 
        # Create published archindep context.
272
 
        pub_source_archindep = self.getPubSource(
273
 
            version='1.0', status=PackagePublishingStatus.PUBLISHED,
274
 
            architecturehintlist='all')
275
 
        pub_binaries_archindep = self.getPubBinaries(
276
 
            pub_source=pub_source_archindep,
277
 
            status=PackagePublishingStatus.PUBLISHED)
278
 
 
279
 
        # Emulated new publication of a archdep binary only on i386.
280
 
        pub_source_archdep = self.getPubSource(
281
 
            version='1.1', architecturehintlist='i386')
282
 
        pub_binaries_archdep = self.getPubBinaries(
283
 
            pub_source=pub_source_archdep)
284
 
 
285
 
        publisher.A_publish(False)
286
 
        publisher.B_dominate(False)
287
 
 
288
 
        # The latest architecture specific source and binary pair is
289
 
        # PUBLISHED.
 
69
        self.checkPublication(dominated, PackagePublishingStatus.SUPERSEDED)
 
70
        self.assertEqual(dominated.supersededby, supersededby)
 
71
        self.checkPastDate(dominated.datesuperseded)
 
72
 
 
73
    def testManualSourceDomination(self):
 
74
        """Test source domination procedure."""
 
75
        [dominant_source, dominant_binary, dominated_source,
 
76
         dominated_binary] = self.createSimpleDominationContext()
 
77
 
 
78
        self.dominateAndCheck(
 
79
            dominant_source, dominated_source,
 
80
            dominant_source.sourcepackagerelease)
 
81
 
 
82
    def testManualBinaryDomination(self):
 
83
        """Test binary domination procedure."""
 
84
        [dominant_source, dominant, dominated_source,
 
85
         dominated] = self.createSimpleDominationContext()
 
86
 
 
87
        self.dominateAndCheck(
 
88
            dominant, dominated, dominant.binarypackagerelease.build)
 
89
 
 
90
    def testJudgeAndDominate(self):
 
91
        """Verify that judgeAndDominate correctly dominates everything."""
 
92
        foo_10_source, foo_10_binaries = self.createSourceAndBinaries('1.0')
 
93
        foo_11_source, foo_11_binaries = self.createSourceAndBinaries('1.1')
 
94
        foo_12_source, foo_12_binaries = self.createSourceAndBinaries('1.2')
 
95
 
 
96
        dominator = Dominator(self.logger, foo_10_source.archive)
 
97
        dominator.judgeAndDominate(
 
98
            foo_10_source.distroseries, foo_10_source.pocket, self.config)
 
99
 
290
100
        self.checkPublications(
291
 
            pub_source_archdep, pub_binaries_archdep,
 
101
            [foo_12_source] + foo_12_binaries,
292
102
            PackagePublishingStatus.PUBLISHED)
293
 
 
294
 
        # The oldest architecture independent source & binaries should
295
 
        # be SUPERSEDED, i.e., the fact that new source version wasn't
296
 
        # built for hppa should not hold the condemned architecture
297
 
        # independent binary.
298
 
        self.checkPublications(
299
 
            pub_source_archindep, pub_binaries_archindep,
300
 
            PackagePublishingStatus.SUPERSEDED)
301
 
 
302
 
    def testDominationOnArchIndependentBinaryOverrides(self):
303
 
        """Check domination of architecture-independent overridden binaries.
304
 
 
305
 
        Due to the mechanism for performing atomic domination of arch-indep
306
 
        binaries (bug #48760) we were erroneously dominating binary override
307
 
        attempts (new pending publications of the same binary in different
308
 
        component/section). See bug #178102 for further information.
309
 
        """
310
 
        publisher = Publisher(
311
 
            self.logger, self.config, self.disk_pool,
312
 
            self.ubuntutest.main_archive)
313
 
 
314
 
        # Create published archindep context.
315
 
        pub_source = self.getPubSource(
316
 
            version='1.0', status=PackagePublishingStatus.PUBLISHED,
317
 
            architecturehintlist='all')
318
 
        overridden_binaries = self.getPubBinaries(
319
 
            pub_source=pub_source, status=PackagePublishingStatus.PUBLISHED)
320
 
 
321
 
        # Committing the transaction here is required to guarantee sane
322
 
        # order in publisher queries.
323
 
        self.layer.commit()
324
 
 
325
 
        # Perform the binary override.
326
 
        universe = getUtility(IComponentSet)['universe']
327
 
        pub_binaries = []
328
 
        for pub in overridden_binaries:
329
 
            pub_binaries.append(pub.changeOverride(new_component=universe))
330
 
 
331
 
        # Overrides are in DB.
332
 
        self.checkBinaryPublications(
333
 
            pub_binaries, PackagePublishingStatus.PENDING)
334
 
 
335
 
        # Publish and dominate them.
336
 
        publisher.A_publish(False)
337
 
        publisher.B_dominate(False)
338
 
 
339
 
        # The original binary publications are marked as SUPERSEDED and
340
 
        # the just-create overrides as preserved as PUBLISHED.
341
 
        self.checkBinaryPublications(
342
 
            overridden_binaries, PackagePublishingStatus.SUPERSEDED)
343
 
 
344
 
        self.checkBinaryPublications(
345
 
            pub_binaries, PackagePublishingStatus.PUBLISHED)
 
103
        self.checkPublications(
 
104
            [foo_11_source] + foo_11_binaries,
 
105
            PackagePublishingStatus.SUPERSEDED)
 
106
        self.checkPublications(
 
107
            [foo_10_source] + foo_10_binaries,
 
108
            PackagePublishingStatus.SUPERSEDED)
 
109
 
 
110
    def testEmptyDomination(self):
 
111
        """Domination asserts for not empty input list."""
 
112
        dominator = Dominator(self.logger, self.ubuntutest.main_archive)
 
113
        pubs = {'foo': []}
 
114
        # This isn't a really good exception. It should probably be
 
115
        # something more indicative of bad input.
 
116
        self.assertRaises(
 
117
            AssertionError, dominator._dominatePublications, pubs)
346
118
 
347
119
 
348
120
class TestDomination(TestNativePublishingBase):
379
151
        # DELETED and OBSOLETED publications are set to be deleted
380
152
        # immediately, whereas SUPERSEDED ones get a stay of execution
381
153
        # according to the configuration.
382
 
        deleted_source = self.checkSourcePublication(
 
154
        self.checkPublication(
383
155
            deleted_source, PackagePublishingStatus.DELETED)
384
156
        self.checkPastDate(deleted_source.scheduleddeletiondate)
385
157
 
386
 
        obsoleted_source = self.checkSourcePublication(
 
158
        self.checkPublication(
387
159
            obsoleted_source, PackagePublishingStatus.OBSOLETE)
388
160
        self.checkPastDate(deleted_source.scheduleddeletiondate)
389
161
 
390
 
        superseded_source = self.checkSourcePublication(
 
162
        self.checkPublication(
391
163
            superseded_source, PackagePublishingStatus.SUPERSEDED)
392
164
        self.checkPastDate(
393
165
            superseded_source.scheduleddeletiondate,