mirror of
				https://github.com/Mikaela/Limnoria.git
				synced 2025-10-25 05:27:23 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			228 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/env python
 | |
| 
 | |
| ###
 | |
| # Copyright (c) 2002-2005, Jeremiah Fincher
 | |
| # Copyright (c) 2011, James McCoy
 | |
| # 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 os
 | |
| import sys
 | |
| import time
 | |
| import shutil
 | |
| started = time.time()
 | |
| 
 | |
| import supybot
 | |
| import logging
 | |
| import traceback
 | |
| 
 | |
| # We need to do this before we import conf.
 | |
| if not os.path.exists('test-conf'):
 | |
|     os.mkdir('test-conf')
 | |
| 
 | |
| registryFilename = os.path.join('test-conf', 'test.conf')
 | |
| fd = open(registryFilename, 'w')
 | |
| fd.write("""
 | |
| supybot.directories.data: test-data
 | |
| supybot.directories.conf: test-conf
 | |
| supybot.directories.log: test-logs
 | |
| supybot.reply.whenNotCommand: True
 | |
| supybot.log.stdout: False
 | |
| supybot.log.level: DEBUG
 | |
| supybot.log.format: %(levelname)s %(message)s
 | |
| supybot.log.plugins.individualLogfiles: False
 | |
| supybot.protocols.irc.throttleTime: 0
 | |
| supybot.reply.whenAddressedBy.chars: @
 | |
| supybot.networks.test.server: should.not.need.this
 | |
| supybot.nick: test
 | |
| supybot.databases.users.allowUnregistration: True
 | |
| """)
 | |
| fd.close()
 | |
| 
 | |
| import supybot.registry as registry
 | |
| registry.open_registry(registryFilename)
 | |
| 
 | |
| import supybot.log as log
 | |
| import supybot.conf as conf
 | |
| conf.allowEval = True
 | |
| conf.supybot.flush.setValue(False)
 | |
| 
 | |
| import re
 | |
| import sys
 | |
| import glob
 | |
| import atexit
 | |
| import os.path
 | |
| import unittest
 | |
| 
 | |
| import supybot.utils as utils
 | |
| import supybot.world as world
 | |
| import supybot.callbacks as callbacks
 | |
| world.startedAt = started
 | |
| 
 | |
| import logging
 | |
| class TestLogFilter(logging.Filter):
 | |
|     bads = [
 | |
|         'No callbacks in',
 | |
|         'Invalid channel database',
 | |
|         'Exact error',
 | |
|         'Invalid user dictionary',
 | |
|         'because of noFlush',
 | |
|         'Queuing NICK',
 | |
|         'Queuing USER',
 | |
|         'IgnoresDB.reload failed',
 | |
|         'Starting log for',
 | |
|         'Irc object for test dying',
 | |
|         'Last Irc,',
 | |
|         ]
 | |
|     def filter(self, record):
 | |
|         for bad in self.bads:
 | |
|             if bad in record.msg:
 | |
|                 return False
 | |
|         return True
 | |
| log._logger.addFilter(TestLogFilter())
 | |
| 
 | |
| class path(str):
 | |
|     """A class to represent platform-independent paths."""
 | |
|     _r = re.compile(r'[\\/]')
 | |
|     def __hash__(self):
 | |
|         return reduce(lambda h, s: h ^ hash(s), self._r.split(self), 0)
 | |
|     def __eq__(self, other):
 | |
|         return self._r.split(self) == self._r.split(other)
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     import glob
 | |
|     import os.path
 | |
|     import optparse
 | |
|     import supybot.test as test
 | |
|     import supybot.plugin as plugin
 | |
| 
 | |
|     parser = optparse.OptionParser(usage='Usage: %prog [options] [plugins]',
 | |
|                                    version='Supybot %s' % conf.version)
 | |
|     parser.add_option('-c', '--clean', action='store_true', default=False,
 | |
|                       dest='clean', help='Cleans the various data/conf/logs'
 | |
|                       'directories before running tests.')
 | |
|     parser.add_option('-t', '--timeout', action='store', type='float',
 | |
|                       dest='timeout',
 | |
|                       help='Sets the timeout, in seconds, for tests to return '
 | |
|                       'responses.')
 | |
|     parser.add_option('-v', '--verbose', action='store_true', default=False,
 | |
|                       help='Sets the verbose flag, logging extra information '
 | |
|                            'about each test that runs.')
 | |
|     parser.add_option('', '--no-network', action='store_true', default=False,
 | |
|                       dest='nonetwork', help='Causes the network-based tests '
 | |
|                                              'not to run.')
 | |
|     parser.add_option('', '--trace', action='store_true', default=False,
 | |
|                       help='Traces all calls made.  Unless you\'re really in '
 | |
|                       'a pinch, you probably shouldn\'t do this; it results '
 | |
|                       'in copious amounts of output.')
 | |
|     parser.add_option('', '--plugins-dir',
 | |
|                       action='append', dest='pluginsDirs', default=[],
 | |
|                       help='Looks in in the given directory for plugins and '
 | |
|                       'loads the tests from all of them.')
 | |
|     parser.add_option('', '--exclude',
 | |
|                       action='append', dest='excludePlugins', default=[],
 | |
|                       help='List of plugins you do not want --plugins-dir '
 | |
|                       'to include.')
 | |
|     parser.add_option('', '--disable-multiprocessing', action='store_true',
 | |
|                       dest='disableMultiprocessing',
 | |
|                       help='Disables multiprocessing stuff.')
 | |
|     (options, args) = parser.parse_args()
 | |
| 
 | |
|     world.disableMultiprocessing = options.disableMultiprocessing
 | |
| 
 | |
|     # This must go before checking for args, of course.
 | |
|     for pluginDir in options.pluginsDirs:
 | |
|         for name in glob.glob(os.path.join(pluginDir, '*')):
 | |
|             #print '***', name
 | |
|             if not any(map(lambda x:name in x,
 | |
|                            map(glob.glob, options.excludePlugins))) and \
 | |
|                     os.path.isdir(name):
 | |
|                 args.append(name)
 | |
| 
 | |
|     if not args:
 | |
|         parser.print_help()
 | |
|         sys.exit(-1)
 | |
| 
 | |
|     if options.timeout:
 | |
|         test.timeout = options.timeout
 | |
| 
 | |
|     if options.trace:
 | |
|         traceFilename = conf.supybot.directories.log.dirize('trace.log')
 | |
|         fd = open(traceFilename, 'w')
 | |
|         sys.settrace(utils.gen.callTracer(fd))
 | |
|         atexit.register(fd.close)
 | |
|         atexit.register(lambda : sys.settrace(None))
 | |
| 
 | |
|     if options.verbose:
 | |
|         world.myVerbose = True
 | |
|     else:
 | |
|         world.myVerbose = False
 | |
| 
 | |
|     if options.nonetwork:
 | |
|         test.network = False
 | |
| 
 | |
|     log.testing = True
 | |
|     world.testing = True
 | |
| 
 | |
|     args = [s.rstrip('\\/') for s in args]
 | |
|     pluginDirs = set([os.path.dirname(s) or '.' for s in args])
 | |
|     conf.supybot.directories.plugins.setValue(list(pluginDirs))
 | |
|     pluginNames = set([os.path.basename(s) for s in args])
 | |
|     load = unittest.defaultTestLoader.loadTestsFromModule
 | |
|     for pluginName in pluginNames:
 | |
|         if pluginName.endswith('.py'):
 | |
|             pluginName = pluginName[:-3]
 | |
|         try:
 | |
|             pluginModule = plugin.loadPluginModule(pluginName)
 | |
|         except (ImportError, callbacks.Error) as e:
 | |
|             sys.stderr.write('Failed to load plugin %s:' % pluginName)
 | |
|             traceback.print_exc()
 | |
|             sys.stderr.write('(pluginDirs: %s)\n' %
 | |
|                              conf.supybot.directories.plugins())
 | |
|             continue
 | |
|         if hasattr(pluginModule, 'test'):
 | |
|             test.suites.append(load(pluginModule.test))
 | |
| 
 | |
|     suite = unittest.TestSuite(test.suites)
 | |
|     runner = unittest.TextTestRunner(verbosity=2)
 | |
|     print('Testing began at %s (pid %s)' % (time.ctime(), os.getpid()))
 | |
|     if options.clean:
 | |
|         shutil.rmtree(conf.supybot.directories.log())
 | |
|         shutil.rmtree(conf.supybot.directories.conf())
 | |
|         shutil.rmtree(conf.supybot.directories.data())
 | |
|     result = runner.run(suite)
 | |
| 
 | |
|     if hasattr(unittest, 'asserts'):
 | |
|         print('Total asserts: %s' % unittest.asserts)
 | |
| 
 | |
|     if result.wasSuccessful():
 | |
|         sys.exit(0)
 | |
|     else:
 | |
|         sys.exit(1)
 | |
| 
 | |
| # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
 | 
