Merge lp:~sinzui/launchpad/mlist-sync-0 into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Merged at revision: 11691
Proposed branch: lp:~sinzui/launchpad/mlist-sync-0
Merge into: lp:launchpad
Diff against target: 183 lines (+29/-108)
2 files modified
lib/lp/services/mailman/doc/staging.txt (+26/-105)
scripts/mlist-sync.py (+3/-3)
To merge this branch: bzr merge lp:~sinzui/launchpad/mlist-sync-0
Reviewer Review Type Date Requested Status
Edwin Grubbs (community) code Approve
Review via email: mp+37885@code.launchpad.net

Description of the change

This is my branch to switch mlist-sync to a LaunchpadScript.

    lp:~sinzui/launchpad/mlist-sync-0
    Diff size: 184
    Launchpad bug:
          https://bugs.launchpad.net/bugs/652007
    Test command: ./bin/test -vv --layer=Mailman -t staging
    Pre-implementation: no one
    Target release: 10.10

Switch mlist-sync to a LaunchpadScript
---------------------------------------

mlist-sync generated a oops, but it should not. scripts/mlist-sync.py gets
this behavior as it inherits from LaunchpadCronScript, despite being in the
scripts directory. This would be a bug - it should inherit from
LaunchpadScript.

Rules
-----

    * Change the script base to LaunchpadScript.
    * Update staging.txt to reliably run. It times out often because
      it indirectly setups of the test using integration tools. Directly
      create the objects under test.

QA
--

    * Verify mlist-sync does not appear in the oopses

Lint
----

Linting changed files:
  lib/lp/services/mailman/doc/staging.txt
  scripts/mlist-sync.py

Test
----

    * lib/lp/services/mailman/doc/staging.txt
      * We would not normally want to change this test because LaunchpadScript
        is interchangeable with LaunchpadCronScript in this case, but the
        test is very brittle. It often times out because it takes too long
        for messages to move through the smtp and xmlrpc servers.
      * I was able to replace the browser-based helpers with factory methods
        that make the objects under test. This made the test stable.
      * I could not discover a way to build the mboxes and archives, but I
        did discover they are not required for the test! I reported bug
        656417 because I think the rsync portion of the script should be
        tested.

Implementation
--------------

    * scripts/mlist-sync.py
      * Changed the base class.

To post a comment you must log in.
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

This looks good.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/services/mailman/doc/staging.txt'
2--- lib/lp/services/mailman/doc/staging.txt 2010-10-03 15:30:06 +0000
3+++ lib/lp/services/mailman/doc/staging.txt 2010-10-07 18:59:42 +0000
4@@ -19,122 +19,43 @@
5 informing them of their new list. We can ignore these.
6
7 >>> from canonical.launchpad.ftests import login, logout
8+ >>> from Mailman import MailList
9+
10+ >>> def makeMailmanList(lp_mailing_list):
11+ ... mlist = MailList.MailList()
12+ ... team = lp_mailing_list.team
13+ ... owner_email = team.teamowner.preferredemail.email
14+ ... mlist.Create(team.name, owner_email, 'password')
15+ ... mlist.host_name = 'lists.prod.launchpad.dev'
16+ ... mlist.web_page_url = 'http://lists.prod.launchpad.dev/mailman/'
17+ ... mlist.Save()
18+ ... mlist.addNewMember(owner_email)
19+ ... mlist.Unlock()
20+ ... return mlist
21
22 >>> login('admin@canonical.com')
23-
24- >>> from zope.security.proxy import removeSecurityProxy
25- >>> owner = removeSecurityProxy(factory.makePerson())
26- >>> team_one = factory.makeTeam(owner=owner, name='staging-one')
27- >>> team_two = factory.makeTeam(owner=owner, name='staging-two')
28- >>> transaction.commit()
29- >>> logout()
30-
31- >>> from canonical.launchpad.testing.pages import setupBrowser
32- >>> browser = setupBrowser('Basic %s:%s' %
33- ... (owner.preferredemail.email, owner._password_cleartext_cached))
34-
35- >>> from lp.services.mailman.testing import helpers
36- >>> helpers.apply_for_list(browser, 'staging-one')
37- >>> list_one = helpers.review_list('staging-one')
38-
39- >>> helpers.apply_for_list(browser, 'staging-two')
40- >>> list_two = helpers.review_list('staging-two')
41-
42-Anne subscribes to two mailing lists. Bart and Cris both subscribe to only
43-one of the mailing lists.
44-
45- >>> helpers.subscribe('Anne', 'staging-one')
46- >>> helpers.subscribe('Anne', 'staging-two')
47- >>> helpers.subscribe('Bart', 'staging-one')
48- >>> helpers.subscribe('Cris', 'staging-two')
49-
50-A bunch of messages are sent to the mailing lists.
51-
52- >>> smtpd.reset()
53- >>> from Mailman.Post import inject
54- >>> inject('staging-one', """\
55- ... From: anne.person@example.com
56- ... To: staging-one@lists.launchpad.dev
57- ... Subject: hello
58- ... Message-ID: <first-injection>
59- ...
60- ... Hello team!
61- ... """)
62-
63- # Wait for all recipients to receive the message.
64- >>> for index in range(3):
65- ... smtpd_watcher.wait_for_mbox_delivery('first-injection')
66-
67- >>> inject('staging-two', """\
68- ... From: anne.person@example.com
69- ... To: staging-two@lists.launchpad.dev
70- ... Subject: hello
71- ... Message-ID: <second-injection>
72- ...
73- ... Hello team!
74- ... """)
75-
76- # Wait for all recipients to receive the message.
77- >>> for index in range(3):
78- ... smtpd_watcher.wait_for_mbox_delivery('second-injection')
79-
80- >>> inject('staging-one', """\
81- ... From: bart.person@example.com
82- ... To: staging-one@lists.launchpad.dev
83- ... Subject: hello
84- ... Message-ID: <third-injection>
85- ...
86- ... Hello team!
87- ... """)
88-
89- # Wait for all recipients to receive the message.
90- >>> for index in range(3):
91- ... smtpd_watcher.wait_for_mbox_delivery('third-injection')
92-
93- >>> inject('staging-two', """\
94- ... From: cris.person@example.com
95- ... To: staging-two@lists.launchpad.dev
96- ... Subject: hello
97- ... Message-ID: <fourth-injection>
98- ...
99- ... Hello team!
100- ... """)
101-
102- # Wait for all recipients to receive the message.
103- >>> for index in range(3):
104- ... smtpd_watcher.wait_for_mbox_delivery('fourth-injection')
105-
106- >>> from operator import itemgetter
107- >>> for message in sorted(smtpd, key=itemgetter('sender')):
108- ... print message['sender']
109- staging-one-bounces+anne.person=example.com@lists.launchpad.dev
110- staging-one-bounces+anne.person=example.com@lists.launchpad.dev
111- staging-one-bounces+archive=mail-archive.dev@lists.launchpad.dev
112- staging-one-bounces+archive=mail-archive.dev@lists.launchpad.dev
113- staging-one-bounces+bart.person=example.com@lists.launchpad.dev
114- staging-one-bounces+bart.person=example.com@lists.launchpad.dev
115- staging-two-bounces+anne.person=example.com@lists.launchpad.dev
116- staging-two-bounces+anne.person=example.com@lists.launchpad.dev
117- staging-two-bounces+archive=mail-archive.dev@lists.launchpad.dev
118- staging-two-bounces+archive=mail-archive.dev@lists.launchpad.dev
119- staging-two-bounces+cris.person=example.com@lists.launchpad.dev
120- staging-two-bounces+cris.person=example.com@lists.launchpad.dev
121+ >>> team_one, list_one = factory.makeTeamAndMailingList(
122+ ... 'staging-one', 'owner-one')
123+ >>> team_two, list_two = factory.makeTeamAndMailingList(
124+ ... 'staging-two', 'owner-two')
125+ >>> mlist_one = makeMailmanList(list_one)
126+ >>> mlist_two = makeMailmanList(list_two)
127
128 Give one of the mailing lists a contact address, to further simulate what the
129 sync script has to deal with.
130
131- >>> from canonical.launchpad.ftests import login, logout
132- >>> from canonical.launchpad.interfaces import (
133- ... EmailAddressStatus, IEmailAddressSet, IPersonSet)
134+ >>> from canonical.launchpad.interfaces.emailaddress import (
135+ ... EmailAddressStatus, IEmailAddressSet)
136 >>> from zope.component import getUtility
137- >>> login('admin@canonical.com')
138- >>> team = getUtility(IPersonSet).getByName('staging-two')
139 >>> email = getUtility(IEmailAddressSet).new(
140- ... 'contact@example.com', team, EmailAddressStatus.VALIDATED)
141- >>> team.setContactAddress(email)
142+ ... 'contact@example.com', team_two, EmailAddressStatus.VALIDATED)
143+ >>> team_two.setContactAddress(email)
144 >>> logout()
145 >>> transaction.commit()
146
147+XXX sinzui 2010-10-07 bug=656417: The archive/mbox rsync rules are not tested
148+and we need a way to build test versions.
149+
150 Now we need to simulate the difference between the staging and production
151 databases. To do this, we'll use a helper, but first we need to stop Mailman.
152
153
154=== modified file 'scripts/mlist-sync.py'
155--- scripts/mlist-sync.py 2010-10-03 15:30:06 +0000
156+++ scripts/mlist-sync.py 2010-10-07 18:59:42 +0000
157@@ -40,7 +40,7 @@
158 from canonical.launchpad.interfaces import (
159 IEmailAddressSet, IMailingListSet, IPersonSet)
160 from lp.services.mailman.config import configure_prefix
161-from lp.services.scripts.base import LaunchpadCronScript
162+from lp.services.scripts.base import LaunchpadScript
163
164
165 RSYNC_OPTIONS = ('-avz', '--delete')
166@@ -49,7 +49,7 @@
167 SPACE = ' '
168
169
170-class MailingListSyncScript(LaunchpadCronScript):
171+class MailingListSyncScript(LaunchpadScript):
172 """
173 %prog [options] source_url
174
175@@ -205,7 +205,7 @@
176 # Keep going.
177
178 def main(self):
179- """See `LaunchpadCronScript`."""
180+ """See `LaunchpadScript`."""
181 source_url = None
182 if len(self.args) == 0:
183 self.parser.error('Missing source_url')