xref: /petsc/src/binding/petsc4py/test/runtests.py (revision 6f33641175f69f1db294cc9ba81c3f4ad4f81d49)
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
18*6f336411SStefano Zampini    parser.add_option(
19*6f336411SStefano Zampini        '-q',
20*6f336411SStefano Zampini        '--quiet',
21*6f336411SStefano Zampini        action='store_const',
22*6f336411SStefano Zampini        const=0,
23*6f336411SStefano Zampini        dest='verbose',
24*6f336411SStefano Zampini        default=1,
25*6f336411SStefano Zampini        help='do not print status messages to stdout',
26*6f336411SStefano Zampini    )
27*6f336411SStefano Zampini    parser.add_option(
28*6f336411SStefano Zampini        '-v',
29*6f336411SStefano Zampini        '--verbose',
30*6f336411SStefano Zampini        action='store_const',
31*6f336411SStefano Zampini        const=2,
32*6f336411SStefano Zampini        dest='verbose',
33*6f336411SStefano Zampini        default=1,
34*6f336411SStefano Zampini        help='print status messages to stdout',
35*6f336411SStefano Zampini    )
36*6f336411SStefano Zampini    parser.add_option(
37*6f336411SStefano Zampini        '-i',
38*6f336411SStefano Zampini        '--include',
39*6f336411SStefano Zampini        type='string',
40*6f336411SStefano Zampini        action='append',
41*6f336411SStefano Zampini        dest='include',
42*6f336411SStefano Zampini        default=[],
43*6f336411SStefano Zampini        help='include tests matching PATTERN',
44*6f336411SStefano Zampini        metavar='PATTERN',
45*6f336411SStefano Zampini    )
46*6f336411SStefano Zampini    parser.add_option(
47*6f336411SStefano Zampini        '-e',
48*6f336411SStefano Zampini        '--exclude',
49*6f336411SStefano Zampini        type='string',
50*6f336411SStefano Zampini        action='append',
51*6f336411SStefano Zampini        dest='exclude',
52*6f336411SStefano Zampini        default=[],
53*6f336411SStefano Zampini        help='exclude tests matching PATTERN',
54*6f336411SStefano Zampini        metavar='PATTERN',
55*6f336411SStefano Zampini    )
56*6f336411SStefano Zampini    parser.add_option(
57*6f336411SStefano Zampini        '-k',
58*6f336411SStefano Zampini        '--pattern',
59*6f336411SStefano Zampini        type='string',
60*6f336411SStefano Zampini        action='append',
61*6f336411SStefano Zampini        dest='patterns',
62*6f336411SStefano Zampini        default=[],
63*6f336411SStefano Zampini        help='only run tests which match the given substring',
64*6f336411SStefano Zampini    )
65*6f336411SStefano Zampini    parser.add_option(
66*6f336411SStefano Zampini        '-f',
67*6f336411SStefano Zampini        '--failfast',
68*6f336411SStefano Zampini        action='store_true',
69*6f336411SStefano Zampini        dest='failfast',
70*6f336411SStefano Zampini        default=False,
71*6f336411SStefano Zampini        help='Stop on first failure',
72*6f336411SStefano Zampini    )
73*6f336411SStefano Zampini    parser.add_option(
74*6f336411SStefano Zampini        '--no-builddir',
75*6f336411SStefano Zampini        action='store_false',
76*6f336411SStefano Zampini        dest='builddir',
77*6f336411SStefano Zampini        default=True,
78*6f336411SStefano Zampini        help='disable testing from build directory',
79*6f336411SStefano Zampini    )
80*6f336411SStefano Zampini    parser.add_option(
81*6f336411SStefano Zampini        '--path',
82*6f336411SStefano Zampini        type='string',
83*6f336411SStefano Zampini        action='append',
84*6f336411SStefano Zampini        dest='path',
85*6f336411SStefano Zampini        default=[],
86*6f336411SStefano Zampini        help='prepend PATH to sys.path',
87*6f336411SStefano Zampini        metavar='PATH',
88*6f336411SStefano Zampini    )
89*6f336411SStefano Zampini    parser.add_option(
90*6f336411SStefano Zampini        '--arch',
91*6f336411SStefano Zampini        type='string',
92*6f336411SStefano Zampini        action='store',
93*6f336411SStefano Zampini        dest='arch',
94*6f336411SStefano Zampini        default=None,
95*6f336411SStefano Zampini        help='use PETSC_ARCH',
96*6f336411SStefano Zampini        metavar='PETSC_ARCH',
97*6f336411SStefano Zampini    )
98*6f336411SStefano Zampini    parser.add_option(
99*6f336411SStefano Zampini        '-s',
100*6f336411SStefano Zampini        '--summary',
101*6f336411SStefano Zampini        action='store_true',
102*6f336411SStefano Zampini        dest='summary',
103*6f336411SStefano Zampini        default=0,
104*6f336411SStefano Zampini        help='print PETSc log summary',
105*6f336411SStefano Zampini    )
106*6f336411SStefano Zampini    parser.add_option(
107*6f336411SStefano Zampini        '--no-memdebug',
108*6f336411SStefano Zampini        action='store_false',
109*6f336411SStefano Zampini        dest='memdebug',
110*6f336411SStefano Zampini        default=True,
111*6f336411SStefano Zampini        help='Do not use PETSc memory debugging',
112*6f336411SStefano 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]
136*6f336411SStefano Zampini    except Exception:
137fb83dddaSLisandro Dalcin        import platform
138*6f336411SStefano Zampini
139fb83dddaSLisandro Dalcin        name = platform.uname()[1]
140fb83dddaSLisandro Dalcin    from petsc4py.PETSc import COMM_WORLD
141*6f336411SStefano Zampini
142fb83dddaSLisandro Dalcin    rank = COMM_WORLD.getRank()
143fb83dddaSLisandro Dalcin    return (rank, name)
144fb83dddaSLisandro Dalcin
145fb83dddaSLisandro Dalcin
146f46a955bSLisandro Dalcindef getlibraryinfo(name):
147*6f336411SStefano 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
151*6f336411SStefano Zampini    if r:
152*6f336411SStefano Zampini        release = 'release'
153*6f336411SStefano Zampini    else:
154*6f336411SStefano Zampini        release = 'development'
155f46a955bSLisandro Dalcin    arch = module.__arch__
156*6f336411SStefano 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]
161*6f336411SStefano 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]
172*6f336411SStefano 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
194*6f336411SStefano Zampini
1955808f684SSatish Balay    def writeln(self, message=''):
196*6f336411SStefano Zampini        try:
197*6f336411SStefano Zampini            self.stream.flush()
198*6f336411SStefano Zampini        except Exception:
199*6f336411SStefano Zampini            pass
2005808f684SSatish Balay        writeln_orig(self, message)
201*6f336411SStefano Zampini        try:
202*6f336411SStefano Zampini            self.stream.flush()
203*6f336411SStefano Zampini        except Exception:
204*6f336411SStefano Zampini            pass
205*6f336411SStefano 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()
222*6f336411SStefano 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
228*6f336411SStefano Zampini
229*6f336411SStefano 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
243*6f336411SStefano 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:
2531e51fb16SStefano Zampini        testloader.testNamePatterns = [
254*6f336411SStefano 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]
264*6f336411SStefano 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)
305*6f336411SStefano Zampini    if not success and options.failfast:
306*6f336411SStefano Zampini        abort()
3075808f684SSatish Balay    shutdown(success)
3085808f684SSatish Balay    return not success
3095808f684SSatish Balay
310fb83dddaSLisandro Dalcin
3115808f684SSatish Balayif __name__ == '__main__':
3125808f684SSatish Balay    import sys
313*6f336411SStefano Zampini
3145808f684SSatish Balay    sys.dont_write_bytecode = True
3155808f684SSatish Balay    sys.exit(main())
316