1fb83dddaSLisandro Dalcin# Author: Lisandro Dalcin 2fb83dddaSLisandro Dalcin# Contact: dalcinl@gmail.com 3fb83dddaSLisandro Dalcinimport os 4fb83dddaSLisandro Dalcinimport sys 55808f684SSatish Balayimport optparse 65808f684SSatish Balayimport unittest 75808f684SSatish Balay 8fb83dddaSLisandro Dalcin__unittest = True 9fb83dddaSLisandro Dalcin 10f46a955bSLisandro Dalcincomponents = [ 11f46a955bSLisandro Dalcin 'PETSc', 12f46a955bSLisandro Dalcin] 13f46a955bSLisandro Dalcin 14fb83dddaSLisandro Dalcin 155808f684SSatish Balaydef getoptionparser(): 165808f684SSatish Balay parser = optparse.OptionParser() 175808f684SSatish Balay 18*6f336411SStefano Zampini parser.add_option( 19*6f336411SStefano Zampini '-q', 20*6f336411SStefano Zampini '--quiet', 21*6f336411SStefano Zampini action='store_const', 22*6f336411SStefano Zampini const=0, 23*6f336411SStefano Zampini dest='verbose', 24*6f336411SStefano Zampini default=1, 25*6f336411SStefano Zampini help='do not print status messages to stdout', 26*6f336411SStefano Zampini ) 27*6f336411SStefano Zampini parser.add_option( 28*6f336411SStefano Zampini '-v', 29*6f336411SStefano Zampini '--verbose', 30*6f336411SStefano Zampini action='store_const', 31*6f336411SStefano Zampini const=2, 32*6f336411SStefano Zampini dest='verbose', 33*6f336411SStefano Zampini default=1, 34*6f336411SStefano Zampini help='print status messages to stdout', 35*6f336411SStefano Zampini ) 36*6f336411SStefano Zampini parser.add_option( 37*6f336411SStefano Zampini '-i', 38*6f336411SStefano Zampini '--include', 39*6f336411SStefano Zampini type='string', 40*6f336411SStefano Zampini action='append', 41*6f336411SStefano Zampini dest='include', 42*6f336411SStefano Zampini default=[], 43*6f336411SStefano Zampini help='include tests matching PATTERN', 44*6f336411SStefano Zampini metavar='PATTERN', 45*6f336411SStefano Zampini ) 46*6f336411SStefano Zampini parser.add_option( 47*6f336411SStefano Zampini '-e', 48*6f336411SStefano Zampini '--exclude', 49*6f336411SStefano Zampini type='string', 50*6f336411SStefano Zampini action='append', 51*6f336411SStefano Zampini dest='exclude', 52*6f336411SStefano Zampini default=[], 53*6f336411SStefano Zampini help='exclude tests matching PATTERN', 54*6f336411SStefano Zampini metavar='PATTERN', 55*6f336411SStefano Zampini ) 56*6f336411SStefano Zampini parser.add_option( 57*6f336411SStefano Zampini '-k', 58*6f336411SStefano Zampini '--pattern', 59*6f336411SStefano Zampini type='string', 60*6f336411SStefano Zampini action='append', 61*6f336411SStefano Zampini dest='patterns', 62*6f336411SStefano Zampini default=[], 63*6f336411SStefano Zampini help='only run tests which match the given substring', 64*6f336411SStefano Zampini ) 65*6f336411SStefano Zampini parser.add_option( 66*6f336411SStefano Zampini '-f', 67*6f336411SStefano Zampini '--failfast', 68*6f336411SStefano Zampini action='store_true', 69*6f336411SStefano Zampini dest='failfast', 70*6f336411SStefano Zampini default=False, 71*6f336411SStefano Zampini help='Stop on first failure', 72*6f336411SStefano Zampini ) 73*6f336411SStefano Zampini parser.add_option( 74*6f336411SStefano Zampini '--no-builddir', 75*6f336411SStefano Zampini action='store_false', 76*6f336411SStefano Zampini dest='builddir', 77*6f336411SStefano Zampini default=True, 78*6f336411SStefano Zampini help='disable testing from build directory', 79*6f336411SStefano Zampini ) 80*6f336411SStefano Zampini parser.add_option( 81*6f336411SStefano Zampini '--path', 82*6f336411SStefano Zampini type='string', 83*6f336411SStefano Zampini action='append', 84*6f336411SStefano Zampini dest='path', 85*6f336411SStefano Zampini default=[], 86*6f336411SStefano Zampini help='prepend PATH to sys.path', 87*6f336411SStefano Zampini metavar='PATH', 88*6f336411SStefano Zampini ) 89*6f336411SStefano Zampini parser.add_option( 90*6f336411SStefano Zampini '--arch', 91*6f336411SStefano Zampini type='string', 92*6f336411SStefano Zampini action='store', 93*6f336411SStefano Zampini dest='arch', 94*6f336411SStefano Zampini default=None, 95*6f336411SStefano Zampini help='use PETSC_ARCH', 96*6f336411SStefano Zampini metavar='PETSC_ARCH', 97*6f336411SStefano Zampini ) 98*6f336411SStefano Zampini parser.add_option( 99*6f336411SStefano Zampini '-s', 100*6f336411SStefano Zampini '--summary', 101*6f336411SStefano Zampini action='store_true', 102*6f336411SStefano Zampini dest='summary', 103*6f336411SStefano Zampini default=0, 104*6f336411SStefano Zampini help='print PETSc log summary', 105*6f336411SStefano Zampini ) 106*6f336411SStefano Zampini parser.add_option( 107*6f336411SStefano Zampini '--no-memdebug', 108*6f336411SStefano Zampini action='store_false', 109*6f336411SStefano Zampini dest='memdebug', 110*6f336411SStefano Zampini default=True, 111*6f336411SStefano Zampini help='Do not use PETSc memory debugging', 112*6f336411SStefano Zampini ) 1135808f684SSatish Balay return parser 1145808f684SSatish Balay 115fb83dddaSLisandro Dalcin 1165808f684SSatish Balaydef getbuilddir(): 117fb83dddaSLisandro Dalcin try: 118fb83dddaSLisandro Dalcin try: 119fb83dddaSLisandro Dalcin from setuptools.dist import Distribution 120fb83dddaSLisandro Dalcin except ImportError: 121fb83dddaSLisandro Dalcin from distutils.dist import Distribution 122fb83dddaSLisandro Dalcin try: 123fb83dddaSLisandro Dalcin from setuptools.command.build import build 124fb83dddaSLisandro Dalcin except ImportError: 125fb83dddaSLisandro Dalcin from distutils.command.build import build 126fb83dddaSLisandro Dalcin cmd_obj = build(Distribution()) 127fb83dddaSLisandro Dalcin cmd_obj.finalize_options() 128fb83dddaSLisandro Dalcin return cmd_obj.build_platlib 129fb83dddaSLisandro Dalcin except Exception: 130fb83dddaSLisandro Dalcin return None 131fb83dddaSLisandro Dalcin 132fb83dddaSLisandro Dalcin 133fb83dddaSLisandro Dalcindef getprocessorinfo(): 134fb83dddaSLisandro Dalcin try: 135fb83dddaSLisandro Dalcin name = os.uname()[1] 136*6f336411SStefano Zampini except Exception: 137fb83dddaSLisandro Dalcin import platform 138*6f336411SStefano Zampini 139fb83dddaSLisandro Dalcin name = platform.uname()[1] 140fb83dddaSLisandro Dalcin from petsc4py.PETSc import COMM_WORLD 141*6f336411SStefano Zampini 142fb83dddaSLisandro Dalcin rank = COMM_WORLD.getRank() 143fb83dddaSLisandro Dalcin return (rank, name) 144fb83dddaSLisandro Dalcin 145fb83dddaSLisandro Dalcin 146f46a955bSLisandro Dalcindef getlibraryinfo(name): 147*6f336411SStefano Zampini modname = f'{name.lower()}4py.{name}' 148f46a955bSLisandro Dalcin module = __import__(modname, fromlist=[name]) 149f46a955bSLisandro Dalcin (major, minor, micro), devel = module.Sys.getVersion(devel=True) 150f46a955bSLisandro Dalcin r = not devel 151*6f336411SStefano Zampini if r: 152*6f336411SStefano Zampini release = 'release' 153*6f336411SStefano Zampini else: 154*6f336411SStefano Zampini release = 'development' 155f46a955bSLisandro Dalcin arch = module.__arch__ 156*6f336411SStefano Zampini return "%s %d.%d.%d %s (conf: '%s')" % (name, major, minor, micro, release, arch) 157fb83dddaSLisandro Dalcin 158fb83dddaSLisandro Dalcin 159fb83dddaSLisandro Dalcindef getpythoninfo(): 160fb83dddaSLisandro Dalcin x, y, z = sys.version_info[:3] 161*6f336411SStefano Zampini return 'Python %d.%d.%d (%s)' % (x, y, z, sys.executable) 162fb83dddaSLisandro Dalcin 163fb83dddaSLisandro Dalcin 164fb83dddaSLisandro Dalcindef getpackageinfo(pkg): 165fb83dddaSLisandro Dalcin try: 166fb83dddaSLisandro Dalcin pkg = __import__(pkg) 167fb83dddaSLisandro Dalcin except ImportError: 168fb83dddaSLisandro Dalcin return None 169fb83dddaSLisandro Dalcin name = pkg.__name__ 170fb83dddaSLisandro Dalcin version = pkg.__version__ 171fb83dddaSLisandro Dalcin path = pkg.__path__[0] 172*6f336411SStefano Zampini return f'{name} {version} ({path})' 173fb83dddaSLisandro Dalcin 1745808f684SSatish Balay 1755808f684SSatish Balaydef setup_python(options): 1765808f684SSatish Balay rootdir = os.path.dirname(os.path.dirname(__file__)) 1775808f684SSatish Balay builddir = os.path.join(rootdir, getbuilddir()) 1785808f684SSatish Balay if options.builddir and os.path.exists(builddir): 1795808f684SSatish Balay sys.path.insert(0, builddir) 1805808f684SSatish Balay if options.path: 1815808f684SSatish Balay path = options.path[:] 1825808f684SSatish Balay path.reverse() 1835808f684SSatish Balay for p in path: 1845808f684SSatish Balay sys.path.insert(0, p) 1855808f684SSatish Balay 186fb83dddaSLisandro Dalcin 1875808f684SSatish Balaydef setup_unittest(options): 1885808f684SSatish Balay try: 1895808f684SSatish Balay from unittest.runner import _WritelnDecorator 1905808f684SSatish Balay except ImportError: 1915808f684SSatish Balay from unittest import _WritelnDecorator 1925808f684SSatish Balay # 1935808f684SSatish Balay writeln_orig = _WritelnDecorator.writeln 194*6f336411SStefano Zampini 1955808f684SSatish Balay def writeln(self, message=''): 196*6f336411SStefano Zampini try: 197*6f336411SStefano Zampini self.stream.flush() 198*6f336411SStefano Zampini except Exception: 199*6f336411SStefano Zampini pass 2005808f684SSatish Balay writeln_orig(self, message) 201*6f336411SStefano Zampini try: 202*6f336411SStefano Zampini self.stream.flush() 203*6f336411SStefano Zampini except Exception: 204*6f336411SStefano Zampini pass 205*6f336411SStefano Zampini 2065808f684SSatish Balay _WritelnDecorator.writeln = writeln 2075808f684SSatish Balay 208fb83dddaSLisandro Dalcin 2095808f684SSatish Balaydef import_package(options, pkgname): 210b254a87dSStefano Zampini args = [sys.argv[0]] 211b254a87dSStefano Zampini if options.memdebug: 212b254a87dSStefano Zampini args.append('-malloc_debug') 213b254a87dSStefano Zampini args.append('-malloc_dump') 2145808f684SSatish Balay if options.summary: 2155808f684SSatish Balay args.append('-log_view') 2165808f684SSatish Balay package = __import__(pkgname) 2175808f684SSatish Balay package.init(args, arch=options.arch) 2185808f684SSatish Balay 2195808f684SSatish Balay 220fb83dddaSLisandro Dalcindef print_banner(options): 221fb83dddaSLisandro Dalcin r, n = getprocessorinfo() 222*6f336411SStefano Zampini prefix = '[%d@%s]' % (r, n) 2235808f684SSatish Balay 2245808f684SSatish Balay def writeln(message='', endl='\n'): 225fb83dddaSLisandro Dalcin if message is None: 226fb83dddaSLisandro Dalcin return 2275808f684SSatish Balay from petsc4py.PETSc import Sys 228*6f336411SStefano Zampini 229*6f336411SStefano Zampini message = f'{prefix} {message}' 2305808f684SSatish Balay Sys.syncPrint(message, endl=endl, flush=True) 2315808f684SSatish Balay 2325808f684SSatish Balay if options.verbose: 233fb83dddaSLisandro Dalcin writeln(getpythoninfo()) 234fb83dddaSLisandro Dalcin writeln(getpackageinfo('numpy')) 235f46a955bSLisandro Dalcin for entry in components: 236f46a955bSLisandro Dalcin writeln(getlibraryinfo(entry)) 237e405789aSLisandro Dalcin writeln(getpackageinfo('%s4py' % entry.lower())) 238fb83dddaSLisandro Dalcin 2395808f684SSatish Balay 2405808f684SSatish Balaydef load_tests(options, args): 2415808f684SSatish Balay from glob import glob 2425808f684SSatish Balay import re 243*6f336411SStefano Zampini 2445808f684SSatish Balay testsuitedir = os.path.dirname(__file__) 2455808f684SSatish Balay sys.path.insert(0, testsuitedir) 2465808f684SSatish Balay pattern = 'test_*.py' 2475808f684SSatish Balay wildcard = os.path.join(testsuitedir, pattern) 2485808f684SSatish Balay testfiles = glob(wildcard) 2495808f684SSatish Balay testfiles.sort() 2505808f684SSatish Balay testsuite = unittest.TestSuite() 2515808f684SSatish Balay testloader = unittest.TestLoader() 2521e51fb16SStefano Zampini if options.patterns: 2531e51fb16SStefano Zampini testloader.testNamePatterns = [ 254*6f336411SStefano Zampini ('*%s*' % p) if ('*' not in p) else p for p in options.patterns 255f46a955bSLisandro Dalcin ] 2565808f684SSatish Balay include = exclude = None 2575808f684SSatish Balay if options.include: 2585808f684SSatish Balay include = re.compile('|'.join(options.include)).search 2595808f684SSatish Balay if options.exclude: 2605808f684SSatish Balay exclude = re.compile('|'.join(options.exclude)).search 2615808f684SSatish Balay for testfile in testfiles: 2625808f684SSatish Balay filename = os.path.basename(testfile) 2635808f684SSatish Balay testname = os.path.splitext(filename)[0] 264*6f336411SStefano Zampini if (exclude and exclude(testname)) or (include and not include(testname)): 2655808f684SSatish Balay continue 2665808f684SSatish Balay module = __import__(testname) 2675808f684SSatish Balay for arg in args: 2685808f684SSatish Balay try: 2695808f684SSatish Balay cases = testloader.loadTestsFromNames((arg,), module) 2705808f684SSatish Balay testsuite.addTests(cases) 2715808f684SSatish Balay except AttributeError: 2725808f684SSatish Balay pass 2735808f684SSatish Balay if not args: 2745808f684SSatish Balay cases = testloader.loadTestsFromModule(module) 2755808f684SSatish Balay testsuite.addTests(cases) 2765808f684SSatish Balay return testsuite 2775808f684SSatish Balay 278fb83dddaSLisandro Dalcin 2795808f684SSatish Balaydef run_tests(options, testsuite, runner=None): 2805808f684SSatish Balay if runner is None: 2815808f684SSatish Balay runner = unittest.TextTestRunner(verbosity=options.verbose) 2825808f684SSatish Balay runner.failfast = options.failfast 2835808f684SSatish Balay result = runner.run(testsuite) 2845808f684SSatish Balay return result.wasSuccessful() 2855808f684SSatish Balay 286fb83dddaSLisandro Dalcin 2875808f684SSatish Balaydef abort(code=1): 2885808f684SSatish Balay os.abort() 2895808f684SSatish Balay 290fb83dddaSLisandro Dalcin 2915808f684SSatish Balaydef shutdown(success): 2925808f684SSatish Balay pass 2935808f684SSatish Balay 294fb83dddaSLisandro Dalcin 2955808f684SSatish Balaydef main(args=None): 296f46a955bSLisandro Dalcin pkgname = '%s4py' % components[-1].lower() 2975808f684SSatish Balay parser = getoptionparser() 2985808f684SSatish Balay (options, args) = parser.parse_args(args) 2995808f684SSatish Balay setup_python(options) 3005808f684SSatish Balay setup_unittest(options) 301fb83dddaSLisandro Dalcin import_package(options, pkgname) 302fb83dddaSLisandro Dalcin print_banner(options) 3035808f684SSatish Balay testsuite = load_tests(options, args) 3045808f684SSatish Balay success = run_tests(options, testsuite) 305*6f336411SStefano Zampini if not success and options.failfast: 306*6f336411SStefano Zampini abort() 3075808f684SSatish Balay shutdown(success) 3085808f684SSatish Balay return not success 3095808f684SSatish Balay 310fb83dddaSLisandro Dalcin 3115808f684SSatish Balayif __name__ == '__main__': 3125808f684SSatish Balay import sys 313*6f336411SStefano Zampini 3145808f684SSatish Balay sys.dont_write_bytecode = True 3155808f684SSatish Balay sys.exit(main()) 316