#!/usr/bin/python ### ### Copyright (C) 1998-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA ### 02110-1301, USA. http://www.fsf.org/licensing/licenses/gpl.html ### ### --------------------------- ### ### Test cases for the mailman_admin_cmd_handler script ### ### Author: Anthony R. Thompson ### Contact: put @ between art and sigilservices.com ### Created: Dec 2009 ### import sys, re, random, unittest, socket import mailman_admin_cmd_handler import ListStream MM_ROOT = '/usr/lib/mailman/' # INSTALL sys.path.append(MM_ROOT) from Mailman import mm_cfg class MMCHTests(unittest.TestCase): __argv__ = sys.argv[:] def save_output(self): self.output = ListStream.ListStream() sys.stdout = self.output def clear_output(self): self.output.clear() def get_output(self): return self.output.contents() def restore_output(self): sys.stdout = sys.__stdout__ def set_input(self, inlist): self.input = ListStream.ListStream() for line in inlist: self.input.write(line) sys.stdin = self.input def restore_input(self): sys.stdin = sys.__stdin__ # INSTALL (put subject line password, if using one) def set_input_msg(self, msgbody, subj=''): if (subj == ''): subj = 'test ' + self.subjlinepw msg = ["From: %s\n" % (self.testadmin)] msg.append("To: mailman-admin-cmd@%s\n" % (self.thishost)) msg.append("Subject: " + subj + "\n") msg.append("Date: Sun, 20 Dec 2009 06:07:02 +0000\n") msg.append("\n") if (type(msgbody) is list): for line in msgbody: if (re.search('\n$', line)): msg.append(line) else: msg.append(line + "\n") else: msg.append(str(msgbody)) self.set_input(msg) def text_in_list(self, find_text, search_list): found = False for line in search_list: if (re.search(find_text, line)): found = True break return found def random_string(self, length): random.seed() randstr = '' for posn in range (0, length): randstr += chr(random.randint(33,126)) return randstr def setUp(self): # Make believe that it was called from the command line sys.argv = ['mailman_admin_cmd_handler.py'] self.thishost = socket.gethostname() self.testfrom = 'mailman-admin-cmd@' + self.thishost self.subjlinepw = 'SUBJECTPASSWORD' # INSTALL (if using one) self.testadmin = 'admin@place.org' # INSTALL self.testlist = 'testlistname' # INSTALL self.testlistpass = 'testlistpass' # INSTALL self.testsub = 'test@someplace.org' # INSTALL, must be on list alre self.testsubname = 'Subscriber Name' # INSTALL self.testsubpass = 'subscriberpasswd' # INSTALL self.siteadminpass = 'siteadminpass' # INSTALL self.testlistowner = 'owner@foo.org' # INSTALL self.testrecip = self.testadmin def testCmdUsage(self): self.assertEquals(mailman_admin_cmd_handler.cmd_usage('who'), 'who listname passwd') def testIsList(self): self.assertTrue(mailman_admin_cmd_handler.is_list(self.testlist)) self.assertFalse(mailman_admin_cmd_handler.is_list('badlistname')) def testIsListOwner(self): mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) self.assertTrue(mailman_admin_cmd_handler.is_list_owner(mlist, self.testlistowner)) def testValidListPass(self): mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) self.assertTrue(mailman_admin_cmd_handler.valid_list_pass( mlist, self.testlistpass)) # Note: This test will FAIL if we move to a shared hosting environment # because our hosting provider might not share this password with us. def testValidSiteAdminPass(self): self.assertTrue(mailman_admin_cmd_handler.valid_site_admin_pass( self.siteadminpass)) self.assertFalse(mailman_admin_cmd_handler.valid_site_admin_pass( 'bad-site-admin-password-xyzzy')) def testValidUserPass(self): mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) self.assertTrue(mailman_admin_cmd_handler.valid_user_pass( mlist, self.testsub, self.testsubpass)) self.assertFalse(mailman_admin_cmd_handler.valid_user_pass( mlist, self.testsub, 'bad-user-password-xyzzy')) def testGetListUnlocked(self): mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) self.assertFalse(mlist.Locked()) def testListToString(self): testlist = ['a', "b\n", 'c'] self.assertEquals(mailman_admin_cmd_handler.list_to_string(testlist), "ab\nc") # Documentation for smtplib says that if sendmail doesn't raise any # exceptions, you can assume it sent the mail successfully, so we # basically just need to call the function and get no errors def testSendMail(self): mailman_admin_cmd_handler.send_mail('mailman_admin_cmd_handler test', 'Test message', self.testrecip, self.testfrom) def testHelp(self): self.assertTrue(re.search('^Valid commands', mailman_admin_cmd_handler.help())) def testWho(self): mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) args = ['who', self.testlist, self.testlistpass] output = mailman_admin_cmd_handler.who(mlist, args) self.assertTrue(re.search(self.testsub, output)) def testPassword(self): # Try setting it to a random password newpass = self.random_string(8) args = ['password', self.testlist, self.testlistpass, self.testsub, newpass] mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) output = mailman_admin_cmd_handler.password(mlist, args) self.assertTrue(re.search('^Password updated', output)) self.assertEquals(mlist.getMemberPassword(self.testsub), newpass) args = ['password', self.testlist, self.testlistpass, self.testsub, self.testsubpass] mailman_admin_cmd_handler.password(mlist, args) self.assertEquals(mlist.getMemberPassword(self.testsub), self.testsubpass) # Now try restoring to the original password args = ['password', self.testlist, self.testlistpass, self.testsub, self.testsubpass] mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) output = mailman_admin_cmd_handler.password(mlist, args) self.assertTrue(re.search('^Password updated', output)) self.assertEquals(mlist.getMemberPassword(self.testsub), self.testsubpass) # Note: We have to do so much mlist = None here bc of caching, I think def testSubscribeChangeUnsubscribe(self): # Subscribe a random address to the test list oldaddr = re.sub('\W', '', self.random_string(8)) + '@hotmail.com' mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) args = ['subscribe', self.testlist, self.testlistpass, oldaddr, 'digest', 'Test Subscriber'] output = mailman_admin_cmd_handler.subscribe(mlist, args) self.assertTrue(re.search('^Subscribed', output)) self.assertTrue(mlist.isMember(oldaddr)) mlist = None # Now change that to a different random address newaddr = re.sub('\W', '', self.random_string(9)) + '@hotmail.com' args = ['change', self.testlist, self.testlistpass, oldaddr, newaddr] mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) output = mailman_admin_cmd_handler.change(mlist, args) self.assertTrue(re.search('clone address added', output)) self.assertTrue(re.search('original address removed', output)) mlist = None mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) self.assertTrue(mlist.isMember(newaddr)) self.assertFalse(mlist.isMember(oldaddr)) mlist = None # Finally, restore list to its original state by removing test addr args = ['unsubscribe', self.testlist, self.testlistpass, newaddr] mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) output = mailman_admin_cmd_handler.unsubscribe(mlist, args) mlist = None mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) self.assertTrue(re.search('removed from list', output)) self.assertFalse(mlist.isMember(newaddr)) def testSet(self): mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) args = ['set', self.testlist, self.testlistpass, self.testsub, 'digest', 'mime'] output = mailman_admin_cmd_handler.set(mlist, args) args = ['set', self.testlist, self.testlistpass, self.testsub, 'delivery', 'off'] output = mailman_admin_cmd_handler.set(mlist, args) args = ['set', self.testlist, self.testlistpass, self.testsub, 'mod', 'on'] output = mailman_admin_cmd_handler.set(mlist, args) # Now check whether we were successful mlist = None mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) args = ['show', self.testlist, self.testlistpass, self.testsub] output = mailman_admin_cmd_handler.show(mlist, args) self.assertTrue(re.search('digest mime', output)) self.assertTrue(re.search('delivery off', output)) self.assertTrue(mlist.getMemberOption(self.testsub, mm_cfg.Moderate)) # Now restore to original good settings mlist = None mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) args = ['set', self.testlist, self.testlistpass, self.testsub, 'digest', 'off'] output = mailman_admin_cmd_handler.set(mlist, args) args = ['set', self.testlist, self.testlistpass, self.testsub, 'delivery', 'on'] output = mailman_admin_cmd_handler.set(mlist, args) args = ['set', self.testlist, self.testlistpass, self.testsub, 'mod', 'off'] output = mailman_admin_cmd_handler.set(mlist, args) def testShow(self): mlist = mailman_admin_cmd_handler.get_list_unlocked(self.testlist) args = ['show', self.testlist, self.testlistpass, self.testsub] output = mailman_admin_cmd_handler.show(mlist, args) self.assertTrue(re.search('^Current option settings for', output)) bademail = re.sub('\W', '', self.random_string(8)) + '@hotmail.com' args = ['show', self.testlist, self.testlistpass, bademail] output = mailman_admin_cmd_handler.show(mlist, args) self.assertTrue(re.search('^No such subscriber', output)) def testBadSubjectPasswd(self): self.set_input_msg(["invalid command\n"], "Bad Subject No Passwd") try: outlist = mailman_admin_cmd_handler.main() self.assertTrue(re.search('^Required password', outlist[0])) except SystemExit: pass self.restore_input() def testInvalidCommand(self): self.set_input_msg(["invalid command\n"]) outlist = mailman_admin_cmd_handler.main() self.assertTrue(re.search('^Unknown command:', outlist[0])) self.restore_input() def testInvalidCommandParameters(self): self.set_input_msg(["set badoption\n"]) outlist = mailman_admin_cmd_handler.main() self.assertTrue(re.search('^Usage:', outlist[0])) self.restore_input() def testEndCommand(self): self.set_input_msg(["end\n", "badcommand\n"]) outlist = mailman_admin_cmd_handler.main() self.assertEquals(len(outlist), 0) self.restore_input() def testHelpCommand(self): self.set_input_msg(["help\n"]) outlist = mailman_admin_cmd_handler.main() self.assertTrue(re.search('^Valid commands', outlist[0])) self.restore_input() def testUndefinedHandler(self): self.set_input_msg(["no_handler_test\n"]) outlist = mailman_admin_cmd_handler.main() self.assertTrue(re.search('^Undefined handler', outlist[0])) self.restore_input() def testBadAllOption(self): self.set_input_msg(["who all whateverpasswd\n"]) outlist = mailman_admin_cmd_handler.main() self.assertTrue(re.search('^all option not supported', outlist[0])) self.restore_input() def testInvalidListName(self): self.set_input_msg(["who badlistname badlistpass\n"]) outlist = mailman_admin_cmd_handler.main() self.assertTrue(re.search('^No such list:', outlist[0])) self.restore_input() def testInvalidListPass(self): badpass = self.random_string(8) # Test for a single list self.set_input_msg(['who ' + self.testlist + ' ' + badpass + "\n"]) outlist = mailman_admin_cmd_handler.main() self.assertTrue(re.search('Bad password:', outlist[0])) self.restore_input() # Also test for "all" lists bademail = re.sub('\W', '', self.random_string(8)) + '@hotmail.com' self.set_input_msg(['unsubscribe all ' + badpass + ' ' + bademail + "\n"]) outlist = mailman_admin_cmd_handler.main() self.assertTrue(self.text_in_list('Bad password:', outlist)) self.restore_input() def tearDown(self): sys.argv = MMCHTests.__argv__ if __name__ == '__main__': unittest.main() #suite = unittest.TestSuite() #suite.addTest(MMCHTests('testSet')) #suite.addTest(WebTests('testSearchPage')) #unittest.TextTestRunner().run(suite)