1# Author: Lisandro Dalcin 2# Contact: dalcinl@gmail.com 3import os 4import sys 5import optparse 6import unittest 7 8__unittest = True 9 10components = [ 11 'PETSc', 12] 13 14 15def getoptionparser(): 16 parser = optparse.OptionParser() 17 18 parser.add_option( 19 '-q', 20 '--quiet', 21 action='store_const', 22 const=0, 23 dest='verbose', 24 default=1, 25 help='do not print status messages to stdout', 26 ) 27 parser.add_option( 28 '-v', 29 '--verbose', 30 action='store_const', 31 const=2, 32 dest='verbose', 33 default=1, 34 help='print status messages to stdout', 35 ) 36 parser.add_option( 37 '-i', 38 '--include', 39 type='string', 40 action='append', 41 dest='include', 42 default=[], 43 help='include tests matching PATTERN', 44 metavar='PATTERN', 45 ) 46 parser.add_option( 47 '-e', 48 '--exclude', 49 type='string', 50 action='append', 51 dest='exclude', 52 default=[], 53 help='exclude tests matching PATTERN', 54 metavar='PATTERN', 55 ) 56 parser.add_option( 57 '-k', 58 '--pattern', 59 type='string', 60 action='append', 61 dest='patterns', 62 default=[], 63 help='only run tests which match the given substring', 64 ) 65 parser.add_option( 66 '-f', 67 '--failfast', 68 action='store_true', 69 dest='failfast', 70 default=False, 71 help='Stop on first failure', 72 ) 73 parser.add_option( 74 '--no-builddir', 75 action='store_false', 76 dest='builddir', 77 default=True, 78 help='disable testing from build directory', 79 ) 80 parser.add_option( 81 '--path', 82 type='string', 83 action='append', 84 dest='path', 85 default=[], 86 help='prepend PATH to sys.path', 87 metavar='PATH', 88 ) 89 parser.add_option( 90 '--arch', 91 type='string', 92 action='store', 93 dest='arch', 94 default=None, 95 help='use PETSC_ARCH', 96 metavar='PETSC_ARCH', 97 ) 98 parser.add_option( 99 '-s', 100 '--summary', 101 action='store_true', 102 dest='summary', 103 default=0, 104 help='print PETSc log summary', 105 ) 106 parser.add_option( 107 '--no-memdebug', 108 action='store_false', 109 dest='memdebug', 110 default=True, 111 help='Do not use PETSc memory debugging', 112 ) 113 return parser 114 115 116def getbuilddir(): 117 try: 118 try: 119 from setuptools.dist import Distribution 120 except ImportError: 121 from distutils.dist import Distribution 122 try: 123 from setuptools.command.build import build 124 except ImportError: 125 from distutils.command.build import build 126 cmd_obj = build(Distribution()) 127 cmd_obj.finalize_options() 128 return cmd_obj.build_platlib 129 except Exception: 130 return None 131 132 133def getprocessorinfo(): 134 try: 135 name = os.uname()[1] 136 except Exception: 137 import platform 138 139 name = platform.uname()[1] 140 from petsc4py.PETSc import COMM_WORLD 141 142 rank = COMM_WORLD.getRank() 143 return (rank, name) 144 145 146def getlibraryinfo(name): 147 modname = f'{name.lower()}4py.{name}' 148 module = __import__(modname, fromlist=[name]) 149 (major, minor, micro), devel = module.Sys.getVersion(devel=True) 150 r = not devel 151 if r: 152 release = 'release' 153 else: 154 release = 'development' 155 arch = module.__arch__ 156 return "%s %d.%d.%d %s (conf: '%s')" % (name, major, minor, micro, release, arch) 157 158 159def getpythoninfo(): 160 x, y, z = sys.version_info[:3] 161 return 'Python %d.%d.%d (%s)' % (x, y, z, sys.executable) 162 163 164def getpackageinfo(pkg): 165 try: 166 pkg = __import__(pkg) 167 except ImportError: 168 return None 169 name = pkg.__name__ 170 version = pkg.__version__ 171 path = pkg.__path__[0] 172 return f'{name} {version} ({path})' 173 174 175def setup_python(options): 176 rootdir = os.path.dirname(os.path.dirname(__file__)) 177 builddir = getbuilddir() 178 if builddir is not None: 179 builddir = os.path.join(rootdir, builddir) 180 if options.builddir and builddir is not None and os.path.exists(builddir): 181 sys.path.insert(0, builddir) 182 if options.path: 183 path = options.path[:] 184 path.reverse() 185 for p in path: 186 sys.path.insert(0, p) 187 188 189def setup_unittest(options): 190 try: 191 from unittest.runner import _WritelnDecorator 192 except ImportError: 193 from unittest import _WritelnDecorator 194 # 195 writeln_orig = _WritelnDecorator.writeln 196 197 def writeln(self, message=''): 198 try: 199 self.stream.flush() 200 except Exception: 201 pass 202 writeln_orig(self, message) 203 try: 204 self.stream.flush() 205 except Exception: 206 pass 207 208 _WritelnDecorator.writeln = writeln 209 210 211def import_package(options, pkgname): 212 args = [sys.argv[0]] 213 if options.memdebug: 214 args.append('-malloc_debug') 215 args.append('-malloc_dump') 216 if options.summary: 217 args.append('-log_view') 218 package = __import__(pkgname) 219 package.init(args, arch=options.arch) 220 221 222def print_banner(options): 223 r, n = getprocessorinfo() 224 prefix = '[%d@%s]' % (r, n) 225 226 def writeln(message='', endl='\n'): 227 if message is None: 228 return 229 from petsc4py.PETSc import Sys 230 231 message = f'{prefix} {message}' 232 Sys.syncPrint(message, endl=endl, flush=True) 233 234 if options.verbose: 235 writeln(getpythoninfo()) 236 writeln(getpackageinfo('numpy')) 237 for entry in components: 238 writeln(getlibraryinfo(entry)) 239 writeln(getpackageinfo('%s4py' % entry.lower())) 240 241 242def load_tests(options, args): 243 from glob import glob 244 import re 245 246 testsuitedir = os.path.dirname(__file__) 247 sys.path.insert(0, testsuitedir) 248 pattern = 'test_*.py' 249 wildcard = os.path.join(testsuitedir, pattern) 250 testfiles = glob(wildcard) 251 testfiles.sort() 252 testsuite = unittest.TestSuite() 253 testloader = unittest.TestLoader() 254 if options.patterns: 255 testloader.testNamePatterns = [ # novermin 256 ('*%s*' % p) if ('*' not in p) else p for p in options.patterns 257 ] 258 include = exclude = None 259 if options.include: 260 include = re.compile('|'.join(options.include)).search 261 if options.exclude: 262 exclude = re.compile('|'.join(options.exclude)).search 263 for testfile in testfiles: 264 filename = os.path.basename(testfile) 265 testname = os.path.splitext(filename)[0] 266 if (exclude and exclude(testname)) or (include and not include(testname)): 267 continue 268 module = __import__(testname) 269 for arg in args: 270 try: 271 cases = testloader.loadTestsFromNames((arg,), module) 272 testsuite.addTests(cases) 273 except AttributeError: 274 pass 275 if not args: 276 cases = testloader.loadTestsFromModule(module) 277 testsuite.addTests(cases) 278 return testsuite 279 280 281def run_tests(options, testsuite, runner=None): 282 if runner is None: 283 runner = unittest.TextTestRunner(verbosity=options.verbose) 284 runner.failfast = options.failfast 285 result = runner.run(testsuite) 286 return result.wasSuccessful() 287 288 289def abort(code=1): 290 os.abort() 291 292 293def shutdown(success): 294 pass 295 296 297def main(args=None): 298 pkgname = '%s4py' % components[-1].lower() 299 parser = getoptionparser() 300 (options, args) = parser.parse_args(args) 301 setup_python(options) 302 setup_unittest(options) 303 import_package(options, pkgname) 304 print_banner(options) 305 testsuite = load_tests(options, args) 306 success = run_tests(options, testsuite) 307 if not success and options.failfast: 308 abort() 309 shutdown(success) 310 return not success 311 312 313if __name__ == '__main__': 314 import sys 315 316 sys.dont_write_bytecode = True 317 sys.exit(main()) 318