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 = os.path.join(rootdir, getbuilddir()) 178 if options.builddir and os.path.exists(builddir): 179 sys.path.insert(0, builddir) 180 if options.path: 181 path = options.path[:] 182 path.reverse() 183 for p in path: 184 sys.path.insert(0, p) 185 186 187def setup_unittest(options): 188 try: 189 from unittest.runner import _WritelnDecorator 190 except ImportError: 191 from unittest import _WritelnDecorator 192 # 193 writeln_orig = _WritelnDecorator.writeln 194 195 def writeln(self, message=''): 196 try: 197 self.stream.flush() 198 except Exception: 199 pass 200 writeln_orig(self, message) 201 try: 202 self.stream.flush() 203 except Exception: 204 pass 205 206 _WritelnDecorator.writeln = writeln 207 208 209def import_package(options, pkgname): 210 args = [sys.argv[0]] 211 if options.memdebug: 212 args.append('-malloc_debug') 213 args.append('-malloc_dump') 214 if options.summary: 215 args.append('-log_view') 216 package = __import__(pkgname) 217 package.init(args, arch=options.arch) 218 219 220def print_banner(options): 221 r, n = getprocessorinfo() 222 prefix = '[%d@%s]' % (r, n) 223 224 def writeln(message='', endl='\n'): 225 if message is None: 226 return 227 from petsc4py.PETSc import Sys 228 229 message = f'{prefix} {message}' 230 Sys.syncPrint(message, endl=endl, flush=True) 231 232 if options.verbose: 233 writeln(getpythoninfo()) 234 writeln(getpackageinfo('numpy')) 235 for entry in components: 236 writeln(getlibraryinfo(entry)) 237 writeln(getpackageinfo('%s4py' % entry.lower())) 238 239 240def load_tests(options, args): 241 from glob import glob 242 import re 243 244 testsuitedir = os.path.dirname(__file__) 245 sys.path.insert(0, testsuitedir) 246 pattern = 'test_*.py' 247 wildcard = os.path.join(testsuitedir, pattern) 248 testfiles = glob(wildcard) 249 testfiles.sort() 250 testsuite = unittest.TestSuite() 251 testloader = unittest.TestLoader() 252 if options.patterns: 253 testloader.testNamePatterns = [ # novermin 254 ('*%s*' % p) if ('*' not in p) else p for p in options.patterns 255 ] 256 include = exclude = None 257 if options.include: 258 include = re.compile('|'.join(options.include)).search 259 if options.exclude: 260 exclude = re.compile('|'.join(options.exclude)).search 261 for testfile in testfiles: 262 filename = os.path.basename(testfile) 263 testname = os.path.splitext(filename)[0] 264 if (exclude and exclude(testname)) or (include and not include(testname)): 265 continue 266 module = __import__(testname) 267 for arg in args: 268 try: 269 cases = testloader.loadTestsFromNames((arg,), module) 270 testsuite.addTests(cases) 271 except AttributeError: 272 pass 273 if not args: 274 cases = testloader.loadTestsFromModule(module) 275 testsuite.addTests(cases) 276 return testsuite 277 278 279def run_tests(options, testsuite, runner=None): 280 if runner is None: 281 runner = unittest.TextTestRunner(verbosity=options.verbose) 282 runner.failfast = options.failfast 283 result = runner.run(testsuite) 284 return result.wasSuccessful() 285 286 287def abort(code=1): 288 os.abort() 289 290 291def shutdown(success): 292 pass 293 294 295def main(args=None): 296 pkgname = '%s4py' % components[-1].lower() 297 parser = getoptionparser() 298 (options, args) = parser.parse_args(args) 299 setup_python(options) 300 setup_unittest(options) 301 import_package(options, pkgname) 302 print_banner(options) 303 testsuite = load_tests(options, args) 304 success = run_tests(options, testsuite) 305 if not success and options.failfast: 306 abort() 307 shutdown(success) 308 return not success 309 310 311if __name__ == '__main__': 312 import sys 313 314 sys.dont_write_bytecode = True 315 sys.exit(main()) 316