1import sys, os 2import optparse 3import unittest 4 5def getoptionparser(): 6 parser = optparse.OptionParser() 7 8 parser.add_option("-q", "--quiet", 9 action="store_const", const=0, dest="verbose", default=1, 10 help="do not print status messages to stdout") 11 parser.add_option("-v", "--verbose", 12 action="store_const", const=2, dest="verbose", default=1, 13 help="print status messages to stdout") 14 parser.add_option("-i", "--include", type="string", 15 action="append", dest="include", default=[], 16 help="include tests matching PATTERN", metavar="PATTERN") 17 parser.add_option("-e", "--exclude", type="string", 18 action="append", dest="exclude", default=[], 19 help="exclude tests matching PATTERN", metavar="PATTERN") 20 parser.add_option("-k", "--pattern", type="string", 21 action="append", dest="patterns", default=[], 22 help="only run tests which match the given substring") 23 parser.add_option("-f", "--failfast", 24 action="store_true", dest="failfast", default=False, 25 help="Stop on first failure") 26 parser.add_option("--no-builddir", 27 action="store_false", dest="builddir", default=True, 28 help="disable testing from build directory") 29 parser.add_option("--path", type="string", 30 action="append", dest="path", default=[], 31 help="prepend PATH to sys.path", metavar="PATH") 32 parser.add_option("--refleaks", type="int", 33 action="store", dest="repeats", default=3, 34 help="run tests REPEAT times in a loop to catch leaks", 35 metavar="REPEAT") 36 parser.add_option("--arch", type="string", 37 action="store", dest="arch", default=None, 38 help="use PETSC_ARCH", 39 metavar="PETSC_ARCH") 40 parser.add_option("-s","--summary", 41 action="store_true", dest="summary", default=0, 42 help="print PETSc log summary") 43 parser.add_option("--no-memdebug", 44 action="store_false", dest="memdebug", default=True, 45 help="Do not use PETSc memory debugging") 46 return parser 47 48def getbuilddir(): 49 from distutils.util import get_platform 50 s = os.path.join("build", "lib.%s-%.3s" % (get_platform(), sys.version)) 51 if hasattr(sys, 'gettotalrefcount'): s += '-pydebug' 52 return s 53 54def setup_python(options): 55 rootdir = os.path.dirname(os.path.dirname(__file__)) 56 builddir = os.path.join(rootdir, getbuilddir()) 57 if options.builddir and os.path.exists(builddir): 58 sys.path.insert(0, builddir) 59 if options.path: 60 path = options.path[:] 61 path.reverse() 62 for p in path: 63 sys.path.insert(0, p) 64 65def setup_unittest(options): 66 from unittest import TestSuite 67 try: 68 from unittest.runner import _WritelnDecorator 69 except ImportError: 70 from unittest import _WritelnDecorator 71 # 72 writeln_orig = _WritelnDecorator.writeln 73 def writeln(self, message=''): 74 try: self.stream.flush() 75 except: pass 76 writeln_orig(self, message) 77 try: self.stream.flush() 78 except: pass 79 _WritelnDecorator.writeln = writeln 80 81def import_package(options, pkgname): 82 args = [ sys.argv[0] ] 83 if options.memdebug: 84 args.append('-malloc') 85 args.append('-malloc_debug') 86 args.append('-malloc_dump') 87 if options.summary: 88 args.append('-log_view') 89 package = __import__(pkgname) 90 package.init(args, arch=options.arch) 91 return package 92 93def getprocessorinfo(): 94 try: 95 name = os.uname()[1] 96 except: 97 import platform 98 name = platform.uname()[1] 99 from petsc4py.PETSc import COMM_WORLD 100 rank = COMM_WORLD.getRank() 101 return (rank, name) 102 103def getlibraryinfo(): 104 from petsc4py import PETSc 105 (major, minor, micro) = PETSc.Sys.getVersion() 106 r = PETSc.Sys.getVersionInfo()['release'] 107 if r: release = 'release' 108 else: release = 'development' 109 arch = PETSc.__arch__ 110 return ("PETSc %d.%d.%d %s (conf: '%s')" 111 % (major, minor, micro, release, arch) ) 112 113def getpythoninfo(): 114 x, y = sys.version_info[:2] 115 return ("Python %d.%d (%s)" % (x, y, sys.executable)) 116 117def getpackageinfo(pkg): 118 return ("%s %s (%s)" % (pkg.__name__, 119 pkg.__version__, 120 pkg.__path__[0])) 121 122def writeln(message='', endl='\n'): 123 from petsc4py.PETSc import Sys 124 Sys.syncPrint(message, endl=endl, flush=True) 125 126def print_banner(options, package): 127 r, n = getprocessorinfo() 128 fmt = "[%d@%s] %s" 129 if options.verbose: 130 writeln(fmt % (r, n, getpythoninfo())) 131 writeln(fmt % (r, n, getlibraryinfo())) 132 writeln(fmt % (r, n, getpackageinfo(package))) 133 134def load_tests(options, args): 135 from glob import glob 136 import re 137 testsuitedir = os.path.dirname(__file__) 138 sys.path.insert(0, testsuitedir) 139 pattern = 'test_*.py' 140 wildcard = os.path.join(testsuitedir, pattern) 141 testfiles = glob(wildcard) 142 testfiles.sort() 143 testsuite = unittest.TestSuite() 144 testloader = unittest.TestLoader() 145 if options.patterns: 146 testloader.testNamePatterns = [ 147 ('*%s*' % p) if ('*' not in p) else p 148 for p in options.patterns] 149 include = exclude = None 150 if options.include: 151 include = re.compile('|'.join(options.include)).search 152 if options.exclude: 153 exclude = re.compile('|'.join(options.exclude)).search 154 for testfile in testfiles: 155 filename = os.path.basename(testfile) 156 testname = os.path.splitext(filename)[0] 157 if ((exclude and exclude(testname)) or 158 (include and not include(testname))): 159 continue 160 module = __import__(testname) 161 for arg in args: 162 try: 163 cases = testloader.loadTestsFromNames((arg,), module) 164 testsuite.addTests(cases) 165 except AttributeError: 166 pass 167 if not args: 168 cases = testloader.loadTestsFromModule(module) 169 testsuite.addTests(cases) 170 return testsuite 171 172def run_tests(options, testsuite, runner=None): 173 if runner is None: 174 runner = unittest.TextTestRunner(verbosity=options.verbose) 175 runner.failfast = options.failfast 176 result = runner.run(testsuite) 177 return result.wasSuccessful() 178 179def test_refleaks(options, args): 180 from sys import gettotalrefcount 181 from gc import collect 182 from copy import deepcopy 183 testsuite = load_tests(options, args) 184 class EmptyIO(object): 185 def write(self, *args): 186 pass 187 runner = unittest.TextTestRunner(stream=EmptyIO(), verbosity=0) 188 rank, name = getprocessorinfo() 189 r1 = r2 = 0 190 repeats = options.repeats 191 while repeats: 192 collect() 193 r1 = gettotalrefcount() 194 run_tests(options, deepcopy(testsuite), runner) 195 collect() 196 r2 = gettotalrefcount() 197 leaks = r2-r1 198 if leaks and repeats < options.repeats: 199 writeln('[%d@%s] refleaks: (%d - %d) --> %d' 200 % (rank, name, r2, r1, leaks)) 201 repeats -= 1 202 203def abort(code=1): 204 os.abort() 205 206def shutdown(success): 207 pass 208 209def main(args=None): 210 pkgname = 'petsc4py' 211 parser = getoptionparser() 212 (options, args) = parser.parse_args(args) 213 setup_python(options) 214 setup_unittest(options) 215 package = import_package(options, pkgname) 216 print_banner(options, package) 217 testsuite = load_tests(options, args) 218 success = run_tests(options, testsuite) 219 if not success and options.failfast: abort() 220 if success and hasattr(sys, 'gettotalrefcount'): 221 test_refleaks(options, args) 222 shutdown(success) 223 return not success 224 225if __name__ == '__main__': 226 import sys 227 sys.dont_write_bytecode = True 228 sys.exit(main()) 229