← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~gary/launchpad/bug548-db-2-tests into lp:launchpad/db-devel

 

Gary Poster has proposed merging lp:~gary/launchpad/bug548-db-2-tests into lp:launchpad/db-devel with lp:~gary/launchpad/bug548-db-2 as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~gary/launchpad/bug548-db-2-tests/+merge/48570

This branch fixes tests that failed on ~gary/launchpad/bug548-db-2

I added a test tool because I was doing the same thing over and over again, and other tests I was touch were too.

I'm not entirely satisfied with the test helper--tests for it would be nice, for instance, and I wonder if it should hang off the Layer, and so on--but this is an improvement at least.

I would love to get this landed before pqm early my tomorrow morning, and would be happy to promise to make a branch to fix review comments afterwards (that is, first thing tomorrow morning) if that is acceptable.

Thank you
-- 
https://code.launchpad.net/~gary/launchpad/bug548-db-2-tests/+merge/48570
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~gary/launchpad/bug548-db-2-tests into lp:launchpad/db-devel.
=== removed directory 'lib/canonical/widgets'
=== removed file 'lib/canonical/widgets/__init__.py'
--- lib/canonical/widgets/__init__.py	2011-02-02 21:39:04 +0000
+++ lib/canonical/widgets/__init__.py	1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-# This is a stub to keep canonical.shipit operational. this module
-# can delete when shipit is independent.
-
-from lp.app.widgets.itemswidgets import (
-    CheckBoxMatrixWidget,
-    LabeledMultiCheckBoxWidget,
-    )
-
-

=== modified file 'lib/lp/archivepublisher/tests/publishing-meta-data-files.txt'
--- lib/lp/archivepublisher/tests/publishing-meta-data-files.txt	2010-12-22 20:46:21 +0000
+++ lib/lp/archivepublisher/tests/publishing-meta-data-files.txt	2011-02-04 02:39:17 +0000
@@ -17,9 +17,11 @@
     >>> from lp.soyuz.enums import PackageUploadCustomFormat
     >>> from lp.soyuz.interfaces.publishing import PackagePublishingPocket
     >>> from lp.soyuz.model.queue import PackageUploadCustom
+    >>> from lp.testing.dbuser import lp_dbuser
 
     >>> bat = getUtility(IDistributionSet)['ubuntutest']['breezy-autotest']
-    >>> ppa = factory.makeArchive(distribution=bat.distribution)
+    >>> with lp_dbuser():
+    ...     ppa = factory.makeArchive(distribution=bat.distribution)
     >>> package_upload = bat.createQueueEntry(
     ...     pocket=PackagePublishingPocket.RELEASE, changesfilename="test",
     ...     changesfilecontent="test",

=== modified file 'lib/lp/archivepublisher/tests/test_dominator.py'
--- lib/lp/archivepublisher/tests/test_dominator.py	2010-10-17 13:35:20 +0000
+++ lib/lp/archivepublisher/tests/test_dominator.py	2011-02-04 02:39:17 +0000
@@ -13,6 +13,7 @@
 from lp.registry.interfaces.series import SeriesStatus
 from lp.soyuz.enums import PackagePublishingStatus
 from lp.soyuz.tests.test_publishing import TestNativePublishingBase
+from lp.testing.dbuser import lp_dbuser
 
 
 class TestDominator(TestNativePublishingBase):
@@ -116,7 +117,8 @@
         in an AssertionError), and shouldn't be directly considered for
         superseding either.
         """
-        ppa = self.factory.makeArchive()
+        with lp_dbuser():
+            ppa = self.factory.makeArchive()
         foo_10_source, foo_10_binaries = self.createSourceAndBinaries(
             '1.0', with_debug=True, archive=ppa)
         foo_11_source, foo_11_binaries = self.createSourceAndBinaries(

=== modified file 'lib/lp/archivepublisher/tests/test_publisher.py'
--- lib/lp/archivepublisher/tests/test_publisher.py	2010-12-19 22:47:25 +0000
+++ lib/lp/archivepublisher/tests/test_publisher.py	2011-02-04 02:39:17 +0000
@@ -50,6 +50,7 @@
     IArchiveSet,
     )
 from lp.soyuz.tests.test_publishing import TestNativePublishingBase
+from lp.testing.dbuser import lp_dbuser
 
 
 class TestPublisherBase(TestNativePublishingBase):
@@ -475,7 +476,8 @@
         # status of DELETING.
         ubuntu = getUtility(IDistributionSet)['ubuntu']
 
-        archive = self.factory.makeArchive()
+        with lp_dbuser():
+            archive = self.factory.makeArchive()
         old_num_pending_archives = ubuntu.getPendingPublicationPPAs().count()
         archive.status = ArchiveStatus.DELETING
         new_num_pending_archives = ubuntu.getPendingPublicationPPAs().count()
@@ -1039,9 +1041,10 @@
     def testHtaccessForPrivatePPA(self):
         # A htaccess file is created for new private PPA's.
 
-        ppa = self.factory.makeArchive(
-            distribution=self.ubuntutest, private=True)
-        ppa.buildd_secret = "geheim"
+        with lp_dbuser():
+            ppa = self.factory.makeArchive(
+                distribution=self.ubuntutest, private=True)
+            ppa.buildd_secret = "geheim"
 
         # Setup the publisher for it and publish its repository.
         archive_publisher = getPublisher(ppa, [], self.logger)

=== modified file 'lib/lp/bugs/doc/bugnotification-sending.txt'
--- lib/lp/bugs/doc/bugnotification-sending.txt	2011-02-04 02:39:16 +0000
+++ lib/lp/bugs/doc/bugnotification-sending.txt	2011-02-04 02:39:17 +0000
@@ -30,20 +30,9 @@
     ...     print email_notification.get_payload(decode=True)
     ...     print "-" * 70
 
-We'll also define some helper functions to help us with database users.
-
-    >>> from canonical.config import config
-    >>> from canonical.database.sqlbase import commit
-    >>> from canonical.testing.layers import LaunchpadZopelessLayer
-
-    >>> def switch_db_to_launchpad():
-    ...     commit()
-    ...     LaunchpadZopelessLayer.switchDbUser('launchpad')
-
-    >>> def switch_db_to_bugnotification():
-    ...     commit()
-    ...     LaunchpadZopelessLayer.switchDbUser(
-    ...         config.malone.bugnotification_dbuser)
+We'll also import a helper function to help us with database users.
+
+    >>> from lp.testing.dbuser import lp_dbuser
 
 You'll note that we are printing out an X-Launchpad-Message-Rationale
 header. This header is a simple string that allows people to filter
@@ -356,16 +345,13 @@
     ...     print member.preferredemail.email
     marilize@xxxxxxx
 
-    >>> switch_db_to_launchpad()
-    >>> bug_one.subscribe(shipit_admins, shipit_admins)
-    <...>
-
-    >>> comment = getUtility(IMessageSet).fromText(
-    ...     'subject', 'a comment.', sample_person,
-    ...     datecreated=ten_minutes_ago)
-    >>> bug_one.addCommentNotification(comment)
-
-    >>> switch_db_to_bugnotification()
+    >>> with lp_dbuser():
+    ...     ignored = bug_one.subscribe(shipit_admins, shipit_admins)
+    ...     comment = getUtility(IMessageSet).fromText(
+    ...         'subject', 'a comment.', sample_person,
+    ...         datecreated=ten_minutes_ago)
+    ...     bug_one.addCommentNotification(comment)
+
     >>> pending_notifications = getUtility(
     ...     IBugNotificationSet).getNotificationsToSend()
     >>> len(pending_notifications)
@@ -398,17 +384,15 @@
     >>> params = CreateBugParams(
     ...     msg=description, owner=sample_person, title='new bug')
 
-    >>> switch_db_to_launchpad()
-    >>> new_bug = ubuntu.createBug(params)
-    >>> switch_db_to_bugnotification()
-    >>> flush_notifications()
+    >>> with lp_dbuser():
+    ...     new_bug = ubuntu.createBug(params)
 
 If a bug is a duplicate of another bug, a marker gets inserted at the
 top of the email:
 
-    >>> switch_db_to_launchpad()
-    >>> new_bug.markAsDuplicate(bug_one)
-    >>> switch_db_to_bugnotification()
+    >>> flush_notifications()
+    >>> with lp_dbuser():
+    ...     new_bug.markAsDuplicate(bug_one)
     >>> comment = getUtility(IMessageSet).fromText(
     ...     'subject', 'a comment.', sample_person,
     ...     datecreated=ten_minutes_ago)
@@ -474,12 +458,11 @@
     ...     'Zero-day on Frobulator', 'Woah.', sample_person,
     ...     datecreated=ten_minutes_ago)
 
-    >>> switch_db_to_launchpad()
-    >>> sec_vuln_bug = ubuntu.createBug(CreateBugParams(
+    >>> with lp_dbuser():
+    ...     sec_vuln_bug = ubuntu.createBug(CreateBugParams(
     ...         msg=sec_vuln_description, owner=sample_person,
     ...         title='Zero-day on Frobulator',
     ...         security_related=True, private=True))
-    >>> switch_db_to_bugnotification()
 
     >>> sec_vuln_bug.security_related
     True
@@ -730,10 +713,8 @@
 The tags will be space-separated to allow the list to be wrapped if it
 gets over-long.
 
-    >>> switch_db_to_launchpad()
-    >>> bug_three.tags = [u'layout-test', u'another-tag', u'yet-another']
-
-    >>> switch_db_to_bugnotification()
+    >>> with lp_dbuser():
+    ...     bug_three.tags = [u'layout-test', u'another-tag', u'yet-another']
 
     >>> bug_three = getUtility(IBugSet).get(3)
     >>> for message in trigger_and_get_email_messages(bug_three):
@@ -743,15 +724,13 @@
 If we remove the tags from the bug, the X-Launchpad-Bug-Tags header
 won't be included.
 
-    >>> switch_db_to_launchpad()
-    >>> bug_three.tags = []
-    >>> switch_db_to_bugnotification()
+    >>> with lp_dbuser():
+    ...     bug_three.tags = []
 
     >>> bug_three = getUtility(IBugSet).get(3)
     >>> for message in trigger_and_get_email_messages(bug_three):
     ...     message.get_all('X-Launchpad-Bug-Tags')
 
-    >>> switch_db_to_launchpad()
     >>> #bug_three.unsubscribe(sample_person, sample_person)
 
 
@@ -771,7 +750,8 @@
 
 Predictably, private bugs are sent with a slightly different header:
 
-    >>> bug_three.setPrivate(True, sample_person)
+    >>> with lp_dbuser():
+    ...     bug_three.setPrivate(True, sample_person)
     True
     >>> bug_three.private
     True
@@ -799,7 +779,8 @@
 The presence of the security flag on a bug is, surprise, denoted by a
 simple "yes":
 
-    >>> bug_three.setSecurityRelated(True)
+    >>> with lp_dbuser():
+    ...     bug_three.setSecurityRelated(True)
     True
     >>> bug_three.security_related
     True
@@ -824,9 +805,9 @@
     >>> foo_bar = getUtility(IPersonSet).getByEmail('foo.bar@xxxxxxxxxxxxx')
 
     >>> from lp.bugs.interfaces.bugmessage import IBugMessageSet
-    >>> getUtility(IBugMessageSet).createMessage(
-    ...     'Hungry', bug_three, foo_bar, "Make me a sandwich.")
-    <BugMessage ...>
+    >>> with lp_dbuser():
+    ...     ignored = getUtility(IBugMessageSet).createMessage(
+    ...         'Hungry', bug_three, foo_bar, "Make me a sandwich.")
 
     >>> for message in trigger_and_get_email_messages(bug_three):
     ...     print message.get('X-Launchpad-Bug-Commenters')
@@ -835,9 +816,9 @@
 It only lists each user once, no matter how many comments they've
 made.
 
-    >>> getUtility(IBugMessageSet).createMessage(
-    ...     'Hungry', bug_three, foo_bar, "Make me a sandwich.")
-    <BugMessage ...>
+    >>> with lp_dbuser():
+    ...     ignored = getUtility(IBugMessageSet).createMessage(
+    ...         'Hungry', bug_three, foo_bar, "Make me a sandwich.")
 
     >>> for message in trigger_and_get_email_messages(bug_three):
     ...     print message.get('X-Launchpad-Bug-Commenters')
@@ -868,63 +849,58 @@
 Concise Person does not. We'll also create teams and give them members
 with different verbose_bugnotifications settings.
 
-    >>> switch_db_to_launchpad()
-    >>> bug = factory.makeBug(
-    ...     product=factory.makeProduct(title='Foo'),
-    ...     title='In the beginning, the universe was created. This '
-    ...         'has made a lot of people very angry and has been '
-    ...         'widely regarded as a bad move',
-    ...     description="This is a long description of the bug, which "
-    ...         "will be automatically wrapped by the BugNotification "
-    ...         "machinery. Ain't technology great?")
-
-    >>> verbose_person = factory.makePerson(
-    ...     displayname='Verbose Person', email='verbose@xxxxxxxxxxx')
-    >>> verbose_person.verbose_bugnotifications = True
-    >>> bug.subscribe(verbose_person, verbose_person)
-    <lp.bugs.model.bugsubscription.BugSubscription ...>
-
-    >>> concise_person = factory.makePerson(
-    ...     displayname='Concise Person', email='concise@xxxxxxxxxxx')
-    >>> concise_person.verbose_bugnotifications = False
-    >>> bug.subscribe(concise_person, concise_person)
-    <lp.bugs.model.bugsubscription.BugSubscription ...>
+    >>> with lp_dbuser():
+    ...     bug = factory.makeBug(
+    ...         product=factory.makeProduct(title='Foo'),
+    ...         title='In the beginning, the universe was created. This '
+    ...             'has made a lot of people very angry and has been '
+    ...             'widely regarded as a bad move',
+    ...         description="This is a long description of the bug, which "
+    ...             "will be automatically wrapped by the BugNotification "
+    ...             "machinery. Ain't technology great?")
+    ...     verbose_person = factory.makePerson(
+    ...         displayname='Verbose Person', email='verbose@xxxxxxxxxxx')
+    ...     verbose_person.verbose_bugnotifications = True
+    ...     ignored = bug.subscribe(verbose_person, verbose_person)
+    ...     concise_person = factory.makePerson(
+    ...         displayname='Concise Person', email='concise@xxxxxxxxxxx')
+    ...     concise_person.verbose_bugnotifications = False
+    ...     ignored = bug.subscribe(concise_person, concise_person)
 
 
 Concise Team doesn't want verbose notifications, while Concise Team
 Person, a member, does.
 
-    >>> concise_team = factory.makeTeam(
-    ...     name='conciseteam', displayname='Concise Team')
-    >>> concise_team.verbose_bugnotifications = False
-    >>> concise_team_person = factory.makePerson(
-    ...     displayname='Concise Team Person',
-    ...     email='conciseteam@xxxxxxxxxxx')
-    >>> concise_team_person.verbose_bugnotifications = True
-    >>> ignored = concise_team.addMember(
-    ...     concise_team_person, concise_team_person)
-    >>> bug.subscribe(concise_team, concise_team_person)
-    <lp.bugs.model.bugsubscription.BugSubscription ...>
+    >>> with lp_dbuser():
+    ...     concise_team = factory.makeTeam(
+    ...         name='conciseteam', displayname='Concise Team')
+    ...     concise_team.verbose_bugnotifications = False
+    ...     concise_team_person = factory.makePerson(
+    ...         displayname='Concise Team Person',
+    ...         email='conciseteam@xxxxxxxxxxx')
+    ...     concise_team_person.verbose_bugnotifications = True
+    ...     ignored = concise_team.addMember(
+    ...         concise_team_person, concise_team_person)
+    ...     ignored = bug.subscribe(concise_team, concise_team_person)
 
 Verbose Team wants verbose notifications, while Verbose Team Person, a
 member, does not.
 
-    >>> verbose_team = factory.makeTeam(
-    ...     name='verboseteam', displayname='Verbose Team')
-    >>> verbose_team.verbose_bugnotifications = True
-    >>> verbose_team_person = factory.makePerson(
-    ...     displayname='Verbose Team Person',
-    ...     email='verboseteam@xxxxxxxxxxx')
-    >>> verbose_team_person.verbose_bugnotifications = False
-    >>> ignored = verbose_team.addMember(
-    ...     verbose_team_person, verbose_team_person)
-    >>> bug.subscribe(verbose_team, verbose_team_person)
-    <lp.bugs.model.bugsubscription.BugSubscription ...>
+    >>> with lp_dbuser():
+    ...     verbose_team = factory.makeTeam(
+    ...         name='verboseteam', displayname='Verbose Team')
+    ...     verbose_team.verbose_bugnotifications = True
+    ...     verbose_team_person = factory.makePerson(
+    ...         displayname='Verbose Team Person',
+    ...         email='verboseteam@xxxxxxxxxxx')
+    ...     verbose_team_person.verbose_bugnotifications = False
+    ...     ignored = verbose_team.addMember(
+    ...         verbose_team_person, verbose_team_person)
+    ...     ignored = bug.subscribe(verbose_team, verbose_team_person)
 
 We'll expire all existing notifications since we're not interested in
 them:
 
-    >>> switch_db_to_bugnotification()
     >>> notifications = getUtility(
     ...     IBugNotificationSet).getNotificationsToSend()
     >>> len(notifications)
@@ -1105,8 +1081,6 @@
 they generated.  For now, everyone receives these notifications whether they
 want them or not.  However, we can show that the attribute exists for now.
 
-    >>> flush_notifications()
-    >>> switch_db_to_launchpad()
     >>> verbose_person.selfgenerated_bugnotifications
     True
 
@@ -1125,16 +1099,14 @@
 notification level of the subscription.
 
     >>> flush_notifications()
-    >>> switch_db_to_launchpad()
 
     >>> from lp.bugs.enum import BugNotificationLevel
     >>> from lp.registry.interfaces.product import IProductSet
     >>> firefox = getUtility(IProductSet).getByName('firefox')
     >>> mr_no_privs = getUtility(IPersonSet).getByName('no-priv')
-    >>> subscription_no_priv = firefox.addBugSubscription(
-    ...     mr_no_privs, mr_no_privs)
-
-    >>> switch_db_to_bugnotification()
+    >>> with lp_dbuser():
+    ...     subscription_no_priv = firefox.addBugSubscription(
+    ...         mr_no_privs, mr_no_privs)
 
 The notifications generated by addCommentNotification() are sent only to
 structural subscribers with no filters, or with the notification level
@@ -1200,10 +1172,9 @@
 
 
     >>> flush_notifications()
-    >>> switch_db_to_launchpad()
-    >>> filter = subscription_no_priv.newBugFilter()
-    >>> filter.bug_notification_level = BugNotificationLevel.COMMENTS
-    >>> switch_db_to_bugnotification()
+    >>> with lp_dbuser():
+    ...     filter = subscription_no_priv.newBugFilter()
+    ...     filter.bug_notification_level = BugNotificationLevel.COMMENTS
 
     >>> comment = getUtility(IMessageSet).fromText(
     ...     'subject', 'another comment.', sample_person,
@@ -1261,9 +1232,8 @@
 no comment notifications.
 
     >>> flush_notifications()
-    >>> switch_db_to_launchpad()
-    >>> filter.bug_notification_level = BugNotificationLevel.METADATA
-    >>> switch_db_to_bugnotification()
+    >>> with lp_dbuser():
+    ...     filter.bug_notification_level = BugNotificationLevel.METADATA
 
     >>> comment = getUtility(IMessageSet).fromText(
     ...     'subject', 'no comment for no-priv.', sample_person,
@@ -1373,9 +1343,8 @@
 no notifications created by addChangeNotification().
 
     >>> flush_notifications()
-    >>> switch_db_to_launchpad()
-    >>> filter.bug_notification_level = BugNotificationLevel.LIFECYCLE
-    >>> switch_db_to_bugnotification()
+    >>> with lp_dbuser():
+    ...     filter.bug_notification_level = BugNotificationLevel.LIFECYCLE
 
     >>> bug_one.addChangeNotification('** Summary changed to: something.',
     ...     sample_person, when=ten_minutes_ago)
@@ -1433,10 +1402,9 @@
 after all.
 
     >>> flush_notifications()
-    >>> switch_db_to_launchpad()
-    >>> filter2 = subscription_no_priv.newBugFilter()
-    >>> filter2.bug_notification_level = BugNotificationLevel.METADATA
-    >>> switch_db_to_bugnotification()
+    >>> with lp_dbuser():
+    ...     filter2 = subscription_no_priv.newBugFilter()
+    ...     filter2.bug_notification_level = BugNotificationLevel.METADATA
 
     >>> bug_one.addChangeNotification('** Summary changed to: whatever.',
     ...     sample_person, when=ten_minutes_ago)

=== added file 'lib/lp/testing/dbuser.py'
--- lib/lp/testing/dbuser.py	1970-01-01 00:00:00 +0000
+++ lib/lp/testing/dbuser.py	2011-02-04 02:39:17 +0000
@@ -0,0 +1,47 @@
+# Copyright 2011 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Provides a context manager to run parts of a test as a different dbuser."""
+
+__metaclass__ = type
+__all__ = [
+    'dbuser',
+    'lp_dbuser',
+    ]
+
+from contextlib import contextmanager
+
+from canonical.database.sqlbase import commit
+from canonical.testing.layers import LaunchpadZopelessLayer
+
+@contextmanager
+def dbuser(temporary_name, restore_name=None):
+    """A context manager that temporarily changes the dbuser.
+    
+    Use with the LaunchpadZopelessLayer layer and subclasses.
+    
+    temporary_name is the name of the dbuser that should be in place for the
+    code in the "with" block.  restore_name is the name of the dbuser that
+    should be restored after the with block.  If it is not supplied, the
+    dbuser currently set (as far as LaunchpadZopelessLayer knows) is used.
+    """
+    if restore_name is None:
+        restore_name = LaunchpadZopelessLayer.txn._dbuser
+    commit()
+    # Note that this will raise an assertion error if the
+    # LaunchpadZopelessLayer is not already set up.
+    LaunchpadZopelessLayer.switchDbUser(temporary_name)
+    yield
+    commit()
+    LaunchpadZopelessLayer.switchDbUser(restore_name)
+
+def lp_dbuser(restore_name=None):
+    """A context manager that temporarily changes to the launchpad dbuser.
+    
+    Use with the LaunchpadZopelessLayer layer and subclasses.
+    
+    restore_name is the name of the dbuser that should be restored after
+    the with block.  If it is not supplied, the dbuser currently set (as
+    far as LaunchpadZopelessLayer knows) is used.
+    """
+    return dbuser('launchpad', restore_name=restore_name)


Follow ups