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