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 return parser 44 45def getbuilddir(): 46 from distutils.util import get_platform 47 s = os.path.join("build", "lib.%s-%.3s" % (get_platform(), sys.version)) 48 if hasattr(sys, 'gettotalrefcount'): s += '-pydebug' 49 return s 50 51def setup_python(options): 52 rootdir = os.path.dirname(os.path.dirname(__file__)) 53 builddir = os.path.join(rootdir, getbuilddir()) 54 if options.builddir and os.path.exists(builddir): 55 sys.path.insert(0, builddir) 56 if options.path: 57 path = options.path[:] 58 path.reverse() 59 for p in path: 60 sys.path.insert(0, p) 61 62def setup_unittest(options): 63 from unittest import TestSuite 64 try: 65 from unittest.runner import _WritelnDecorator 66 except ImportError: 67 from unittest import _WritelnDecorator 68 # 69 writeln_orig = _WritelnDecorator.writeln 70 def writeln(self, message=''): 71 try: self.stream.flush() 72 except: pass 73 writeln_orig(self, message) 74 try: self.stream.flush() 75 except: pass 76 _WritelnDecorator.writeln = writeln 77 78def import_package(options, pkgname): 79 args = [ 80 sys.argv[0], 81 '-malloc', 82 '-malloc_debug', 83 '-malloc_dump', 84 ] 85 if options.summary: 86 args.append('-log_view') 87 package = __import__(pkgname) 88 package.init(args, arch=options.arch) 89 return package 90 91def getprocessorinfo(): 92 try: 93 name = os.uname()[1] 94 except: 95 import platform 96 name = platform.uname()[1] 97 from petsc4py.PETSc import COMM_WORLD 98 rank = COMM_WORLD.getRank() 99 return (rank, name) 100 101def getlibraryinfo(): 102 from petsc4py import PETSc 103 (major, minor, micro) = PETSc.Sys.getVersion() 104 r = PETSc.Sys.getVersionInfo()['release'] 105 if r: release = 'release' 106 else: release = 'development' 107 arch = PETSc.__arch__ 108 return ("PETSc %d.%d.%d %s (conf: '%s')" 109 % (major, minor, micro, release, arch) ) 110 111def getpythoninfo(): 112 x, y = sys.version_info[:2] 113 return ("Python %d.%d (%s)" % (x, y, sys.executable)) 114 115def getpackageinfo(pkg): 116 return ("%s %s (%s)" % (pkg.__name__, 117 pkg.__version__, 118 pkg.__path__[0])) 119 120def writeln(message='', endl='\n'): 121 from petsc4py.PETSc import Sys 122 Sys.syncPrint(message, endl=endl, flush=True) 123 124def print_banner(options, package): 125 r, n = getprocessorinfo() 126 fmt = "[%d@%s] %s" 127 if options.verbose: 128 writeln(fmt % (r, n, getpythoninfo())) 129 writeln(fmt % (r, n, getlibraryinfo())) 130 writeln(fmt % (r, n, getpackageinfo(package))) 131 132def load_tests(options, args): 133 from glob import glob 134 import re 135 testsuitedir = os.path.dirname(__file__) 136 sys.path.insert(0, testsuitedir) 137 pattern = 'test_*.py' 138 wildcard = os.path.join(testsuitedir, pattern) 139 testfiles = glob(wildcard) 140 testfiles.sort() 141 testsuite = unittest.TestSuite() 142 testloader = unittest.TestLoader() 143 if options.patterns: 144 testloader.testNamePatterns = [ 145 ('*%s*' % p) if ('*' not in p) else p 146 for p in options.patterns] 147 include = exclude = None 148 if options.include: 149 include = re.compile('|'.join(options.include)).search 150 if options.exclude: 151 exclude = re.compile('|'.join(options.exclude)).search 152 for testfile in testfiles: 153 filename = os.path.basename(testfile) 154 testname = os.path.splitext(filename)[0] 155 if ((exclude and exclude(testname)) or 156 (include and not include(testname))): 157 continue 158 module = __import__(testname) 159 for arg in args: 160 try: 161 cases = testloader.loadTestsFromNames((arg,), module) 162 testsuite.addTests(cases) 163 except AttributeError: 164 pass 165 if not args: 166 cases = testloader.loadTestsFromModule(module) 167 testsuite.addTests(cases) 168 return testsuite 169 170def run_tests(options, testsuite, runner=None): 171 if runner is None: 172 runner = unittest.TextTestRunner(verbosity=options.verbose) 173 runner.failfast = options.failfast 174 result = runner.run(testsuite) 175 return result.wasSuccessful() 176 177def test_refleaks(options, args): 178 from sys import gettotalrefcount 179 from gc import collect 180 from copy import deepcopy 181 testsuite = load_tests(options, args) 182 class EmptyIO(object): 183 def write(self, *args): 184 pass 185 runner = unittest.TextTestRunner(stream=EmptyIO(), verbosity=0) 186 rank, name = getprocessorinfo() 187 r1 = r2 = 0 188 repeats = options.repeats 189 while repeats: 190 collect() 191 r1 = gettotalrefcount() 192 run_tests(options, deepcopy(testsuite), runner) 193 collect() 194 r2 = gettotalrefcount() 195 leaks = r2-r1 196 if leaks and repeats < options.repeats: 197 writeln('[%d@%s] refleaks: (%d - %d) --> %d' 198 % (rank, name, r2, r1, leaks)) 199 repeats -= 1 200 201def abort(code=1): 202 os.abort() 203 204def shutdown(success): 205 pass 206 207def main(args=None): 208 pkgname = 'petsc4py' 209 parser = getoptionparser() 210 (options, args) = parser.parse_args(args) 211 setup_python(options) 212 setup_unittest(options) 213 package = import_package(options, pkgname) 214 print_banner(options, package) 215 testsuite = load_tests(options, args) 216 success = run_tests(options, testsuite) 217 if not success and options.failfast: abort() 218 if success and hasattr(sys, 'gettotalrefcount'): 219 test_refleaks(options, args) 220 shutdown(success) 221 return not success 222 223if __name__ == '__main__': 224 import sys 225 sys.dont_write_bytecode = True 226 sys.exit(main()) 227