xref: /petsc/src/binding/petsc4py/test/runtests.py (revision b254a87d8f00b4cbd2ec69d20701b6994d8d7069)
15808f684SSatish Balayimport sys, os
25808f684SSatish Balayimport optparse
35808f684SSatish Balayimport unittest
45808f684SSatish Balay
55808f684SSatish Balaydef getoptionparser():
65808f684SSatish Balay    parser = optparse.OptionParser()
75808f684SSatish Balay
85808f684SSatish Balay    parser.add_option("-q", "--quiet",
95808f684SSatish Balay                      action="store_const", const=0, dest="verbose", default=1,
105808f684SSatish Balay                      help="do not print status messages to stdout")
115808f684SSatish Balay    parser.add_option("-v", "--verbose",
125808f684SSatish Balay                      action="store_const", const=2, dest="verbose", default=1,
135808f684SSatish Balay                      help="print status messages to stdout")
145808f684SSatish Balay    parser.add_option("-i", "--include", type="string",
155808f684SSatish Balay                      action="append",  dest="include", default=[],
165808f684SSatish Balay                      help="include tests matching PATTERN", metavar="PATTERN")
175808f684SSatish Balay    parser.add_option("-e", "--exclude", type="string",
185808f684SSatish Balay                      action="append", dest="exclude", default=[],
195808f684SSatish Balay                      help="exclude tests matching PATTERN", metavar="PATTERN")
201e51fb16SStefano Zampini    parser.add_option("-k", "--pattern", type="string",
211e51fb16SStefano Zampini                      action="append", dest="patterns", default=[],
221e51fb16SStefano Zampini                      help="only run tests which match the given substring")
235808f684SSatish Balay    parser.add_option("-f", "--failfast",
245808f684SSatish Balay                      action="store_true", dest="failfast", default=False,
255808f684SSatish Balay                      help="Stop on first failure")
265808f684SSatish Balay    parser.add_option("--no-builddir",
275808f684SSatish Balay                      action="store_false", dest="builddir", default=True,
285808f684SSatish Balay                      help="disable testing from build directory")
295808f684SSatish Balay    parser.add_option("--path", type="string",
305808f684SSatish Balay                      action="append", dest="path", default=[],
315808f684SSatish Balay                      help="prepend PATH to sys.path", metavar="PATH")
325808f684SSatish Balay    parser.add_option("--refleaks", type="int",
335808f684SSatish Balay                      action="store", dest="repeats", default=3,
345808f684SSatish Balay                      help="run tests REPEAT times in a loop to catch leaks",
355808f684SSatish Balay                      metavar="REPEAT")
365808f684SSatish Balay    parser.add_option("--arch", type="string",
375808f684SSatish Balay                      action="store", dest="arch", default=None,
385808f684SSatish Balay                      help="use PETSC_ARCH",
395808f684SSatish Balay                      metavar="PETSC_ARCH")
405808f684SSatish Balay    parser.add_option("-s","--summary",
415808f684SSatish Balay                      action="store_true", dest="summary", default=0,
425808f684SSatish Balay                      help="print PETSc log summary")
43*b254a87dSStefano Zampini    parser.add_option("--no-memdebug",
44*b254a87dSStefano Zampini                      action="store_false", dest="memdebug", default=True,
45*b254a87dSStefano Zampini                      help="Do not use PETSc memory debugging")
465808f684SSatish Balay    return parser
475808f684SSatish Balay
485808f684SSatish Balaydef getbuilddir():
495808f684SSatish Balay    from distutils.util import get_platform
505808f684SSatish Balay    s = os.path.join("build", "lib.%s-%.3s" % (get_platform(), sys.version))
515808f684SSatish Balay    if hasattr(sys, 'gettotalrefcount'): s += '-pydebug'
525808f684SSatish Balay    return s
535808f684SSatish Balay
545808f684SSatish Balaydef setup_python(options):
555808f684SSatish Balay    rootdir = os.path.dirname(os.path.dirname(__file__))
565808f684SSatish Balay    builddir = os.path.join(rootdir, getbuilddir())
575808f684SSatish Balay    if options.builddir and os.path.exists(builddir):
585808f684SSatish Balay        sys.path.insert(0, builddir)
595808f684SSatish Balay    if options.path:
605808f684SSatish Balay        path = options.path[:]
615808f684SSatish Balay        path.reverse()
625808f684SSatish Balay        for p in path:
635808f684SSatish Balay            sys.path.insert(0, p)
645808f684SSatish Balay
655808f684SSatish Balaydef setup_unittest(options):
665808f684SSatish Balay    from unittest import TestSuite
675808f684SSatish Balay    try:
685808f684SSatish Balay        from unittest.runner import _WritelnDecorator
695808f684SSatish Balay    except ImportError:
705808f684SSatish Balay        from unittest import _WritelnDecorator
715808f684SSatish Balay    #
725808f684SSatish Balay    writeln_orig = _WritelnDecorator.writeln
735808f684SSatish Balay    def writeln(self, message=''):
745808f684SSatish Balay        try: self.stream.flush()
755808f684SSatish Balay        except: pass
765808f684SSatish Balay        writeln_orig(self, message)
775808f684SSatish Balay        try: self.stream.flush()
785808f684SSatish Balay        except: pass
795808f684SSatish Balay    _WritelnDecorator.writeln = writeln
805808f684SSatish Balay
815808f684SSatish Balaydef import_package(options, pkgname):
82*b254a87dSStefano Zampini    args = [ sys.argv[0] ]
83*b254a87dSStefano Zampini    if options.memdebug:
84*b254a87dSStefano Zampini        args.append('-malloc')
85*b254a87dSStefano Zampini        args.append('-malloc_debug')
86*b254a87dSStefano Zampini        args.append('-malloc_dump')
875808f684SSatish Balay    if options.summary:
885808f684SSatish Balay        args.append('-log_view')
895808f684SSatish Balay    package = __import__(pkgname)
905808f684SSatish Balay    package.init(args, arch=options.arch)
915808f684SSatish Balay    return package
925808f684SSatish Balay
935808f684SSatish Balaydef getprocessorinfo():
9445ab8edeSSatish Balay    try:
9545ab8edeSSatish Balay        name = os.uname()[1]
9645ab8edeSSatish Balay    except:
9745ab8edeSSatish Balay        import platform
9845ab8edeSSatish Balay        name = platform.uname()[1]
995808f684SSatish Balay    from petsc4py.PETSc import COMM_WORLD
1005808f684SSatish Balay    rank = COMM_WORLD.getRank()
1015808f684SSatish Balay    return (rank, name)
1025808f684SSatish Balay
1035808f684SSatish Balaydef getlibraryinfo():
1045808f684SSatish Balay    from petsc4py import PETSc
1055808f684SSatish Balay    (major, minor, micro) = PETSc.Sys.getVersion()
1065808f684SSatish Balay    r = PETSc.Sys.getVersionInfo()['release']
1075808f684SSatish Balay    if r: release = 'release'
1085808f684SSatish Balay    else: release = 'development'
1095808f684SSatish Balay    arch = PETSc.__arch__
1105808f684SSatish Balay    return ("PETSc %d.%d.%d %s (conf: '%s')"
1115808f684SSatish Balay            % (major, minor, micro, release, arch) )
1125808f684SSatish Balay
1135808f684SSatish Balaydef getpythoninfo():
1145808f684SSatish Balay    x, y = sys.version_info[:2]
1155808f684SSatish Balay    return ("Python %d.%d (%s)" % (x, y, sys.executable))
1165808f684SSatish Balay
1175808f684SSatish Balaydef getpackageinfo(pkg):
1185808f684SSatish Balay    return ("%s %s (%s)" % (pkg.__name__,
1195808f684SSatish Balay                            pkg.__version__,
1205808f684SSatish Balay                            pkg.__path__[0]))
1215808f684SSatish Balay
1225808f684SSatish Balaydef writeln(message='', endl='\n'):
1235808f684SSatish Balay    from petsc4py.PETSc import Sys
1245808f684SSatish Balay    Sys.syncPrint(message, endl=endl, flush=True)
1255808f684SSatish Balay
1265808f684SSatish Balaydef print_banner(options, package):
1275808f684SSatish Balay    r, n = getprocessorinfo()
1285808f684SSatish Balay    fmt = "[%d@%s] %s"
1295808f684SSatish Balay    if options.verbose:
1305808f684SSatish Balay        writeln(fmt % (r, n, getpythoninfo()))
1315808f684SSatish Balay        writeln(fmt % (r, n, getlibraryinfo()))
1325808f684SSatish Balay        writeln(fmt % (r, n, getpackageinfo(package)))
1335808f684SSatish Balay
1345808f684SSatish Balaydef load_tests(options, args):
1355808f684SSatish Balay    from glob import glob
1365808f684SSatish Balay    import re
1375808f684SSatish Balay    testsuitedir = os.path.dirname(__file__)
1385808f684SSatish Balay    sys.path.insert(0, testsuitedir)
1395808f684SSatish Balay    pattern = 'test_*.py'
1405808f684SSatish Balay    wildcard = os.path.join(testsuitedir, pattern)
1415808f684SSatish Balay    testfiles = glob(wildcard)
1425808f684SSatish Balay    testfiles.sort()
1435808f684SSatish Balay    testsuite = unittest.TestSuite()
1445808f684SSatish Balay    testloader = unittest.TestLoader()
1451e51fb16SStefano Zampini    if options.patterns:
1461e51fb16SStefano Zampini        testloader.testNamePatterns = [
1471e51fb16SStefano Zampini            ('*%s*' % p) if ('*' not in p) else p
1481e51fb16SStefano Zampini            for p in options.patterns]
1495808f684SSatish Balay    include = exclude = None
1505808f684SSatish Balay    if options.include:
1515808f684SSatish Balay        include = re.compile('|'.join(options.include)).search
1525808f684SSatish Balay    if options.exclude:
1535808f684SSatish Balay        exclude = re.compile('|'.join(options.exclude)).search
1545808f684SSatish Balay    for testfile in testfiles:
1555808f684SSatish Balay        filename = os.path.basename(testfile)
1565808f684SSatish Balay        testname = os.path.splitext(filename)[0]
1575808f684SSatish Balay        if ((exclude and exclude(testname)) or
1585808f684SSatish Balay            (include and not include(testname))):
1595808f684SSatish Balay            continue
1605808f684SSatish Balay        module = __import__(testname)
1615808f684SSatish Balay        for arg in args:
1625808f684SSatish Balay            try:
1635808f684SSatish Balay                cases = testloader.loadTestsFromNames((arg,), module)
1645808f684SSatish Balay                testsuite.addTests(cases)
1655808f684SSatish Balay            except AttributeError:
1665808f684SSatish Balay                pass
1675808f684SSatish Balay        if not args:
1685808f684SSatish Balay            cases = testloader.loadTestsFromModule(module)
1695808f684SSatish Balay            testsuite.addTests(cases)
1705808f684SSatish Balay    return testsuite
1715808f684SSatish Balay
1725808f684SSatish Balaydef run_tests(options, testsuite, runner=None):
1735808f684SSatish Balay    if runner is None:
1745808f684SSatish Balay        runner = unittest.TextTestRunner(verbosity=options.verbose)
1755808f684SSatish Balay        runner.failfast = options.failfast
1765808f684SSatish Balay    result = runner.run(testsuite)
1775808f684SSatish Balay    return result.wasSuccessful()
1785808f684SSatish Balay
1795808f684SSatish Balaydef test_refleaks(options, args):
1805808f684SSatish Balay    from sys import gettotalrefcount
1815808f684SSatish Balay    from gc import collect
1825808f684SSatish Balay    from copy import deepcopy
1835808f684SSatish Balay    testsuite = load_tests(options, args)
1845808f684SSatish Balay    class EmptyIO(object):
1855808f684SSatish Balay        def write(self, *args):
1865808f684SSatish Balay            pass
1875808f684SSatish Balay    runner = unittest.TextTestRunner(stream=EmptyIO(), verbosity=0)
1885808f684SSatish Balay    rank, name = getprocessorinfo()
1895808f684SSatish Balay    r1 = r2 = 0
1905808f684SSatish Balay    repeats = options.repeats
1915808f684SSatish Balay    while repeats:
1925808f684SSatish Balay        collect()
1935808f684SSatish Balay        r1 = gettotalrefcount()
1945808f684SSatish Balay        run_tests(options, deepcopy(testsuite), runner)
1955808f684SSatish Balay        collect()
1965808f684SSatish Balay        r2 = gettotalrefcount()
1975808f684SSatish Balay        leaks = r2-r1
1985808f684SSatish Balay        if leaks and repeats < options.repeats:
1995808f684SSatish Balay            writeln('[%d@%s] refleaks:  (%d - %d) --> %d'
2005808f684SSatish Balay                    % (rank, name, r2, r1, leaks))
2015808f684SSatish Balay        repeats -= 1
2025808f684SSatish Balay
2035808f684SSatish Balaydef abort(code=1):
2045808f684SSatish Balay    os.abort()
2055808f684SSatish Balay
2065808f684SSatish Balaydef shutdown(success):
2075808f684SSatish Balay    pass
2085808f684SSatish Balay
2095808f684SSatish Balaydef main(args=None):
2105808f684SSatish Balay    pkgname = 'petsc4py'
2115808f684SSatish Balay    parser = getoptionparser()
2125808f684SSatish Balay    (options, args) = parser.parse_args(args)
2135808f684SSatish Balay    setup_python(options)
2145808f684SSatish Balay    setup_unittest(options)
2155808f684SSatish Balay    package = import_package(options, pkgname)
2165808f684SSatish Balay    print_banner(options, package)
2175808f684SSatish Balay    testsuite = load_tests(options, args)
2185808f684SSatish Balay    success = run_tests(options, testsuite)
2195808f684SSatish Balay    if not success and options.failfast: abort()
2205808f684SSatish Balay    if success and hasattr(sys, 'gettotalrefcount'):
2215808f684SSatish Balay        test_refleaks(options, args)
2225808f684SSatish Balay    shutdown(success)
2235808f684SSatish Balay    return not success
2245808f684SSatish Balay
2255808f684SSatish Balayif __name__ == '__main__':
2265808f684SSatish Balay    import sys
2275808f684SSatish Balay    sys.dont_write_bytecode = True
2285808f684SSatish Balay    sys.exit(main())
229