xref: /petsc/src/binding/petsc4py/test/runtests.py (revision a47f5240f9a566ca3f90453fc02858db57a93a4e)
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
186f336411SStefano Zampini    parser.add_option(
196f336411SStefano Zampini        '-q',
206f336411SStefano Zampini        '--quiet',
216f336411SStefano Zampini        action='store_const',
226f336411SStefano Zampini        const=0,
236f336411SStefano Zampini        dest='verbose',
246f336411SStefano Zampini        default=1,
256f336411SStefano Zampini        help='do not print status messages to stdout',
266f336411SStefano Zampini    )
276f336411SStefano Zampini    parser.add_option(
286f336411SStefano Zampini        '-v',
296f336411SStefano Zampini        '--verbose',
306f336411SStefano Zampini        action='store_const',
316f336411SStefano Zampini        const=2,
326f336411SStefano Zampini        dest='verbose',
336f336411SStefano Zampini        default=1,
346f336411SStefano Zampini        help='print status messages to stdout',
356f336411SStefano Zampini    )
366f336411SStefano Zampini    parser.add_option(
376f336411SStefano Zampini        '-i',
386f336411SStefano Zampini        '--include',
396f336411SStefano Zampini        type='string',
406f336411SStefano Zampini        action='append',
416f336411SStefano Zampini        dest='include',
426f336411SStefano Zampini        default=[],
436f336411SStefano Zampini        help='include tests matching PATTERN',
446f336411SStefano Zampini        metavar='PATTERN',
456f336411SStefano Zampini    )
466f336411SStefano Zampini    parser.add_option(
476f336411SStefano Zampini        '-e',
486f336411SStefano Zampini        '--exclude',
496f336411SStefano Zampini        type='string',
506f336411SStefano Zampini        action='append',
516f336411SStefano Zampini        dest='exclude',
526f336411SStefano Zampini        default=[],
536f336411SStefano Zampini        help='exclude tests matching PATTERN',
546f336411SStefano Zampini        metavar='PATTERN',
556f336411SStefano Zampini    )
566f336411SStefano Zampini    parser.add_option(
576f336411SStefano Zampini        '-k',
586f336411SStefano Zampini        '--pattern',
596f336411SStefano Zampini        type='string',
606f336411SStefano Zampini        action='append',
616f336411SStefano Zampini        dest='patterns',
626f336411SStefano Zampini        default=[],
636f336411SStefano Zampini        help='only run tests which match the given substring',
646f336411SStefano Zampini    )
656f336411SStefano Zampini    parser.add_option(
666f336411SStefano Zampini        '-f',
676f336411SStefano Zampini        '--failfast',
686f336411SStefano Zampini        action='store_true',
696f336411SStefano Zampini        dest='failfast',
706f336411SStefano Zampini        default=False,
716f336411SStefano Zampini        help='Stop on first failure',
726f336411SStefano Zampini    )
736f336411SStefano Zampini    parser.add_option(
746f336411SStefano Zampini        '--no-builddir',
756f336411SStefano Zampini        action='store_false',
766f336411SStefano Zampini        dest='builddir',
776f336411SStefano Zampini        default=True,
786f336411SStefano Zampini        help='disable testing from build directory',
796f336411SStefano Zampini    )
806f336411SStefano Zampini    parser.add_option(
816f336411SStefano Zampini        '--path',
826f336411SStefano Zampini        type='string',
836f336411SStefano Zampini        action='append',
846f336411SStefano Zampini        dest='path',
856f336411SStefano Zampini        default=[],
866f336411SStefano Zampini        help='prepend PATH to sys.path',
876f336411SStefano Zampini        metavar='PATH',
886f336411SStefano Zampini    )
896f336411SStefano Zampini    parser.add_option(
906f336411SStefano Zampini        '--arch',
916f336411SStefano Zampini        type='string',
926f336411SStefano Zampini        action='store',
936f336411SStefano Zampini        dest='arch',
946f336411SStefano Zampini        default=None,
956f336411SStefano Zampini        help='use PETSC_ARCH',
966f336411SStefano Zampini        metavar='PETSC_ARCH',
976f336411SStefano Zampini    )
986f336411SStefano Zampini    parser.add_option(
996f336411SStefano Zampini        '-s',
1006f336411SStefano Zampini        '--summary',
1016f336411SStefano Zampini        action='store_true',
1026f336411SStefano Zampini        dest='summary',
1036f336411SStefano Zampini        default=0,
1046f336411SStefano Zampini        help='print PETSc log summary',
1056f336411SStefano Zampini    )
1066f336411SStefano Zampini    parser.add_option(
1076f336411SStefano Zampini        '--no-memdebug',
1086f336411SStefano Zampini        action='store_false',
1096f336411SStefano Zampini        dest='memdebug',
1106f336411SStefano Zampini        default=True,
1116f336411SStefano Zampini        help='Do not use PETSc memory debugging',
1126f336411SStefano 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]
1366f336411SStefano Zampini    except Exception:
137fb83dddaSLisandro Dalcin        import platform
1386f336411SStefano Zampini
139fb83dddaSLisandro Dalcin        name = platform.uname()[1]
140fb83dddaSLisandro Dalcin    from petsc4py.PETSc import COMM_WORLD
1416f336411SStefano Zampini
142fb83dddaSLisandro Dalcin    rank = COMM_WORLD.getRank()
143fb83dddaSLisandro Dalcin    return (rank, name)
144fb83dddaSLisandro Dalcin
145fb83dddaSLisandro Dalcin
146f46a955bSLisandro Dalcindef getlibraryinfo(name):
1476f336411SStefano 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
1516f336411SStefano Zampini    if r:
1526f336411SStefano Zampini        release = 'release'
1536f336411SStefano Zampini    else:
1546f336411SStefano Zampini        release = 'development'
155f46a955bSLisandro Dalcin    arch = module.__arch__
1566f336411SStefano 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]
1616f336411SStefano 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]
1726f336411SStefano 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__))
177*051d6827SStefano Zampini    builddir = getbuilddir()
178*051d6827SStefano Zampini    if builddir is not None:
179*051d6827SStefano Zampini        builddir = os.path.join(rootdir, builddir)
180*051d6827SStefano Zampini    if options.builddir and builddir is not None and os.path.exists(builddir):
1815808f684SSatish Balay        sys.path.insert(0, builddir)
1825808f684SSatish Balay    if options.path:
1835808f684SSatish Balay        path = options.path[:]
1845808f684SSatish Balay        path.reverse()
1855808f684SSatish Balay        for p in path:
1865808f684SSatish Balay            sys.path.insert(0, p)
1875808f684SSatish Balay
188fb83dddaSLisandro Dalcin
1895808f684SSatish Balaydef setup_unittest(options):
1905808f684SSatish Balay    try:
1915808f684SSatish Balay        from unittest.runner import _WritelnDecorator
1925808f684SSatish Balay    except ImportError:
1935808f684SSatish Balay        from unittest import _WritelnDecorator
1945808f684SSatish Balay    #
1955808f684SSatish Balay    writeln_orig = _WritelnDecorator.writeln
1966f336411SStefano Zampini
1975808f684SSatish Balay    def writeln(self, message=''):
1986f336411SStefano Zampini        try:
1996f336411SStefano Zampini            self.stream.flush()
2006f336411SStefano Zampini        except Exception:
2016f336411SStefano Zampini            pass
2025808f684SSatish Balay        writeln_orig(self, message)
2036f336411SStefano Zampini        try:
2046f336411SStefano Zampini            self.stream.flush()
2056f336411SStefano Zampini        except Exception:
2066f336411SStefano Zampini            pass
2076f336411SStefano Zampini
2085808f684SSatish Balay    _WritelnDecorator.writeln = writeln
2095808f684SSatish Balay
210fb83dddaSLisandro Dalcin
2115808f684SSatish Balaydef import_package(options, pkgname):
212b254a87dSStefano Zampini    args = [sys.argv[0]]
213b254a87dSStefano Zampini    if options.memdebug:
214b254a87dSStefano Zampini        args.append('-malloc_debug')
215b254a87dSStefano Zampini        args.append('-malloc_dump')
2165808f684SSatish Balay    if options.summary:
2175808f684SSatish Balay        args.append('-log_view')
2185808f684SSatish Balay    package = __import__(pkgname)
2195808f684SSatish Balay    package.init(args, arch=options.arch)
2205808f684SSatish Balay
2215808f684SSatish Balay
222fb83dddaSLisandro Dalcindef print_banner(options):
223fb83dddaSLisandro Dalcin    r, n = getprocessorinfo()
2246f336411SStefano Zampini    prefix = '[%d@%s]' % (r, n)
2255808f684SSatish Balay
2265808f684SSatish Balay    def writeln(message='', endl='\n'):
227fb83dddaSLisandro Dalcin        if message is None:
228fb83dddaSLisandro Dalcin            return
2295808f684SSatish Balay        from petsc4py.PETSc import Sys
2306f336411SStefano Zampini
2316f336411SStefano Zampini        message = f'{prefix} {message}'
2325808f684SSatish Balay        Sys.syncPrint(message, endl=endl, flush=True)
2335808f684SSatish Balay
2345808f684SSatish Balay    if options.verbose:
235fb83dddaSLisandro Dalcin        writeln(getpythoninfo())
236fb83dddaSLisandro Dalcin        writeln(getpackageinfo('numpy'))
237f46a955bSLisandro Dalcin        for entry in components:
238f46a955bSLisandro Dalcin            writeln(getlibraryinfo(entry))
239e405789aSLisandro Dalcin            writeln(getpackageinfo('%s4py' % entry.lower()))
240fb83dddaSLisandro Dalcin
2415808f684SSatish Balay
2425808f684SSatish Balaydef load_tests(options, args):
2435808f684SSatish Balay    from glob import glob
2445808f684SSatish Balay    import re
2456f336411SStefano Zampini
2465808f684SSatish Balay    testsuitedir = os.path.dirname(__file__)
2475808f684SSatish Balay    sys.path.insert(0, testsuitedir)
2485808f684SSatish Balay    pattern = 'test_*.py'
2495808f684SSatish Balay    wildcard = os.path.join(testsuitedir, pattern)
2505808f684SSatish Balay    testfiles = glob(wildcard)
2515808f684SSatish Balay    testfiles.sort()
2525808f684SSatish Balay    testsuite = unittest.TestSuite()
2535808f684SSatish Balay    testloader = unittest.TestLoader()
2541e51fb16SStefano Zampini    if options.patterns:
255f5636c68SSatish Balay        testloader.testNamePatterns = [ # novermin
2566f336411SStefano Zampini            ('*%s*' % p) if ('*' not in p) else p for p in options.patterns
257f46a955bSLisandro Dalcin        ]
2585808f684SSatish Balay    include = exclude = None
2595808f684SSatish Balay    if options.include:
2605808f684SSatish Balay        include = re.compile('|'.join(options.include)).search
2615808f684SSatish Balay    if options.exclude:
2625808f684SSatish Balay        exclude = re.compile('|'.join(options.exclude)).search
2635808f684SSatish Balay    for testfile in testfiles:
2645808f684SSatish Balay        filename = os.path.basename(testfile)
2655808f684SSatish Balay        testname = os.path.splitext(filename)[0]
2666f336411SStefano Zampini        if (exclude and exclude(testname)) or (include and not include(testname)):
2675808f684SSatish Balay            continue
2685808f684SSatish Balay        module = __import__(testname)
2695808f684SSatish Balay        for arg in args:
2705808f684SSatish Balay            try:
2715808f684SSatish Balay                cases = testloader.loadTestsFromNames((arg,), module)
2725808f684SSatish Balay                testsuite.addTests(cases)
2735808f684SSatish Balay            except AttributeError:
2745808f684SSatish Balay                pass
2755808f684SSatish Balay        if not args:
2765808f684SSatish Balay            cases = testloader.loadTestsFromModule(module)
2775808f684SSatish Balay            testsuite.addTests(cases)
2785808f684SSatish Balay    return testsuite
2795808f684SSatish Balay
280fb83dddaSLisandro Dalcin
2815808f684SSatish Balaydef run_tests(options, testsuite, runner=None):
2825808f684SSatish Balay    if runner is None:
2835808f684SSatish Balay        runner = unittest.TextTestRunner(verbosity=options.verbose)
2845808f684SSatish Balay        runner.failfast = options.failfast
2855808f684SSatish Balay    result = runner.run(testsuite)
2865808f684SSatish Balay    return result.wasSuccessful()
2875808f684SSatish Balay
288fb83dddaSLisandro Dalcin
2895808f684SSatish Balaydef abort(code=1):
2905808f684SSatish Balay    os.abort()
2915808f684SSatish Balay
292fb83dddaSLisandro Dalcin
2935808f684SSatish Balaydef shutdown(success):
2945808f684SSatish Balay    pass
2955808f684SSatish Balay
296fb83dddaSLisandro Dalcin
2975808f684SSatish Balaydef main(args=None):
298f46a955bSLisandro Dalcin    pkgname = '%s4py' % components[-1].lower()
2995808f684SSatish Balay    parser = getoptionparser()
3005808f684SSatish Balay    (options, args) = parser.parse_args(args)
3015808f684SSatish Balay    setup_python(options)
3025808f684SSatish Balay    setup_unittest(options)
303fb83dddaSLisandro Dalcin    import_package(options, pkgname)
304fb83dddaSLisandro Dalcin    print_banner(options)
3055808f684SSatish Balay    testsuite = load_tests(options, args)
3065808f684SSatish Balay    success = run_tests(options, testsuite)
3076f336411SStefano Zampini    if not success and options.failfast:
3086f336411SStefano Zampini        abort()
3095808f684SSatish Balay    shutdown(success)
3105808f684SSatish Balay    return not success
3115808f684SSatish Balay
312fb83dddaSLisandro Dalcin
3135808f684SSatish Balayif __name__ == '__main__':
3145808f684SSatish Balay    import sys
3156f336411SStefano Zampini
3165808f684SSatish Balay    sys.dont_write_bytecode = True
3175808f684SSatish Balay    sys.exit(main())
318