~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/registry/tests/test_distributionsourcepackage.py

Merged replication into pending-db-changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 
6
6
__metaclass__ = type
7
7
 
 
8
from storm.store import Store
 
9
from testtools.matchers import Equals
8
10
import transaction
9
11
from zope.component import getUtility
10
12
from zope.security.proxy import removeSecurityProxy
11
13
 
 
14
from canonical.database.sqlbase import flush_database_updates
12
15
from canonical.launchpad.interfaces.lpstorm import IStore
13
16
from canonical.testing.layers import (
14
17
    DatabaseFunctionalLayer,
22
25
from lp.registry.model.karma import KarmaTotalCache
23
26
from lp.soyuz.enums import PackagePublishingStatus
24
27
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
25
 
from lp.testing import TestCaseWithFactory
 
28
from lp.testing import (
 
29
    StormStatementRecorder,
 
30
    TestCaseWithFactory,
 
31
    )
 
32
from lp.testing.matchers import HasQueryCount
26
33
 
27
34
 
28
35
class TestDistributionSourcePackage(TestCaseWithFactory):
262
269
            archive.name for archive in related_archives]
263
270
 
264
271
        self.assertEqual(related_archive_names, ['gedit-beta'])
 
272
 
 
273
 
 
274
class TestDistributionSourcePackageInDatabase(TestCaseWithFactory):
 
275
 
 
276
    layer = DatabaseFunctionalLayer
 
277
 
 
278
    def test_mapping_cache_cleared_on_abort(self):
 
279
        # DistributionSourcePackageInDatabase._cache is cleared when a
 
280
        # transaction is aborted.
 
281
        DistributionSourcePackageInDatabase._cache["Frank"] = "Sinatra"
 
282
        transaction.abort()
 
283
        self.assertEqual(
 
284
            {}, DistributionSourcePackageInDatabase._cache.items())
 
285
 
 
286
    def test_mapping_cache_cleared_on_commit(self):
 
287
        # DistributionSourcePackageInDatabase._cache is cleared when a
 
288
        # transaction is committed.
 
289
        DistributionSourcePackageInDatabase._cache["Frank"] = "Sinatra"
 
290
        transaction.commit()
 
291
        self.assertEqual(
 
292
            {}, DistributionSourcePackageInDatabase._cache.items())
 
293
 
 
294
    def test_new(self):
 
295
        # DistributionSourcePackageInDatabase.new() creates a new DSP, adds it
 
296
        # to the store, and updates the mapping cache.
 
297
        distribution = self.factory.makeDistribution()
 
298
        sourcepackagename = self.factory.makeSourcePackageName()
 
299
        dsp = DistributionSourcePackageInDatabase.new(
 
300
            distribution, sourcepackagename)
 
301
        self.assertIs(Store.of(distribution), Store.of(dsp))
 
302
        self.assertEqual(
 
303
            {(distribution.id, sourcepackagename.id): dsp.id},
 
304
            DistributionSourcePackageInDatabase._cache.items())
 
305
 
 
306
    def test_getDirect_not_found(self):
 
307
        # DistributionSourcePackageInDatabase.getDirect() returns None if a
 
308
        # DSP does not exist in the database. It does not modify the mapping
 
309
        # cache.
 
310
        distribution = self.factory.makeDistribution()
 
311
        sourcepackagename = self.factory.makeSourcePackageName()
 
312
        flush_database_updates()
 
313
        with StormStatementRecorder() as recorder:
 
314
            dsp = DistributionSourcePackageInDatabase.getDirect(
 
315
                distribution, sourcepackagename)
 
316
            self.assertIs(None, dsp)
 
317
        self.assertThat(recorder, HasQueryCount(Equals(1)))
 
318
        self.assertEqual(
 
319
            {}, DistributionSourcePackageInDatabase._cache.items())
 
320
 
 
321
    def test_getDirect_found(self):
 
322
        # DistributionSourcePackageInDatabase.getDirect() returns the
 
323
        # DSPInDatabase if one already exists in the database. It also adds
 
324
        # the new mapping to the mapping cache.
 
325
        distribution = self.factory.makeDistribution()
 
326
        sourcepackagename = self.factory.makeSourcePackageName()
 
327
        dsp = DistributionSourcePackageInDatabase.new(
 
328
            distribution, sourcepackagename)
 
329
        flush_database_updates()
 
330
        with StormStatementRecorder() as recorder:
 
331
            dsp_found = DistributionSourcePackageInDatabase.getDirect(
 
332
                dsp.distribution, dsp.sourcepackagename)
 
333
            self.assertIs(dsp, dsp_found)
 
334
        self.assertThat(recorder, HasQueryCount(Equals(1)))
 
335
        self.assertEqual(
 
336
            {(distribution.id, sourcepackagename.id): dsp.id},
 
337
            DistributionSourcePackageInDatabase._cache.items())
 
338
 
 
339
    def test_get_not_cached_and_not_found(self):
 
340
        # DistributionSourcePackageInDatabase.get() returns None if a DSP does
 
341
        # not exist in the database and no mapping cache entry exists for
 
342
        # it. It does not modify the mapping cache.
 
343
        distribution = self.factory.makeDistribution()
 
344
        sourcepackagename = self.factory.makeSourcePackageName()
 
345
        flush_database_updates()
 
346
        with StormStatementRecorder() as recorder:
 
347
            dsp = DistributionSourcePackageInDatabase.get(
 
348
                distribution, sourcepackagename)
 
349
            self.assertIs(None, dsp)
 
350
        self.assertThat(recorder, HasQueryCount(Equals(1)))
 
351
        self.assertEqual(
 
352
            {}, DistributionSourcePackageInDatabase._cache.items())
 
353
 
 
354
    def test_get_cached_and_not_found(self):
 
355
        # DistributionSourcePackageInDatabase.get() returns None if a DSP does
 
356
        # not exist in the database for a stale mapping cache entry.
 
357
        distribution = self.factory.makeDistribution()
 
358
        sourcepackagename = self.factory.makeSourcePackageName()
 
359
        # Enter a stale entry in the mapping cache.
 
360
        stale_dsp_cache_key = distribution.id, sourcepackagename.id
 
361
        DistributionSourcePackageInDatabase._cache[stale_dsp_cache_key] = -123
 
362
        flush_database_updates()
 
363
        with StormStatementRecorder() as recorder:
 
364
            dsp = DistributionSourcePackageInDatabase.get(
 
365
                distribution, sourcepackagename)
 
366
            self.assertIs(None, dsp)
 
367
        # A stale mapping means that we have to issue two queries: the first
 
368
        # queries for the stale DSP from the database, the second gets the
 
369
        # correct DSP (or None).
 
370
        self.assertThat(recorder, HasQueryCount(Equals(2)))
 
371
 
 
372
    def test_get_cached_and_not_found_with_bogus_dsp(self):
 
373
        # DistributionSourcePackageInDatabase.get() returns None if a DSP does
 
374
        # exist in the database for a mapping cache entry, but the DSP
 
375
        # discovered does not match the mapping cache key.
 
376
        distribution = self.factory.makeDistribution()
 
377
        sourcepackagename = self.factory.makeSourcePackageName()
 
378
        # Put a bogus entry into the mapping cache.
 
379
        bogus_dsp = DistributionSourcePackageInDatabase.new(
 
380
            distribution, self.factory.makeSourcePackageName())
 
381
        bogus_dsp_cache_key = distribution.id, sourcepackagename.id
 
382
        DistributionSourcePackageInDatabase._cache[
 
383
            bogus_dsp_cache_key] = bogus_dsp.id
 
384
        # Invalidate the bogus DSP from Storm's cache.
 
385
        Store.of(bogus_dsp).invalidate(bogus_dsp)
 
386
        flush_database_updates()
 
387
        with StormStatementRecorder() as recorder:
 
388
            dsp = DistributionSourcePackageInDatabase.get(
 
389
                distribution, sourcepackagename)
 
390
            self.assertIs(None, dsp)
 
391
        # A stale mapping means that we have to issue two queries: the first
 
392
        # gets the bogus DSP from the database, the second gets the correct
 
393
        # DSP (or None).
 
394
        self.assertThat(recorder, HasQueryCount(Equals(2)))
 
395
 
 
396
    def test_get_cached_and_not_found_with_bogus_dsp_in_storm_cache(self):
 
397
        # DistributionSourcePackageInDatabase.get() returns None if a DSP does
 
398
        # exist in the database for a mapping cache entry, but the DSP
 
399
        # discovered does not match the mapping cache key.
 
400
        distribution = self.factory.makeDistribution()
 
401
        sourcepackagename = self.factory.makeSourcePackageName()
 
402
        # Put a bogus entry into the mapping cache.
 
403
        bogus_dsp = DistributionSourcePackageInDatabase.new(
 
404
            distribution, self.factory.makeSourcePackageName())
 
405
        bogus_dsp_cache_key = distribution.id, sourcepackagename.id
 
406
        DistributionSourcePackageInDatabase._cache[
 
407
            bogus_dsp_cache_key] = bogus_dsp.id
 
408
        flush_database_updates()
 
409
        with StormStatementRecorder() as recorder:
 
410
            dsp = DistributionSourcePackageInDatabase.get(
 
411
                distribution, sourcepackagename)
 
412
            self.assertIs(None, dsp)
 
413
        # A stale mapping means that we ordinarily have to issue two queries:
 
414
        # the first gets the bogus DSP from the database, the second gets the
 
415
        # correct DSP (or None). However, the bogus DSP is already in Storm's
 
416
        # cache, so we issue only one query.
 
417
        self.assertThat(recorder, HasQueryCount(Equals(1)))
 
418
 
 
419
    def test_get_not_cached_and_found(self):
 
420
        # DistributionSourcePackageInDatabase.get() returns the DSP if it's
 
421
        # found in the database even if no mapping cache entry exists for
 
422
        # it. It updates the mapping cache with this discovered information.
 
423
        distribution = self.factory.makeDistribution()
 
424
        sourcepackagename = self.factory.makeSourcePackageName()
 
425
        dsp = DistributionSourcePackageInDatabase.new(
 
426
            distribution, sourcepackagename)
 
427
        # new() updates the mapping cache so we must clear it.
 
428
        DistributionSourcePackageInDatabase._cache.clear()
 
429
        flush_database_updates()
 
430
        with StormStatementRecorder() as recorder:
 
431
            dsp_found = DistributionSourcePackageInDatabase.get(
 
432
                distribution, sourcepackagename)
 
433
            self.assertIs(dsp, dsp_found)
 
434
        self.assertThat(recorder, HasQueryCount(Equals(1)))
 
435
        self.assertEqual(
 
436
            {(distribution.id, sourcepackagename.id): dsp.id},
 
437
            DistributionSourcePackageInDatabase._cache.items())
 
438
 
 
439
    def test_get_cached_and_found(self):
 
440
        # DistributionSourcePackageInDatabase.get() returns the DSP if it's
 
441
        # found in the database from a good mapping cache entry.
 
442
        distribution = self.factory.makeDistribution()
 
443
        sourcepackagename = self.factory.makeSourcePackageName()
 
444
        dsp = DistributionSourcePackageInDatabase.new(
 
445
            distribution, sourcepackagename)
 
446
        flush_database_updates()
 
447
        with StormStatementRecorder() as recorder:
 
448
            dsp_found = DistributionSourcePackageInDatabase.get(
 
449
                distribution, sourcepackagename)
 
450
            self.assertIs(dsp, dsp_found)
 
451
        # Hurrah! This is what we're aiming for: a DSP that is in the mapping
 
452
        # cache *and* in Storm's cache.
 
453
        self.assertThat(recorder, HasQueryCount(Equals(0)))