summaryrefslogtreecommitdiff
path: root/src/mailman/runners/tests
diff options
context:
space:
mode:
authorBarry Warsaw2012-03-23 19:25:27 -0400
committerBarry Warsaw2012-03-23 19:25:27 -0400
commit25a392bf5c1a8d4d2bc63d51697350fc7dbd48bc (patch)
treef51fe7931545e23058cdb65595c7caed9b43bb0e /src/mailman/runners/tests
parentaa2d0ad067adfd2515ed3c256cd0bca296058479 (diff)
parente005e1b12fa0bd82d2e126df476b5505b440ce36 (diff)
downloadmailman-25a392bf5c1a8d4d2bc63d51697350fc7dbd48bc.tar.gz
mailman-25a392bf5c1a8d4d2bc63d51697350fc7dbd48bc.tar.zst
mailman-25a392bf5c1a8d4d2bc63d51697350fc7dbd48bc.zip
Merge the 'owners' branch. Posting to a list's -owner address now works as
expected.
Diffstat (limited to 'src/mailman/runners/tests')
-rw-r--r--src/mailman/runners/tests/test_incoming.py94
-rw-r--r--src/mailman/runners/tests/test_owner.py142
-rw-r--r--src/mailman/runners/tests/test_pipeline.py115
3 files changed, 351 insertions, 0 deletions
diff --git a/src/mailman/runners/tests/test_incoming.py b/src/mailman/runners/tests/test_incoming.py
new file mode 100644
index 000000000..5a0d82765
--- /dev/null
+++ b/src/mailman/runners/tests/test_incoming.py
@@ -0,0 +1,94 @@
+# Copyright (C) 2012 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Test the incoming queue runner."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestIncoming',
+ ]
+
+
+import unittest
+
+from mailman.app.lifecycle import create_list
+from mailman.chains.base import TerminalChainBase
+from mailman.config import config
+from mailman.runners.incoming import IncomingRunner
+from mailman.testing.helpers import (
+ get_queue_messages,
+ make_testable_runner,
+ specialized_message_from_string as mfs)
+from mailman.testing.layers import ConfigLayer
+
+
+
+class Chain(TerminalChainBase):
+ name = 'test'
+ description = 'a test chain'
+
+ def __init__(self, marker):
+ self._marker = marker
+
+ def _process(self, mlist, msg, msgdata):
+ msgdata['marker'] = self._marker
+ config.switchboards['out'].enqueue(msg, msgdata)
+
+
+
+class TestIncoming(unittest.TestCase):
+ """Test the incoming queue runner."""
+
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('test@example.com')
+ self._mlist.posting_chain = 'test posting'
+ self._mlist.owner_chain = 'test owner'
+ config.chains['test posting'] = Chain('posting')
+ config.chains['test owner'] = Chain('owner')
+ self._in = make_testable_runner(IncomingRunner, 'in')
+ self._msg = mfs("""\
+From: anne@example.com
+To: test@example.com
+
+""")
+
+ def tearDown(self):
+ del config.chains['test posting']
+ del config.chains['test owner']
+
+ def test_posting(self):
+ # A message posted to the list goes through the posting chain.
+ msgdata = dict(listname='test@example.com')
+ config.switchboards['in'].enqueue(self._msg, msgdata)
+ self._in.run()
+ messages = get_queue_messages('out')
+ self.assertEqual(len(messages), 1)
+ self.assertEqual(messages[0].msgdata.get('marker'), 'posting')
+
+ def test_owner(self):
+ # A message posted to the list goes through the posting chain.
+ msgdata = dict(listname='test@example.com',
+ to_owner=True)
+ config.switchboards['in'].enqueue(self._msg, msgdata)
+ self._in.run()
+ messages = get_queue_messages('out')
+ self.assertEqual(len(messages), 1)
+ self.assertEqual(messages[0].msgdata.get('marker'), 'owner')
diff --git a/src/mailman/runners/tests/test_owner.py b/src/mailman/runners/tests/test_owner.py
new file mode 100644
index 000000000..8264ef0d8
--- /dev/null
+++ b/src/mailman/runners/tests/test_owner.py
@@ -0,0 +1,142 @@
+# Copyright (C) 2012 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Test posting to a mailing list's -owner address."""
+
+# XXX 2012-03-23 BAW: This is not necessarily the best place for this test.
+# We really need a better place to collect these sort of end-to-end posting
+# tests. They're not exactly integration tests, but they do touch lots of
+# parts of the system.
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestEmailToOwner',
+ ]
+
+
+import unittest
+
+from operator import itemgetter
+from zope.component import getUtility
+
+from mailman.app.lifecycle import create_list
+from mailman.config import config
+from mailman.interfaces.member import MemberRole
+from mailman.interfaces.usermanager import IUserManager
+from mailman.testing.helpers import (
+ TestableMaster,
+ get_lmtp_client,
+ make_testable_runner)
+from mailman.runners.incoming import IncomingRunner
+from mailman.runners.outgoing import OutgoingRunner
+from mailman.runners.pipeline import PipelineRunner
+from mailman.testing.layers import SMTPLayer
+
+
+
+class TestEmailToOwner(unittest.TestCase):
+ """Test emailing a mailing list's -owner address."""
+
+ layer = SMTPLayer
+
+ def setUp(self):
+ self._mlist = create_list('test@example.com')
+ # Add some owners, moderators, and members
+ manager = getUtility(IUserManager)
+ anne = manager.create_address('anne@example.com')
+ bart = manager.create_address('bart@example.com')
+ cris = manager.create_address('cris@example.com')
+ dave = manager.create_address('dave@example.com')
+ self._mlist.subscribe(anne, MemberRole.member)
+ self._mlist.subscribe(anne, MemberRole.owner)
+ self._mlist.subscribe(bart, MemberRole.moderator)
+ self._mlist.subscribe(bart, MemberRole.owner)
+ self._mlist.subscribe(cris, MemberRole.moderator)
+ self._mlist.subscribe(dave, MemberRole.member)
+ config.db.commit()
+ self._inq = make_testable_runner(IncomingRunner, 'in')
+ self._pipelineq = make_testable_runner(PipelineRunner, 'pipeline')
+ self._outq = make_testable_runner(OutgoingRunner, 'out')
+ # Python 2.7 has assertMultiLineEqual. Let this work without bounds.
+ self.maxDiff = None
+ self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual)
+
+ def test_owners_get_email(self):
+ # XXX 2012-03-23 BAW: We can't use a layer here because we need both
+ # the SMTPLayer and LMTPLayer and these are incompatible. There's no
+ # way to make zope.test* happy without causing errors or worse. Live
+ # with this hack until we can rip all that layer crap out and use
+ # something like testresources.
+ def wait():
+ get_lmtp_client(quiet=True)
+ lmtpd = TestableMaster(wait)
+ lmtpd.start()
+ # Post a message to the list's -owner address, and all the owners will
+ # get a copy of the message.
+ lmtp = get_lmtp_client(quiet=True)
+ lmtp.lhlo('remote.example.org')
+ lmtp.sendmail('zuzu@example.org', ['test-owner@example.com'], """\
+From: Zuzu Person <zuzu@example.org>
+To: test-owner@example.com
+Message-ID: <ant>
+
+Can you help me?
+""")
+ lmtpd.stop()
+ # There should now be one message sitting in the incoming queue.
+ # Check that, then process it. Don't use get_queue_messages() since
+ # that will empty the queue.
+ self.assertEqual(len(config.switchboards['in'].files), 1)
+ self._inq.run()
+ # There should now be one message sitting in the pipeline queue.
+ # Process that one too.
+ self.assertEqual(len(config.switchboards['pipeline'].files), 1)
+ self._pipelineq.run()
+ # The message has made its way to the outgoing queue. Again, check
+ # and process that one.
+ self.assertEqual(len(config.switchboards['out'].files), 1)
+ self._outq.run()
+ # The SMTP server has now received three messages, one for each of the
+ # owners and moderators. Of course, Bart is both an owner and a
+ # moderator, so he'll get only one copy of the message. Dave does not
+ # get a copy of the message.
+ messages = sorted(SMTPLayer.smtpd.messages, key=itemgetter('x-rcptto'))
+ self.assertEqual(len(messages), 3)
+ self.assertEqual(messages[0]['x-rcptto'], 'anne@example.com')
+ self.assertEqual(messages[1]['x-rcptto'], 'bart@example.com')
+ self.assertEqual(messages[2]['x-rcptto'], 'cris@example.com')
+ # And yet, all three messages are addressed to the -owner address.
+ for message in messages:
+ self.assertEqual(message['to'], 'test-owner@example.com')
+ # All three messages will have two X-MailFrom headers. One is added
+ # by the LMTP server accepting Zuzu's original message, and will
+ # contain her posting address, i.e. zuzu@example.com. The second one
+ # is added by the lazr.smtptest server that accepts Mailman's VERP'd
+ # message to the individual recipient. By verifying both, we prove
+ # that Zuzu sent the original message, and that Mailman is VERP'ing
+ # the copy to all the owners.
+ self.assertEqual(
+ messages[0].get_all('x-mailfrom'),
+ ['zuzu@example.org', 'test-bounces+anne=example.com@example.com'])
+ self.assertEqual(
+ messages[1].get_all('x-mailfrom'),
+ ['zuzu@example.org', 'test-bounces+bart=example.com@example.com'])
+ self.assertEqual(
+ messages[2].get_all('x-mailfrom'),
+ ['zuzu@example.org', 'test-bounces+cris=example.com@example.com'])
diff --git a/src/mailman/runners/tests/test_pipeline.py b/src/mailman/runners/tests/test_pipeline.py
new file mode 100644
index 000000000..8776bf844
--- /dev/null
+++ b/src/mailman/runners/tests/test_pipeline.py
@@ -0,0 +1,115 @@
+# Copyright (C) 2012 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Test the pipeline runner."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestPipelineRunner',
+ ]
+
+
+import unittest
+
+from zope.interface import implements
+
+from mailman.app.lifecycle import create_list
+from mailman.config import config
+from mailman.interfaces.handler import IHandler
+from mailman.interfaces.pipeline import IPipeline
+from mailman.runners.pipeline import PipelineRunner
+from mailman.testing.helpers import (
+ make_testable_runner,
+ specialized_message_from_string as mfs)
+from mailman.testing.layers import ConfigLayer
+
+
+
+class MyTestHandler:
+ implements(IHandler)
+ name = 'test handler'
+ description = 'A test handler'
+
+ def __init__(self, marker, test):
+ self._marker = marker
+ self._test = test
+
+ def process(self, mlist, msg, msgdata):
+ self._test.mark(self._marker)
+
+
+class MyTestPipeline:
+ implements(IPipeline)
+ name = 'test'
+ description = 'a test pipeline'
+
+ def __init__(self, marker, test):
+ self._marker = marker
+ self._test = test
+
+ def __iter__(self):
+ yield MyTestHandler(self._marker, self._test)
+
+
+
+class TestPipelineRunner(unittest.TestCase):
+ """Test the pipeline runner."""
+
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('test@example.com')
+ self._mlist.posting_pipeline = 'test posting'
+ self._mlist.owner_pipeline = 'test owner'
+ config.pipelines['test posting'] = MyTestPipeline('posting', self)
+ config.pipelines['test owner'] = MyTestPipeline('owner', self)
+ self._pipeline = make_testable_runner(PipelineRunner, 'pipeline')
+ self._markers = []
+ self._msg = mfs("""\
+From: anne@example.com
+To: test@example.com
+
+""")
+
+ def tearDown(self):
+ del config.pipelines['test posting']
+ del config.pipelines['test owner']
+
+ def mark(self, marker):
+ # Record a marker seen by a handler.
+ self._markers.append(marker)
+
+ def test_posting(self):
+ # A message accepted for posting gets processed through the posting
+ # pipeline.
+ msgdata = dict(listname='test@example.com')
+ config.switchboards['pipeline'].enqueue(self._msg, msgdata)
+ self._pipeline.run()
+ self.assertEqual(len(self._markers), 1)
+ self.assertEqual(self._markers[0], 'posting')
+
+ def test_owner(self):
+ # A message accepted for posting to a list's owners gets processed
+ # through the owner pipeline.
+ msgdata = dict(listname='test@example.com',
+ to_owner=True)
+ config.switchboards['pipeline'].enqueue(self._msg, msgdata)
+ self._pipeline.run()
+ self.assertEqual(len(self._markers), 1)
+ self.assertEqual(self._markers[0], 'owner')