~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/bugs/mail/tests/test_handler.py

  • Committer: Launchpad Patch Queue Manager
  • Date: 2011-09-06 12:22:28 UTC
  • mfrom: (13788.1.16 private-bug-4)
  • Revision ID: launchpad@pqm.canonical.com-20110906122228-52suwkin6kvqw1gp
[r=henninge][bug=404010, 531954,
 385607] Use command groups in the bug mail process loop to control
 the order.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
    BugTaskCommandGroup,
36
36
    MaloneHandler,
37
37
    )
 
38
from lp.bugs.model.bugnotification import BugNotification
38
39
from lp.services.mail import stub
39
40
from lp.testing import (
40
41
    celebrity_logged_in,
204
205
            "There is no such bug in Launchpad: 1", message)
205
206
 
206
207
 
 
208
class MaloneHandlerProcessTestCase(TestCaseWithFactory):
 
209
    """Test the bug mail processing loop."""
 
210
    layer = LaunchpadFunctionalLayer
 
211
 
 
212
    @staticmethod
 
213
    def getLatestBugNotification():
 
214
        return BugNotification.selectFirst(orderBy='-id')
 
215
 
 
216
    def test_new_bug(self):
 
217
        project = self.factory.makeProduct(name='fnord')
 
218
        transaction.commit()
 
219
        handler = MaloneHandler()
 
220
        with person_logged_in(project.owner):
 
221
            msg = self.factory.makeSignedMessage(
 
222
                body='borked\n affects fnord',
 
223
                subject='subject borked',
 
224
                to_address='new@bugs.launchpad.dev')
 
225
            handler.process(msg, msg['To'])
 
226
        notification = self.getLatestBugNotification()
 
227
        bug = notification.bug
 
228
        self.assertEqual(
 
229
            [project.owner], list(bug.getDirectSubscribers()))
 
230
        self.assertEqual(project.owner, bug.owner)
 
231
        self.assertEqual('subject borked', bug.title)
 
232
        self.assertEqual(1, bug.messages.count())
 
233
        self.assertEqual('borked\n affects fnord', bug.description)
 
234
        self.assertEqual(1, len(bug.bugtasks))
 
235
        self.assertEqual(project, bug.bugtasks[0].target)
 
236
 
 
237
    def test_new_bug_with_one_misplaced_affects_line(self):
 
238
        # Affects commands in the wrong position are processed as the user
 
239
        # intended when the bug is new and there is only one affects.
 
240
        project = self.factory.makeProduct(name='fnord')
 
241
        assignee = self.factory.makePerson(name='pting')
 
242
        transaction.commit()
 
243
        handler = MaloneHandler()
 
244
        with person_logged_in(project.owner):
 
245
            msg = self.factory.makeSignedMessage(
 
246
                body='borked\n assignee pting\n affects fnord',
 
247
                subject='affects after assignee',
 
248
                to_address='new@bugs.launchpad.dev')
 
249
            handler.process(msg, msg['To'])
 
250
        notification = self.getLatestBugNotification()
 
251
        bug = notification.bug
 
252
        self.assertEqual('affects after assignee', bug.title)
 
253
        self.assertEqual(1, len(bug.bugtasks))
 
254
        self.assertEqual(project, bug.bugtasks[0].target)
 
255
        self.assertEqual(assignee, bug.bugtasks[0].assignee)
 
256
 
 
257
    def test_new_affect_command_interleaved_with_bug_commands(self):
 
258
        # The bug commands can appear before and after the affects command.
 
259
        project = self.factory.makeProduct(name='fnord')
 
260
        transaction.commit()
 
261
        handler = MaloneHandler()
 
262
        with person_logged_in(project.owner):
 
263
            msg = self.factory.makeSignedMessage(
 
264
                body='unsecure\n security yes\n affects fnord\n tag ajax',
 
265
                subject='unsecure code',
 
266
                to_address='new@bugs.launchpad.dev')
 
267
            handler.process(msg, msg['To'])
 
268
        notification = self.getLatestBugNotification()
 
269
        bug = notification.bug
 
270
        self.assertEqual('unsecure code', bug.title)
 
271
        self.assertEqual(True, bug.security_related)
 
272
        self.assertEqual(['ajax'], bug.tags)
 
273
        self.assertEqual(1, len(bug.bugtasks))
 
274
        self.assertEqual(project, bug.bugtasks[0].target)
 
275
 
 
276
    def test_new_security_bug(self):
 
277
        # Structural subscribers are not notified of security bugs.
 
278
        maintainer = self.factory.makePerson(name='maintainer')
 
279
        project = self.factory.makeProduct(name='fnord', owner=maintainer)
 
280
        subscriber = self.factory.makePerson(name='subscriber')
 
281
        with person_logged_in(subscriber):
 
282
            project.addBugSubscription(subscriber, subscriber)
 
283
        transaction.commit()
 
284
        handler = MaloneHandler()
 
285
        with person_logged_in(project.owner):
 
286
            msg = self.factory.makeSignedMessage(
 
287
                body='bad thing\n security yes\n affects fnord',
 
288
                subject='security issue',
 
289
                to_address='new@bugs.launchpad.dev')
 
290
            handler.process(msg, msg['To'])
 
291
        notification = self.getLatestBugNotification()
 
292
        bug = notification.bug
 
293
        self.assertEqual('security issue', bug.title)
 
294
        self.assertEqual(True, bug.security_related)
 
295
        self.assertEqual(1, len(bug.bugtasks))
 
296
        self.assertEqual(project, bug.bugtasks[0].target)
 
297
        recipients = set()
 
298
        for notification in BugNotification.select():
 
299
            for recipient in notification.recipients:
 
300
                recipients.add(recipient.person)
 
301
        self.assertContentEqual([maintainer], recipients)
 
302
 
 
303
 
207
304
class BugTaskCommandGroupTestCase(TestCase):
208
305
 
209
306
    def test_BugTaskCommandGroup_init_with_command(self):
309
406
        self.assertFalse(group._groups is group.groups)
310
407
        self.assertEqual([bugtask_group_1, bugtask_group_2], group.groups)
311
408
 
 
409
    def test_BugCommandGroup_groups_new_bug_with_fixable_affects(self):
 
410
        # A new bug that affects only one target does not require the
 
411
        # affects command to be first.
 
412
        group = BugCommandGroup(
 
413
            BugEmailCommands.get('bug', ['new']))
 
414
        status_command = BugEmailCommands.get('status', ['triaged'])
 
415
        bugtask_group_1 = BugTaskCommandGroup(status_command)
 
416
        group.add(bugtask_group_1)
 
417
        affects_command = BugEmailCommands.get('affects', ['fnord'])
 
418
        bugtask_group_2 = BugTaskCommandGroup(affects_command)
 
419
        group.add(bugtask_group_2)
 
420
        self.assertEqual(1, len(group.groups))
 
421
        self.assertIsNot(
 
422
            group._groups, group.groups,
 
423
            "List reference returned instead of copy.")
 
424
        self.assertEqual(
 
425
            [affects_command, status_command], group.groups[0].commands)
 
426
 
312
427
    def test_BugCommandGroup__nonzero__false(self):
313
428
        # A BugCommandGroup is zero is it has no commands or groups.
314
429
        group = BugCommandGroup()
480
595
        self.assertEqual(3, len(ordered_commands.groups))
481
596
        self.assertEqual(expected, str(ordered_commands))
482
597
 
 
598
    def test_BugCommandGroups__iter_(self):
 
599
        email_commands = [
 
600
            ('bug', '1234'),
 
601
            ('importance', 'high'),
 
602
            ('private', 'yes'),
 
603
            ('bug', 'new'),
 
604
            ('security', 'yes'),
 
605
            ('status', 'triaged'),
 
606
            ('affects', 'fnord'),
 
607
            ]
 
608
        commands = [
 
609
            BugEmailCommands.get(name=name, string_args=[args])
 
610
            for name, args in email_commands]
 
611
        ordered_commands = list(BugCommandGroups(commands))
 
612
        expected = [
 
613
            'bug 1234',
 
614
            'private yes',
 
615
            'importance high',
 
616
            'bug new',
 
617
            'security yes',
 
618
            'affects fnord',
 
619
            'status triaged',
 
620
            ]
 
621
        self.assertEqual(
 
622
            expected, [str(command) for command in ordered_commands])
 
623
 
483
624
 
484
625
class FakeSignature:
485
626