From 235fe36118976009be293b58290fc411d141743d Mon Sep 17 00:00:00 2001 From: bwarsaw <> Date: Mon, 31 Mar 2003 22:06:51 +0000 Subject: Backporting from trunk --- tests/fblast.py | 2 +- tests/test_handlers.py | 108 ++++++++++++++------------------------------- tests/test_membership.py | 19 ++++---- tests/test_security_mgr.py | 30 +++++++++---- tests/test_smtp.py | 70 +++++++++++++++++++++++++++++ tests/testall.py | 10 ++--- 6 files changed, 140 insertions(+), 99 deletions(-) create mode 100644 tests/test_smtp.py diff --git a/tests/fblast.py b/tests/fblast.py index 2add9458..50368b3b 100644 --- a/tests/fblast.py +++ b/tests/fblast.py @@ -54,7 +54,7 @@ testing %(num)d """ % {'num' : i, 'FROMADDR': FROMADDR, 'LISTADDR': LISTADDR, - } + }) time.sleep(snooze) finally: conn.quit() diff --git a/tests/test_handlers.py b/tests/test_handlers.py index d169c51e..6c5b9a2e 100644 --- a/tests/test_handlers.py +++ b/tests/test_handlers.py @@ -1,31 +1,31 @@ -# Copyright (C) 2001,2002 by the Free Software Foundation, Inc. +# Copyright (C) 2001-2003 by the Free Software Foundation, Inc. # # This program 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 2 # of the License, or (at your option) any later version. -# +# # This program 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 this program; if not, write to the Free Software +# along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """Unit tests for the various Mailman/Handlers/*.py modules. """ import os -import time import sha -import unittest -import cPickle -import errno +import time import email -from email.Generator import Generator +import errno +import cPickle +import unittest from types import ListType +from email.Generator import Generator from Mailman import mm_cfg from Mailman.MailList import MailList @@ -45,10 +45,8 @@ from Mailman.Handlers import FileRecips from Mailman.Handlers import Hold from Mailman.Handlers import MimeDel from Mailman.Handlers import Moderate -from Mailman.Handlers import Personalize from Mailman.Handlers import Replybot -from Mailman.Handlers import SMTPDirect -from Mailman.Handlers import Sendmail +# Don't test handlers such as SMTPDirect and Sendmail here from Mailman.Handlers import SpamDetect from Mailman.Handlers import Tagger from Mailman.Handlers import ToArchive @@ -72,6 +70,7 @@ class TestAcknowledge(TestBase): self._sb = Switchboard(mm_cfg.VIRGINQUEUE_DIR) # Add a member self._mlist.addNewMember('aperson@dom.ain') + self._mlist.personalize = False def tearDown(self): for f in os.listdir(mm_cfg.VIRGINQUEUE_DIR): @@ -146,6 +145,7 @@ Your message entitled was successfully received by the _xtest mailing list. List info page: http://www.dom.ain/mailman/listinfo/_xtest +Your preferences: http://www.dom.ain/mailman/options/_xtest/aperson%40dom.ain """) # Make sure we dequeued the only message eq(len(self._sb.files()), 0) @@ -185,46 +185,7 @@ Your message entitled was successfully received by the _xtest mailing list. List info page: http://www.dom.ain/mailman/listinfo/_xtest -""") - # Make sure we dequeued the only message - eq(len(self._sb.files()), 0) - - def test_ack_with_prefixed_subject(self): - eq = self.assertEqual - self._mlist.subject_prefix = '[XTEST] ' - self._mlist.setMemberOption( - 'aperson@dom.ain', mm_cfg.AcknowledgePosts, 1) - eq(len(self._sb.files()), 0) - msg = email.message_from_string("""\ -From: aperson@dom.ain -Subject: [XTEST] Wish you were here - -""", Message.Message) - Acknowledge.process(self._mlist, msg, {}) - files = self._sb.files() - eq(len(files), 1) - qmsg, qdata = self._sb.dequeue(files[0]) - # Check the .db file - eq(qdata.get('listname'), '_xtest') - eq(qdata.get('recips'), ['aperson@dom.ain']) - eq(qdata.get('version'), 3) - # Check the .pck - eq(str(qmsg['subject']), '_xtest post acknowledgement') - eq(qmsg['to'], 'aperson@dom.ain') - eq(qmsg['from'], '_xtest-bounces@dom.ain') - eq(qmsg.get_type(), 'text/plain') - eq(qmsg.get_param('charset'), 'us-ascii') - msgid = qmsg['message-id'] - self.failUnless(msgid.startswith('')) - eq(qmsg.get_payload(), """\ -Your message entitled - - Wish you were here - -was successfully received by the _xtest mailing list. - -List info page: http://www.dom.ain/mailman/listinfo/_xtest +Your preferences: http://www.dom.ain/mailman/options/_xtest/aperson%40dom.ain """) # Make sure we dequeued the only message eq(len(self._sb.files()), 0) @@ -555,7 +516,7 @@ From: aperson@dom.ain """, Message.Message) CookHeaders.process(self._mlist, msg, {}) - eq(msg['precedence'], 'bulk') + eq(msg['precedence'], 'list') def test_existing_precedence(self): eq = self.assertEqual @@ -574,7 +535,9 @@ Precedence: junk From: aperson@dom.ain """, Message.Message) - CookHeaders.process(self._mlist, msg, {}) + msgdata = {} + CookHeaders.process(self._mlist, msg, msgdata) + self.assertEqual(msgdata.get('origsubj'), '') self.assertEqual(str(msg['subject']), '[XTEST] (no subject)') def test_subject_munging(self): @@ -794,7 +757,7 @@ Here is a message. XTest header Here is a message. XTest footer""") - + def test_no_multipart_type_error(self): mlist = self._mlist mlist.msg_header = '%(real_name) header\n' @@ -810,7 +773,7 @@ Here is a message. %(real_name) header Here is a message. %(real_name) footer""") - + def test_no_multipart_value_error(self): mlist = self._mlist # These will generate warnings in logs/error @@ -827,7 +790,7 @@ Here is a message. %(real_name)p header Here is a message. %(real_name)p footer""") - + def test_no_multipart_missing_key(self): mlist = self._mlist mlist.msg_header = '%(spooge)s header\n' @@ -842,7 +805,7 @@ Here is a message. %(spooge)s header Here is a message. %(spooge)s footer""") - + def test_multipart(self): mlist = self._mlist mlist.msg_header = 'header\n' @@ -871,6 +834,7 @@ Content-Type: multipart/mixed; boundary="BOUNDARY" Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit +Content-Disposition: inline header @@ -888,12 +852,14 @@ Here is the second message. Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit +Content-Disposition: inline footer --BOUNDARY--""") def test_image(self): + eq = self.assertEqual mlist = self._mlist mlist.msg_header = 'header\n' mlist.msg_footer = 'footer' @@ -904,7 +870,8 @@ Content-type: image/x-spooge IMAGEDATAIMAGEDATAIMAGEDATA """) Decorate.process(self._mlist, msg, {}) - self.assertEqual(msg.get_payload(), """\ + eq(len(msg.get_payload()), 3) + self.assertEqual(msg.get_payload(1).get_payload(), """\ IMAGEDATAIMAGEDATAIMAGEDATA """) @@ -1164,6 +1131,7 @@ class TestMimeDel(TestBase): TestBase.setUp(self) self._mlist.filter_content = 1 self._mlist.filter_mime_types = ['image/jpeg'] + self._mlist.pass_mime_types = [] self._mlist.convert_html_to_plaintext = 1 def test_outer_matches(self): @@ -1249,7 +1217,7 @@ MIME-Version: 1.0 """) MimeDel.process(self._mlist, msg, {}) eq(msg.get_type(), 'text/plain') - eq(msg.get_payload(), '\n \n\n') + eq(msg.get_payload(), '\n\n\n') def test_deep_structure(self): eq = self.assertEqual @@ -1338,16 +1306,6 @@ class TestReplybot(TestBase): pass - -class TestSMTPDirect(TestBase): - pass - - - -class TestSendmail(TestBase): - pass - - class TestSpamDetect(TestBase): def test_short_circuit(self): @@ -1565,7 +1523,7 @@ Here is message %(i)d fp = open(self._path, 'w') g = Generator(fp) for i in range(5): - g(self._makemsg(i), unixfrom=1) + g.flatten(self._makemsg(i), unixfrom=1) fp.close() self._sb = Switchboard(mm_cfg.VIRGINQUEUE_DIR) @@ -1609,13 +1567,14 @@ Here is message %(i)d # is the RFC 1153 digest. for filebase in files: qmsg, qdata = self._sb.dequeue(filebase) - if qmsg['mime-version']: + if qmsg.get_main_type() == 'multipart': mimemsg = qmsg mimedata = qdata else: rfc1153msg = qmsg rfc1153data = qdata - eq(mimemsg.get_type(), 'multipart/mixed') + eq(rfc1153msg.get_content_type(), 'text/plain') + eq(mimemsg.get_content_type(), 'multipart/mixed') eq(mimemsg['from'], mlist.GetRequestEmail()) eq(mimemsg['subject'], '%(realname)s Digest, Vol %(volume)d, Issue %(issue)d' % { @@ -1652,12 +1611,11 @@ It rocks! eq(len(files), 1) msg2, data = self._sb.dequeue(files[0]) eq(msg.as_string(unixfrom=0), msg2.as_string(unixfrom=0)) - eq(len(data), 6) + eq(len(data), 5) eq(data['foo'], 1) eq(data['bar'], 2) eq(data['version'], 3) eq(data['listname'], '_xtest') - eq(data['verp'], 0) # Clock skew makes this unreliable #self.failUnless(data['received_time'] <= time.time()) diff --git a/tests/test_membership.py b/tests/test_membership.py index c3850186..ae408fe3 100644 --- a/tests/test_membership.py +++ b/tests/test_membership.py @@ -1,17 +1,17 @@ -# Copyright (C) 2001,2002 by the Free Software Foundation, Inc. +# Copyright (C) 2001-2003 by the Free Software Foundation, Inc. # # This program 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 2 # of the License, or (at your option) any later version. -# +# # This program 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 this program; if not, write to the Free Software +# along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """Unit tests for OldStyleMemberships. @@ -84,7 +84,7 @@ class TestMembers(TestBase): password='xxXXxx', language='xx', realname='A. Nice Person') - + def test_add_member(self): eq = self.assertEqual mlist = self._mlist @@ -97,7 +97,7 @@ class TestMembers(TestBase): eq(mlist.getMemberCPAddresses(('person@dom.ain', 'noperson@dom.ain')), ['person@dom.ain', None]) eq(mlist.getMemberPassword('person@dom.ain'), 'xxXXxx') - eq(mlist.getMemberLanguage('person@dom.ain'), 'xx') + eq(mlist.getMemberLanguage('person@dom.ain'), 'en') eq(mlist.getMemberOption('person@dom.ain', mm_cfg.Digests), 0) eq(mlist.getMemberOption('person@dom.ain', mm_cfg.AcknowledgePosts), 0) eq(mlist.getMemberName('person@dom.ain'), 'A. Nice Person') @@ -163,7 +163,7 @@ class TestMembers(TestBase): eq(mlist.getMemberCPAddresses(('nice@dom.ain', 'nonice@dom.ain')), ['nice@dom.ain', None]) eq(mlist.getMemberPassword('nice@dom.ain'), 'xxXXxx') - eq(mlist.getMemberLanguage('nice@dom.ain'), 'xx') + eq(mlist.getMemberLanguage('nice@dom.ain'), 'en') eq(mlist.getMemberOption('nice@dom.ain', mm_cfg.Digests), 0) eq(mlist.getMemberOption('nice@dom.ain', mm_cfg.AcknowledgePosts), 0) eq(mlist.getMemberName('nice@dom.ain'), 'A. Nice Person') @@ -195,8 +195,9 @@ class TestMembers(TestBase): self.failIf(mlist.authenticateMember('person@dom.ain', 'xxXXxx')) def test_set_language(self): - self._mlist.setMemberLanguage('person@dom.ain', 'yy') - self.assertEqual(self._mlist.getMemberLanguage('person@dom.ain'), 'yy') + self._mlist.available_languages.append('xx') + self._mlist.setMemberLanguage('person@dom.ain', 'xx') + self.assertEqual(self._mlist.getMemberLanguage('person@dom.ain'), 'xx') def test_basic_option(self): eq = self.assertEqual diff --git a/tests/test_security_mgr.py b/tests/test_security_mgr.py index 451e6bbd..bfe902a1 100644 --- a/tests/test_security_mgr.py +++ b/tests/test_security_mgr.py @@ -1,17 +1,17 @@ -# Copyright (C) 2001 by the Free Software Foundation, Inc. +# Copyright (C) 2001-2003 by the Free Software Foundation, Inc. # # This program 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 2 # of the License, or (at your option) any later version. -# +# # This program 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 this program; if not, write to the Free Software +# along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """Unit tests for Mailman/SecurityManager.py @@ -27,7 +27,8 @@ try: import crypt except ImportError: crypt = None -from cStringIO import StringIO +# Don't use cStringIO because we're going to inherit +from StringIO import StringIO from Mailman import mm_cfg from Mailman import Utils @@ -101,7 +102,7 @@ class TestAuthenticate(TestBase): except OSError, e: if e.errno <> errno.ENOENT: raise TestBase.tearDown(self) - + def test_auth_creator(self): self.assertEqual(self._mlist.Authenticate( [mm_cfg.AuthCreator], 'ccCCcc'), mm_cfg.AuthCreator) @@ -176,7 +177,7 @@ class TestAuthenticate(TestBase): def test_no_user(self): mlist = self._mlist mlist.addNewMember('aperson@dom.ain', password='nosrepa') - self.assertRaises(TypeError, mlist.Authenticate, + self.assertRaises(AttributeError, mlist.Authenticate, [mm_cfg.AuthUser], 'nosrepa') def test_user_unauth(self): @@ -192,6 +193,14 @@ class TestAuthenticate(TestBase): +class StripperIO(StringIO): + HEAD = 'Set-Cookie: ' + def write(self, s): + if s.startswith(self.HEAD): + s = s[len(self.HEAD):] + StringIO.write(self, s) + + class TestWebAuthenticate(TestBase): def setUp(self): TestBase.setUp(self) @@ -201,13 +210,15 @@ class TestWebAuthenticate(TestBase): mlist.mod_password = password('abcdefg') mlist.addNewMember('aperson@dom.ain', password='qqQQqq') # Set up the cookie data - sfp = StringIO() + sfp = StripperIO() print >> sfp, mlist.MakeCookie(mm_cfg.AuthSiteAdmin) # AuthCreator isn't handled in AuthContextInfo() print >> sfp, mlist.MakeCookie(mm_cfg.AuthListAdmin) print >> sfp, mlist.MakeCookie(mm_cfg.AuthListModerator) print >> sfp, mlist.MakeCookie(mm_cfg.AuthUser, 'aperson@dom.ain') - os.environ['HTTP_COOKIE'] = sfp.getvalue() + # Strip off the "Set-Cookie: " prefix + cookie = sfp.getvalue() + os.environ['HTTP_COOKIE'] = cookie def tearDown(self): try: @@ -218,6 +229,7 @@ class TestWebAuthenticate(TestBase): os.unlink(mm_cfg.LISTCREATOR_PW_FILE) except OSError, e: if e.errno <> errno.ENOENT: raise + del os.environ['HTTP_COOKIE'] TestBase.tearDown(self) def test_auth_site_admin(self): diff --git a/tests/test_smtp.py b/tests/test_smtp.py new file mode 100644 index 00000000..71e9284a --- /dev/null +++ b/tests/test_smtp.py @@ -0,0 +1,70 @@ +# Copyright (C) 2003 by the Free Software Foundation, Inc. +# +# This program 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 2 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +"""Unit tests for SMTPDirect and (eventually perhaps) Sendmail. +""" + +import email +import unittest +import thread + +from Mailman import mm_cfg +from Mailman.Handlers import SMTPDirect + +from EmailBase import EmailBase + +TESTPORT = 3925 + + + +class TestSMTPDirect(EmailBase): + def setUp(self): + self._origport = mm_cfg.SMTPPORT + self._sessions = mm_cfg.SMTP_MAX_SESSIONS_PER_CONNECTION + mm_cfg.SMTPPORT = TESTPORT + mm_cfg.SMTP_MAX_SESSIONS_PER_CONNECTION = 1 + EmailBase.setUp(self) + + def tearDown(self): + mm_cfg.SMTPPORT = self._origport + mm_cfg.SMTP_MAX_SESSIONS_PER_CONNECTION = self._sessions + EmailBase.tearDown(self) + + def test_disconnect_midsession(self): + msgdata = {'recips': ['aperson@dom.ain', 'bperson@dom.ain'], + 'personalize': 1, + } + self._mlist.personalize = 1 + msg = email.message_from_string(""" +From: cperson@dom.ain +To: _xtest@dom.ain +Subject: testing + +testing +""") + id = thread.start_new_thread(self._readmsg, ()) + SMTPDirect.process(self._mlist, msg, msgdata) + + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestSMTPDirect)) + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') diff --git a/tests/testall.py b/tests/testall.py index 0f6a9be2..8630222d 100644 --- a/tests/testall.py +++ b/tests/testall.py @@ -1,17 +1,17 @@ -# Copyright (C) 2001,2002 by the Free Software Foundation, Inc. +# Copyright (C) 2001-2003 by the Free Software Foundation, Inc. # # This program 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 2 # of the License, or (at your option) any later version. -# +# # This program 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 this program; if not, write to the Free Software +# along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """PyUnit-based test harness for Mailman.""" @@ -19,7 +19,7 @@ import unittest MODULES = ('bounces', 'handlers', 'membership', 'safedict', - 'security_mgr', 'runners', 'lockfile', + 'security_mgr', 'runners', 'lockfile', 'smtp', ) # test_message.py can only be run when mailmanctl is running, but mailmanctl -- cgit v1.2.3