xref: /petsc/src/binding/petsc4py/test/runtests.py (revision f5636c688d6f85da6ba667a85e3a2a12826d38c6)
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__))
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
1946f336411SStefano Zampini
1955808f684SSatish Balay    def writeln(self, message=''):
1966f336411SStefano Zampini        try:
1976f336411SStefano Zampini            self.stream.flush()
1986f336411SStefano Zampini        except Exception:
1996f336411SStefano Zampini            pass
2005808f684SSatish Balay        writeln_orig(self, message)
2016f336411SStefano Zampini        try:
2026f336411SStefano Zampini            self.stream.flush()
2036f336411SStefano Zampini        except Exception:
2046f336411SStefano Zampini            pass
2056f336411SStefano 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()
2226f336411SStefano 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
2286f336411SStefano Zampini
2296f336411SStefano 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
2436f336411SStefano 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:
253*f5636c68SSatish Balay        testloader.testNamePatterns = [ # novermin
2546f336411SStefano 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]
2646f336411SStefano 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)
3056f336411SStefano Zampini    if not success and options.failfast:
3066f336411SStefano Zampini        abort()
3075808f684SSatish Balay    shutdown(success)
3085808f684SSatish Balay    return not success
3095808f684SSatish Balay
310fb83dddaSLisandro Dalcin
3115808f684SSatish Balayif __name__ == '__main__':
3125808f684SSatish Balay    import sys
3136f336411SStefano Zampini
3145808f684SSatish Balay    sys.dont_write_bytecode = True
3155808f684SSatish Balay    sys.exit(main())
316