diff --git a/test/test.py b/test/test.py index 4e2f87413..f8ec25f7e 100755 --- a/test/test.py +++ b/test/test.py @@ -31,78 +31,21 @@ import supybot -import logging - import conf conf.dataDir = 'test-data' conf.confDir = 'test-conf' conf.logDir = 'test-log' conf.replyWhenNotCommand = False -conf.minimumLogPriority = logging.CRITICAL +conf.stdoutLogging = False import fix -import gc import re -import sys -import imp import glob -import time -started = time.time() import os.path import unittest import world -world.startedAt = started -import ircdb -import irclib -import drivers -import ircmsgs -import ircutils -import callbacks -import Owner -import Misc - -originalCallbacksGetHelp = callbacks.getHelp -lastGetHelp = 'x'*1000 -def cachingGetHelp(method, name=None): - global lastGetHelp - lastGetHelp = originalCallbacksGetHelp(method, name) - return lastGetHelp -callbacks.getHelp = cachingGetHelp - -nicks = ['fatjim','scn','moshez','LordVan','MetaCosm','pythong','fishfart', - 'alb','d0rt','jemfinch','StyxAlso','fors','deltab','gd', - 'hellz_hunter','are_j|pub_comp','jason_','dreid','sayke_','winjer', - 'TenOfTen','GoNoVas','queuetue','the|zzz','Hellfried','Therion', - 'shro','DaCa','rexec','polin8','r0ky','aaron_','ironfroggy','eugene', - 'faassen','tirloni','mackstann','Yhg1s','ElBarono','vegai','shang', - 'typo_','kikoforgetme','asqui','TazyTiggy','fab','nixman','liiwi', - 'AdamV','paolo','red_one','_AleX_','lament','jamessan','supybot', - 'macr0_zzz','plaisthos','redghost','disco','mphardy','gt3','mathie', - 'jonez','r0ky-office','tic','d33p','ES3merge','talin','af','flippo', - 'sholden','ameoba','shepherg','j2','Acapnotic','dash','merlin262', - 'Taaus','_moshez','rik','jafo__','blk-majik','JT__','itamar', - 'kermit-','davidmccabe','glyph','jojo','dave_p','goo','hyjinx', - 'SamB','exarkun','drewp','Ragica','skylan','redgore','k3','Ra1stlin', - 'StevenK','carball','h3x','carljm','_jacob','teratorn','frangen', - 'phed','datazone','Yaggo','acct_','nowhere','pyn','ThomasWaldmann', - 'dunker','pilotLight','brainless','LoganH_','jmpnz','steinn', - 'EliasREC','lowks__','OldSmrf','Mad77','snibril','delta','psy', - 'skimpIzu','Kengur','MoonFallen','kotkis','Hyperi'] - -fd = file(os.path.join('test', 'rfc2812.msgs'), 'r') -rawmsgs = [line.strip() for line in fd] -fd.close() - -msgs = [] -for s in rawmsgs: - try: - msgs.append(ircmsgs.IrcMsg(s)) - except: - print 'IrcMsg constructor failed: %r' % s - -nicks += [msg.nick for msg in msgs if msg.nick] class path(str): """A class to represent platform-independent paths.""" @@ -112,251 +55,6 @@ class path(str): def __eq__(self, other): return self._r.split(self) == self._r.split(other) -class TimeoutError(AssertionError): - def __str__(self): - return '%r timed out' % self.args[0] - -class PluginTestCase(unittest.TestCase): - """Subclass this to write a test case for a plugin. See test/test_Fun.py - for an example. - """ - timeout = 10 - plugins = None - cleanConfDir = True - cleanDataDir = True - def setUp(self, nick='test'): - # Set conf variables appropriately. - conf.prefixChars = '@' - conf.replyWhenNotCommand = False - self.myVerbose = world.myVerbose - if self.cleanConfDir: - for filename in os.listdir(conf.confDir): - os.remove(os.path.join(conf.confDir, filename)) - if self.cleanDataDir: - for filename in os.listdir(conf.dataDir): - os.remove(os.path.join(conf.dataDir, filename)) - ircdb.users.reload() - ircdb.channels.reload() - if self.plugins is None: - raise ValueError, 'PluginTestCase must have a "plugins" attribute.' - self.nick = nick - self.prefix = ircutils.joinHostmask(nick, 'user', 'host.domain.tld') - self.irc = irclib.Irc(nick) - while self.irc.takeMsg(): - pass - _ = Owner.loadPluginClass(self.irc, Owner) - _ = Owner.loadPluginClass(self.irc, Misc) - if isinstance(self.plugins, str): - if self.plugins not in ('Owner', 'Misc'): - module = Owner.loadPluginModule(self.plugins) - cb = Owner.loadPluginClass(self.irc, module) - else: - for name in self.plugins: - if name not in ('Owner', 'Misc'): - module = Owner.loadPluginModule(name) - cb = Owner.loadPluginClass(self.irc, module) - - def tearDown(self): - self.irc.die() - gc.collect() - - def _feedMsg(self, query, timeout=None): - if timeout is None: - timeout = self.timeout - if self.myVerbose: - print # Extra newline, so it's pretty. - msg = ircmsgs.privmsg(self.irc.nick, query, prefix=self.prefix) - if self.myVerbose: - print 'Feeding: %r' % msg - self.irc.feedMsg(msg) - fed = time.time() - response = self.irc.takeMsg() - while response is None and time.time() - fed < timeout: - time.sleep(0.1) # So it doesn't suck up 100% cpu. - drivers.run() - response = self.irc.takeMsg() - if self.myVerbose: - print 'Response: %r' % response - return response - - def getMsg(self, query, timeout=None): - return self._feedMsg(query, timeout=timeout) - - def feedMsg(self, query): - """Just feeds it a message, that's all.""" - self.irc.feedMsg(ircmsgs.privmsg(self.irc.nick, query, - prefix=self.prefix)) - - # These assertError/assertNoError are somewhat fragile. The proper way to - # do them would be to use a proxy for the irc object and intercept .error. - # But that would be hard, so I don't bother. When this breaks, it'll get - # fixed, but not until then. - def assertError(self, query): - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - if lastGetHelp not in m.args[1]: - self.failUnless(m.args[1].startswith('Error:'), - '%r did not error: %s' % (query, m.args[1])) - - def assertNotError(self, query): - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - self.failIf(m.args[1].startswith('Error:'), - '%r errored: %s' % (query, m.args[1])) - self.failIf(lastGetHelp in m.args[1], - '%r returned the help string.' % query) - - def assertHelp(self, query): - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - self.failUnless(lastGetHelp in m.args[1]) - - def assertNoResponse(self, query, timeout=None): - m = self._feedMsg(query, timeout) - self.failIf(m, 'Unexpected response: %r' % m) - - def assertResponse(self, query, expectedResponse): - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - self.assertEqual(m.args[1], expectedResponse, - '%r != %r' % (expectedResponse, m.args[1])) - - def assertRegexp(self, query, regexp, flags=re.I): - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - self.failUnless(re.search(regexp, m.args[1], flags), - '%r does not match %r' % (m.args[1], regexp)) - - def assertNotRegexp(self, query, regexp, flags=re.I): - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - self.failUnless(re.search(regexp, m.args[1], flags) is None, - '%r matched %r' % (m.args[1], regexp)) - - def assertRegexps(self, query, regexps): - started = time.time() - total = len(regexps)*self.timeout - while regexps and time.time() - started < total: - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - regexp = regexps.pop(0) - self.failUnless(re.search(regexp, m.args[1]), - '%r does not match %r' % (m.args[1], regexp)) - self.failIf(time.time() - started > total) - - def assertResponses(self, query, expectedResponses): - responses = [] - started = time.time() - while len(responses) < len(expectedResponses) and \ - time.time() - started > len(expectedResponses)*self.timeout: - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - responses.append(m) - self.assertEqual(len(expectedResponses), len(responses)) - for (m, expected) in zip(responses, expectedResponses): - self.assertEqual(m.args[1], expected) - - def assertAction(self, query, expectedResponse=None): - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - self.failUnless(ircmsgs.isAction(m)) - if expectedResponse is not None: - self.assertEqual(ircmsgs.unAction(m), expectedResponse) - - def assertActionRegexp(self, query, regexp, flags=re.I): - m = self._feedMsg(query) - if m is None: - raise TimeoutError, query - self.failUnless(ircmsgs.isAction(m)) - s = ircmsgs.unAction(m) - self.failUnless(re.search(regexp, s, flags), - '%r does not match %r' % (s, regexp)) - -class ChannelPluginTestCase(PluginTestCase): - channel = '#test' - def setUp(self): - PluginTestCase.setUp(self) - self.irc.feedMsg(ircmsgs.join(self.channel, prefix=self.prefix)) - - def _feedMsg(self, query, timeout=None): - if timeout is None: - timeout = self.timeout - if self.myVerbose: - print # Newline, just like PluginTestCase. - if query[0] not in conf.prefixChars: - query = conf.prefixChars[0] + query - msg = ircmsgs.privmsg(self.channel, query, prefix=self.prefix) - if self.myVerbose: - print 'Feeding: %r' % msg - self.irc.feedMsg(msg) - fed = time.time() - response = self.irc.takeMsg() - while response is None and time.time() - fed < timeout: - drivers.run() - response = self.irc.takeMsg() - if response is not None: - if response.command == 'PRIVMSG': - args = list(response.args) - # Strip off nick: at beginning of response. - if args[1].startswith(self.nick) or \ - args[1].startswith(ircutils.nickFromHostmask(self.prefix)): - args[1] = args[1].split(' ', 1)[1] - ret = ircmsgs.privmsg(*args) - else: - ret = response - else: - ret = None - if self.myVerbose: - print 'Returning: %r' % ret - return ret - - def feedMsg(self, query): - """Just feeds it a message, that's all.""" - self.irc.feedMsg(ircmsgs.privmsg(self.channel, query, - prefix=self.prefix)) - - -class PluginDocumentation: - def testAllCommandsHaveHelp(self): - for cb in self.irc.callbacks: - if isinstance(cb, callbacks.PrivmsgRegexp): - continue - if hasattr(cb, 'isCommand'): - for attr in cb.__class__.__dict__: - if cb.isCommand(attr): - self.failUnless(getattr(cb, attr).__doc__, - '%s has no syntax' % attr) - - def testAllCommandsHaveMorehelp(self): - for cb in self.irc.callbacks: - if isinstance(cb, callbacks.PrivmsgRegexp): - continue - if hasattr(cb, 'isCommand'): - for attr in cb.__class__.__dict__: - if cb.isCommand(attr): - command = getattr(cb, attr) - helps = command.__doc__ - self.failUnless(helps and len(helps.splitlines()) >= 3, - '%s has no help' % attr) - - def testPluginHasDocumentation(self): - for cb in self.irc.callbacks: - m = sys.modules[cb.__class__.__module__] - self.failIf(m.__doc__ is None, - '%s has no module documentation'%cb.__class__.__name__) - - - - if __name__ == '__main__': import optparse @@ -369,11 +67,11 @@ if __name__ == '__main__': if not os.path.exists(conf.logDir): os.mkdir(conf.logDir) - for filename in os.listdir(conf.logDir): - if filename == 'plugins': - continue - filename = os.path.join(conf.logDir, filename) - os.remove(filename) +## for filename in os.listdir(conf.logDir): +## if filename == 'plugins': +## continue +## filename = os.path.join(conf.logDir, filename) +## os.remove(filename) pluginLogDir = os.path.join(conf.logDir, 'plugins') for filename in os.listdir(pluginLogDir): os.remove(os.path.join(pluginLogDir, filename)) @@ -421,6 +119,5 @@ if __name__ == '__main__': runner = unittest.TextTestRunner(verbosity=2) runner.run(suite) print 'Total asserts: %s' % unittest.asserts - world.testing = False # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: diff --git a/test/test_Admin.py b/test/test_Admin.py index 211bc0518..843c80360 100644 --- a/test/test_Admin.py +++ b/test/test_Admin.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import conf diff --git a/test/test_Alias.py b/test/test_Alias.py index ae5ce1c55..1f3956589 100644 --- a/test/test_Alias.py +++ b/test/test_Alias.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * Alias = Owner.loadPluginModule('Alias') diff --git a/test/test_Amazon.py b/test/test_Amazon.py index 61da444b1..4f2a00839 100644 --- a/test/test_Amazon.py +++ b/test/test_Amazon.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class AmazonTestCase(PluginTestCase, PluginDocumentation): plugins = ('Amazon',) diff --git a/test/test_Babelfish.py b/test/test_Babelfish.py index e0edd60db..3fd702d2d 100644 --- a/test/test_Babelfish.py +++ b/test/test_Babelfish.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class BabelFishTestCase(PluginTestCase, PluginDocumentation): plugins = ('Babelfish',) diff --git a/test/test_BadWords.py b/test/test_BadWords.py index 198156d4e..5b5f368c3 100644 --- a/test/test_BadWords.py +++ b/test/test_BadWords.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class BadWordsTestCase(PluginTestCase, PluginDocumentation): plugins = ('BadWords', 'Utilities') diff --git a/test/test_Bugzilla.py b/test/test_Bugzilla.py index 359060939..8aa6ba354 100644 --- a/test/test_Bugzilla.py +++ b/test/test_Bugzilla.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class BugzillaTest(PluginTestCase, PluginDocumentation): plugins = ('Bugzilla',) diff --git a/test/test_Channel.py b/test/test_Channel.py index f11c099cf..295da4565 100644 --- a/test/test_Channel.py +++ b/test/test_Channel.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import conf import ircdb diff --git a/test/test_ChannelDB.py b/test/test_ChannelDB.py index 3b91bc91e..bb06c409c 100644 --- a/test/test_ChannelDB.py +++ b/test/test_ChannelDB.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import ircdb diff --git a/test/test_Ctcp.py b/test/test_Ctcp.py index e185084ad..0935788bc 100644 --- a/test/test_Ctcp.py +++ b/test/test_Ctcp.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class CtcpTestCase(PluginTestCase): plugins = ('Ctcp',) diff --git a/test/test_DCC.py b/test/test_DCC.py index 3536d072d..3a68c9606 100644 --- a/test/test_DCC.py +++ b/test/test_DCC.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import time import telnetlib diff --git a/test/test_Debian.py b/test/test_Debian.py index e50f9b926..0fe5c5100 100644 --- a/test/test_Debian.py +++ b/test/test_Debian.py @@ -32,7 +32,7 @@ import os import time -from test import * +from testsupport import * class DebianTestCase(PluginTestCase, PluginDocumentation): plugins = ('Debian',) diff --git a/test/test_Dict.py b/test/test_Dict.py index 9fc24ae9c..21944288d 100644 --- a/test/test_Dict.py +++ b/test/test_Dict.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class DictTestCase(PluginTestCase, PluginDocumentation): plugins = ('Dict', 'Misc') diff --git a/test/test_Dunno.py b/test/test_Dunno.py index c8adf7d85..b5f2f533c 100644 --- a/test/test_Dunno.py +++ b/test/test_Dunno.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * try: import sqlite diff --git a/test/test_Ebay.py b/test/test_Ebay.py index 970850a16..bdde91322 100644 --- a/test/test_Ebay.py +++ b/test/test_Ebay.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class EbayTest(PluginTestCase, PluginDocumentation): plugins = ('Ebay',) diff --git a/test/test_Enforcer.py b/test/test_Enforcer.py index 5ac823d7a..4773269a5 100644 --- a/test/test_Enforcer.py +++ b/test/test_Enforcer.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class EnforcerTestCase(PluginTestCase, PluginDocumentation): plugins = ('Enforcer',) diff --git a/test/test_Factoids.py b/test/test_Factoids.py index 967b29c6a..06d8e8e90 100644 --- a/test/test_Factoids.py +++ b/test/test_Factoids.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * try: import sqlite diff --git a/test/test_FixRelayBot.py b/test/test_FixRelayBot.py index d03f10c9c..2a2fc38bf 100644 --- a/test/test_FixRelayBot.py +++ b/test/test_FixRelayBot.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import ircmsgs diff --git a/test/test_Friendly.py b/test/test_Friendly.py index efa2c86d8..ab5e6e05e 100644 --- a/test/test_Friendly.py +++ b/test/test_Friendly.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class FriendlyTestCase(PluginTestCase): plugins = ('Friendly',) diff --git a/test/test_Fun.py b/test/test_Fun.py index b3354183c..83dece44a 100644 --- a/test/test_Fun.py +++ b/test/test_Fun.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import re diff --git a/test/test_FunDB.py b/test/test_FunDB.py index 4db9f1ee5..7e36ebc0d 100644 --- a/test/test_FunDB.py +++ b/test/test_FunDB.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import ircdb diff --git a/test/test_Gameknot.py b/test/test_Gameknot.py index a8f457bd4..44cb3252d 100644 --- a/test/test_Gameknot.py +++ b/test/test_Gameknot.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import utils diff --git a/test/test_Google.py b/test/test_Google.py index 3a83f4f52..c016badf9 100644 --- a/test/test_Google.py +++ b/test/test_Google.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class GoogleTestCase(ChannelPluginTestCase, PluginDocumentation): plugins = ('Google',) diff --git a/test/test_Http.py b/test/test_Http.py index 539d43548..ffa5fe16b 100644 --- a/test/test_Http.py +++ b/test/test_Http.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class HttpTest(PluginTestCase, PluginDocumentation): plugins = ('Http',) diff --git a/test/test_Karma.py b/test/test_Karma.py index 93e28cfb5..b6c1c35db 100644 --- a/test/test_Karma.py +++ b/test/test_Karma.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import conf diff --git a/test/test_Lookup.py b/test/test_Lookup.py index bbd79eb18..18d018b91 100644 --- a/test/test_Lookup.py +++ b/test/test_Lookup.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import os diff --git a/test/test_Markov.py b/test/test_Markov.py index c0a24291e..2a7d04b96 100644 --- a/test/test_Markov.py +++ b/test/test_Markov.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * try: import sqlite diff --git a/test/test_Math.py b/test/test_Math.py index 301d84b8d..ad5d5b9a1 100644 --- a/test/test_Math.py +++ b/test/test_Math.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class MathTestCase(PluginTestCase, PluginDocumentation): plugins = ('Math',) diff --git a/test/test_Misc.py b/test/test_Misc.py index 27eedc40f..d7632ab5b 100644 --- a/test/test_Misc.py +++ b/test/test_Misc.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class MiscTestCase(ChannelPluginTestCase, PluginDocumentation): plugins = ('Misc', 'Utilities', 'Gameknot', 'Ctcp') diff --git a/test/test_MoobotFactoids.py b/test/test_MoobotFactoids.py index 70b04bf1d..67df13477 100644 --- a/test/test_MoobotFactoids.py +++ b/test/test_MoobotFactoids.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * try: import sqlite diff --git a/test/test_Movies.py b/test/test_Movies.py index 665712b2e..ee7892877 100644 --- a/test/test_Movies.py +++ b/test/test_Movies.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class MoviesTestCase(PluginTestCase, PluginDocumentation): plugins = ('Movies',) diff --git a/test/test_Network.py b/test/test_Network.py index 6eb9bb5a9..6ce2a89d0 100644 --- a/test/test_Network.py +++ b/test/test_Network.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class NetworkTestCase(PluginTestCase, PluginDocumentation): plugins = ['Network'] diff --git a/test/test_News.py b/test/test_News.py index c20ab1ce5..1605b67a0 100644 --- a/test/test_News.py +++ b/test/test_News.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import time diff --git a/test/test_Note.py b/test/test_Note.py index ade020d29..3e188c17e 100644 --- a/test/test_Note.py +++ b/test/test_Note.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import utils import ircdb diff --git a/test/test_OSU.py b/test/test_OSU.py index bd65a8ff0..f4f236292 100644 --- a/test/test_OSU.py +++ b/test/test_OSU.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class OSUTestCase(PluginTestCase, PluginDocumentation): plugins = ('OSU',) diff --git a/test/test_Owner.py b/test/test_Owner.py index 4db836414..1b779af0e 100644 --- a/test/test_Owner.py +++ b/test/test_Owner.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import conf import Owner diff --git a/test/test_Parter.py b/test/test_Parter.py index 7e16d6251..1204c67ac 100644 --- a/test/test_Parter.py +++ b/test/test_Parter.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import ircmsgs diff --git a/test/test_Poll.py b/test/test_Poll.py index 8ac442c4c..b158cf63d 100644 --- a/test/test_Poll.py +++ b/test/test_Poll.py @@ -30,7 +30,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import utils import ircdb diff --git a/test/test_Python.py b/test/test_Python.py index 87aa57fcd..8a8532183 100644 --- a/test/test_Python.py +++ b/test/test_Python.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import os diff --git a/test/test_QuoteGrabs.py b/test/test_QuoteGrabs.py index 319aaa36c..3b56a2553 100644 --- a/test/test_QuoteGrabs.py +++ b/test/test_QuoteGrabs.py @@ -31,7 +31,7 @@ import sets -from test import * +from testsupport import * try: import sqlite diff --git a/test/test_Quotes.py b/test/test_Quotes.py index 55b58ad6a..a9c434116 100644 --- a/test/test_Quotes.py +++ b/test/test_Quotes.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * try: import sqlite diff --git a/test/test_RSS.py b/test/test_RSS.py index 197f75174..ddbf31bea 100644 --- a/test/test_RSS.py +++ b/test/test_RSS.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class RSSTestCase(PluginTestCase, PluginDocumentation): plugins = ('RSS',) diff --git a/test/test_Relay.py b/test/test_Relay.py index 131611a78..dfefdab1e 100644 --- a/test/test_Relay.py +++ b/test/test_Relay.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class RelayTestCase(PluginTestCase, PluginDocumentation): plugins = ('Relay',) diff --git a/test/test_RootWarner.py b/test/test_RootWarner.py index b4ad09321..a1e14555c 100644 --- a/test/test_RootWarner.py +++ b/test/test_RootWarner.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class RootWarnerTestCase(PluginTestCase): plugins = ('RootWarner',) diff --git a/test/test_Services.py b/test/test_Services.py index 86deccbc1..5d1258025 100644 --- a/test/test_Services.py +++ b/test/test_Services.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class ServicesTestCase(PluginTestCase, PluginDocumentation): plugins = ('Services',) diff --git a/test/test_Sourceforge.py b/test/test_Sourceforge.py index 48323c1b5..afc521f4f 100644 --- a/test/test_Sourceforge.py +++ b/test/test_Sourceforge.py @@ -31,7 +31,7 @@ import re -from test import * +from testsupport import * class SourceforgeTest(ChannelPluginTestCase, PluginDocumentation): plugins = ('Sourceforge',) diff --git a/test/test_Status.py b/test/test_Status.py index a392d8a55..733869777 100644 --- a/test/test_Status.py +++ b/test/test_Status.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import sys diff --git a/test/test_Todo.py b/test/test_Todo.py index 42042eabb..f1c37c7fb 100644 --- a/test/test_Todo.py +++ b/test/test_Todo.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * try: import sqlite diff --git a/test/test_Topic.py b/test/test_Topic.py index d68cdc996..53ed5d574 100644 --- a/test/test_Topic.py +++ b/test/test_Topic.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class TopicTestCase(ChannelPluginTestCase, PluginDocumentation): plugins = ('Topic',) diff --git a/test/test_URL.py b/test/test_URL.py index b81ac4ea1..71cadf96a 100644 --- a/test/test_URL.py +++ b/test/test_URL.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * urls = """ http://www.ureg.ohio-state.edu/courses/book3.asp diff --git a/test/test_Unix.py b/test/test_Unix.py index 5ea51ff1d..cca526c88 100644 --- a/test/test_Unix.py +++ b/test/test_Unix.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import os diff --git a/test/test_User.py b/test/test_User.py index 645a5b645..46f8f73ba 100644 --- a/test/test_User.py +++ b/test/test_User.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import ircdb diff --git a/test/test_Utilities.py b/test/test_Utilities.py index 140a4e8c6..9e07cb3a9 100644 --- a/test/test_Utilities.py +++ b/test/test_Utilities.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * class UtilitiesTestCase(PluginTestCase, PluginDocumentation): plugins = ('Utilities', 'Status') diff --git a/test/test_callbacks.py b/test/test_callbacks.py index 195666788..3ed7a3da2 100644 --- a/test/test_callbacks.py +++ b/test/test_callbacks.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import conf import utils diff --git a/test/test_fix.py b/test/test_fix.py index 00bcace4d..380b0270d 100644 --- a/test/test_fix.py +++ b/test/test_fix.py @@ -31,7 +31,7 @@ ## from __future__ import generators -from test import * +from testsupport import * import itertools diff --git a/test/test_ircdb.py b/test/test_ircdb.py index 410a97833..ef0708a27 100644 --- a/test/test_ircdb.py +++ b/test/test_ircdb.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import os import unittest diff --git a/test/test_irclib.py b/test/test_irclib.py index 6987e741f..71e313a6e 100644 --- a/test/test_irclib.py +++ b/test/test_irclib.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import copy import pickle diff --git a/test/test_ircmsgs.py b/test/test_ircmsgs.py index 36b639e1c..237b0690f 100644 --- a/test/test_ircmsgs.py +++ b/test/test_ircmsgs.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import copy import pickle diff --git a/test/test_ircutils.py b/test/test_ircutils.py index ef6ab3292..06d8d73d2 100644 --- a/test/test_ircutils.py +++ b/test/test_ircutils.py @@ -30,7 +30,7 @@ ### -from test import * +from testsupport import * import copy import random diff --git a/test/test_plugins.py b/test/test_plugins.py index beacc9491..e5957cf5e 100644 --- a/test/test_plugins.py +++ b/test/test_plugins.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import sets diff --git a/test/test_privmsgs.py b/test/test_privmsgs.py index b522744e9..70ad1576a 100644 --- a/test/test_privmsgs.py +++ b/test/test_privmsgs.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import ircmsgs import privmsgs diff --git a/test/test_schedule.py b/test/test_schedule.py index e75bef927..53b89b32b 100644 --- a/test/test_schedule.py +++ b/test/test_schedule.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import time diff --git a/test/test_structures.py b/test/test_structures.py index 737411eca..c5439f68f 100644 --- a/test/test_structures.py +++ b/test/test_structures.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import pickle diff --git a/test/test_utils.py b/test/test_utils.py index 618a4705a..a4b46fe93 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -29,7 +29,7 @@ # POSSIBILITY OF SUCH DAMAGE. ### -from test import * +from testsupport import * import sets import utils diff --git a/test/testsupport.py b/test/testsupport.py new file mode 100644 index 000000000..058cfaf16 --- /dev/null +++ b/test/testsupport.py @@ -0,0 +1,343 @@ +#!/usr/bin/env python + +### +# Copyright (c) 2002, Jeremiah Fincher +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + +import fix + +import gc +import os +import re +import sys +import time +started = time.time() +import unittest + +import conf +import ircdb +import world +world.startedAt = started +import irclib +import drivers +import ircmsgs +import ircutils +import callbacks + +import Owner +import Misc + +nicks = ['fatjim','scn','moshez','LordVan','MetaCosm','pythong','fishfart', + 'alb','d0rt','jemfinch','StyxAlso','fors','deltab','gd', + 'hellz_hunter','are_j|pub_comp','jason_','dreid','sayke_','winjer', + 'TenOfTen','GoNoVas','queuetue','the|zzz','Hellfried','Therion', + 'shro','DaCa','rexec','polin8','r0ky','aaron_','ironfroggy','eugene', + 'faassen','tirloni','mackstann','Yhg1s','ElBarono','vegai','shang', + 'typo_','kikoforgetme','asqui','TazyTiggy','fab','nixman','liiwi', + 'AdamV','paolo','red_one','_AleX_','lament','jamessan','supybot', + 'macr0_zzz','plaisthos','redghost','disco','mphardy','gt3','mathie', + 'jonez','r0ky-office','tic','d33p','ES3merge','talin','af','flippo', + 'sholden','ameoba','shepherg','j2','Acapnotic','dash','merlin262', + 'Taaus','_moshez','rik','jafo__','blk-majik','JT__','itamar', + 'kermit-','davidmccabe','glyph','jojo','dave_p','goo','hyjinx', + 'SamB','exarkun','drewp','Ragica','skylan','redgore','k3','Ra1stlin', + 'StevenK','carball','h3x','carljm','_jacob','teratorn','frangen', + 'phed','datazone','Yaggo','acct_','nowhere','pyn','ThomasWaldmann', + 'dunker','pilotLight','brainless','LoganH_','jmpnz','steinn', + 'EliasREC','lowks__','OldSmrf','Mad77','snibril','delta','psy', + 'skimpIzu','Kengur','MoonFallen','kotkis','Hyperi'] + +fd = file(os.path.join('test', 'rfc2812.msgs'), 'r') +rawmsgs = [line.strip() for line in fd] +fd.close() + +msgs = [] +for s in rawmsgs: + try: + msgs.append(ircmsgs.IrcMsg(s)) + except: + print 'IrcMsg constructor failed: %r' % s + +nicks += [msg.nick for msg in msgs if msg.nick] + +originalCallbacksGetHelp = callbacks.getHelp +lastGetHelp = 'x'*1000 +def cachingGetHelp(method, name=None): + global lastGetHelp + lastGetHelp = originalCallbacksGetHelp(method, name) + return lastGetHelp +callbacks.getHelp = cachingGetHelp + +class TimeoutError(AssertionError): + def __str__(self): + return '%r timed out' % self.args[0] + +class PluginTestCase(unittest.TestCase): + """Subclass this to write a test case for a plugin. See test/test_Fun.py + for an example. + """ + timeout = 10 + plugins = None + cleanConfDir = True + cleanDataDir = True + def setUp(self, nick='test'): + # Set conf variables appropriately. + conf.prefixChars = '@' + conf.replyWhenNotCommand = False + self.myVerbose = world.myVerbose + if self.cleanConfDir: + for filename in os.listdir(conf.confDir): + os.remove(os.path.join(conf.confDir, filename)) + if self.cleanDataDir: + for filename in os.listdir(conf.dataDir): + os.remove(os.path.join(conf.dataDir, filename)) + ircdb.users.reload() + ircdb.channels.reload() + if self.plugins is None: + raise ValueError, 'PluginTestCase must have a "plugins" attribute.' + self.nick = nick + self.prefix = ircutils.joinHostmask(nick, 'user', 'host.domain.tld') + self.irc = irclib.Irc(nick) + while self.irc.takeMsg(): + pass + _ = Owner.loadPluginClass(self.irc, Owner) + _ = Owner.loadPluginClass(self.irc, Misc) + if isinstance(self.plugins, str): + if self.plugins not in ('Owner', 'Misc'): + module = Owner.loadPluginModule(self.plugins) + cb = Owner.loadPluginClass(self.irc, module) + else: + for name in self.plugins: + if name not in ('Owner', 'Misc'): + module = Owner.loadPluginModule(name) + cb = Owner.loadPluginClass(self.irc, module) + + def tearDown(self): + self.irc.die() + gc.collect() + + def _feedMsg(self, query, timeout=None): + if timeout is None: + timeout = self.timeout + if self.myVerbose: + print # Extra newline, so it's pretty. + msg = ircmsgs.privmsg(self.irc.nick, query, prefix=self.prefix) + if self.myVerbose: + print 'Feeding: %r' % msg + self.irc.feedMsg(msg) + fed = time.time() + response = self.irc.takeMsg() + while response is None and time.time() - fed < timeout: + time.sleep(0.1) # So it doesn't suck up 100% cpu. + drivers.run() + response = self.irc.takeMsg() + if self.myVerbose: + print 'Response: %r' % response + return response + + def getMsg(self, query, timeout=None): + return self._feedMsg(query, timeout=timeout) + + def feedMsg(self, query): + """Just feeds it a message, that's all.""" + self.irc.feedMsg(ircmsgs.privmsg(self.irc.nick, query, + prefix=self.prefix)) + + # These assertError/assertNoError are somewhat fragile. The proper way to + # do them would be to use a proxy for the irc object and intercept .error. + # But that would be hard, so I don't bother. When this breaks, it'll get + # fixed, but not until then. + def assertError(self, query): + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + if lastGetHelp not in m.args[1]: + self.failUnless(m.args[1].startswith('Error:'), + '%r did not error: %s' % (query, m.args[1])) + + def assertNotError(self, query): + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + self.failIf(m.args[1].startswith('Error:'), + '%r errored: %s' % (query, m.args[1])) + self.failIf(lastGetHelp in m.args[1], + '%r returned the help string.' % query) + + def assertHelp(self, query): + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + self.failUnless(lastGetHelp in m.args[1]) + + def assertNoResponse(self, query, timeout=None): + m = self._feedMsg(query, timeout) + self.failIf(m, 'Unexpected response: %r' % m) + + def assertResponse(self, query, expectedResponse): + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + self.assertEqual(m.args[1], expectedResponse, + '%r != %r' % (expectedResponse, m.args[1])) + + def assertRegexp(self, query, regexp, flags=re.I): + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + self.failUnless(re.search(regexp, m.args[1], flags), + '%r does not match %r' % (m.args[1], regexp)) + + def assertNotRegexp(self, query, regexp, flags=re.I): + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + self.failUnless(re.search(regexp, m.args[1], flags) is None, + '%r matched %r' % (m.args[1], regexp)) + + def assertRegexps(self, query, regexps): + started = time.time() + total = len(regexps)*self.timeout + while regexps and time.time() - started < total: + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + regexp = regexps.pop(0) + self.failUnless(re.search(regexp, m.args[1]), + '%r does not match %r' % (m.args[1], regexp)) + self.failIf(time.time() - started > total) + + def assertResponses(self, query, expectedResponses): + responses = [] + started = time.time() + while len(responses) < len(expectedResponses) and \ + time.time() - started > len(expectedResponses)*self.timeout: + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + responses.append(m) + self.assertEqual(len(expectedResponses), len(responses)) + for (m, expected) in zip(responses, expectedResponses): + self.assertEqual(m.args[1], expected) + + def assertAction(self, query, expectedResponse=None): + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + self.failUnless(ircmsgs.isAction(m)) + if expectedResponse is not None: + self.assertEqual(ircmsgs.unAction(m), expectedResponse) + + def assertActionRegexp(self, query, regexp, flags=re.I): + m = self._feedMsg(query) + if m is None: + raise TimeoutError, query + self.failUnless(ircmsgs.isAction(m)) + s = ircmsgs.unAction(m) + self.failUnless(re.search(regexp, s, flags), + '%r does not match %r' % (s, regexp)) + +class ChannelPluginTestCase(PluginTestCase): + channel = '#test' + def setUp(self): + PluginTestCase.setUp(self) + self.irc.feedMsg(ircmsgs.join(self.channel, prefix=self.prefix)) + + def _feedMsg(self, query, timeout=None): + if timeout is None: + timeout = self.timeout + if self.myVerbose: + print # Newline, just like PluginTestCase. + if query[0] not in conf.prefixChars: + query = conf.prefixChars[0] + query + msg = ircmsgs.privmsg(self.channel, query, prefix=self.prefix) + if self.myVerbose: + print 'Feeding: %r' % msg + self.irc.feedMsg(msg) + fed = time.time() + response = self.irc.takeMsg() + while response is None and time.time() - fed < timeout: + drivers.run() + response = self.irc.takeMsg() + if response is not None: + if response.command == 'PRIVMSG': + args = list(response.args) + # Strip off nick: at beginning of response. + if args[1].startswith(self.nick) or \ + args[1].startswith(ircutils.nickFromHostmask(self.prefix)): + args[1] = args[1].split(' ', 1)[1] + ret = ircmsgs.privmsg(*args) + else: + ret = response + else: + ret = None + if self.myVerbose: + print 'Returning: %r' % ret + return ret + + def feedMsg(self, query): + """Just feeds it a message, that's all.""" + self.irc.feedMsg(ircmsgs.privmsg(self.channel, query, + prefix=self.prefix)) + + +class PluginDocumentation: + def testAllCommandsHaveHelp(self): + for cb in self.irc.callbacks: + if isinstance(cb, callbacks.PrivmsgRegexp): + continue + if hasattr(cb, 'isCommand'): + for attr in cb.__class__.__dict__: + if cb.isCommand(attr): + self.failUnless(getattr(cb, attr).__doc__, + '%s has no syntax' % attr) + + def testAllCommandsHaveMorehelp(self): + for cb in self.irc.callbacks: + if isinstance(cb, callbacks.PrivmsgRegexp): + continue + if hasattr(cb, 'isCommand'): + for attr in cb.__class__.__dict__: + if cb.isCommand(attr): + command = getattr(cb, attr) + helps = command.__doc__ + self.failUnless(helps and len(helps.splitlines()) >= 3, + '%s has no help' % attr) + + def testPluginHasDocumentation(self): + for cb in self.irc.callbacks: + m = sys.modules[cb.__class__.__module__] + self.failIf(m.__doc__ is None, + '%s has no module documentation'%cb.__class__.__name__) + + + + + +# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: +