xref: /petsc/src/binding/petsc4py/test/runtests.py (revision fb83dddadea1072c893d178467655cbacad931ac)
1# Author:  Lisandro Dalcin
2# Contact: dalcinl@gmail.com
3import os
4import sys
5import optparse
6import unittest
7
8__unittest = True
9
10
11def getoptionparser():
12    parser = optparse.OptionParser()
13
14    parser.add_option("-q", "--quiet",
15                      action="store_const", const=0, dest="verbose", default=1,
16                      help="do not print status messages to stdout")
17    parser.add_option("-v", "--verbose",
18                      action="store_const", const=2, dest="verbose", default=1,
19                      help="print status messages to stdout")
20    parser.add_option("-i", "--include", type="string",
21                      action="append",  dest="include", default=[],
22                      help="include tests matching PATTERN", metavar="PATTERN")
23    parser.add_option("-e", "--exclude", type="string",
24                      action="append", dest="exclude", default=[],
25                      help="exclude tests matching PATTERN", metavar="PATTERN")
26    parser.add_option("-k", "--pattern", type="string",
27                      action="append", dest="patterns", default=[],
28                      help="only run tests which match the given substring")
29    parser.add_option("-f", "--failfast",
30                      action="store_true", dest="failfast", default=False,
31                      help="Stop on first failure")
32    parser.add_option("--no-builddir",
33                      action="store_false", dest="builddir", default=True,
34                      help="disable testing from build directory")
35    parser.add_option("--path", type="string",
36                      action="append", dest="path", default=[],
37                      help="prepend PATH to sys.path", metavar="PATH")
38    parser.add_option("--arch", type="string",
39                      action="store", dest="arch", default=None,
40                      help="use PETSC_ARCH",
41                      metavar="PETSC_ARCH")
42    parser.add_option("-s","--summary",
43                      action="store_true", dest="summary", default=0,
44                      help="print PETSc log summary")
45    parser.add_option("--no-memdebug",
46                      action="store_false", dest="memdebug", default=True,
47                      help="Do not use PETSc memory debugging")
48    return parser
49
50
51def getbuilddir():
52    try:
53        try:
54            from setuptools.dist import Distribution
55        except ImportError:
56            from distutils.dist import Distribution
57        try:
58            from setuptools.command.build import build
59        except ImportError:
60            from distutils.command.build import build
61        cmd_obj = build(Distribution())
62        cmd_obj.finalize_options()
63        return cmd_obj.build_platlib
64    except Exception:
65        return None
66
67
68def getprocessorinfo():
69    try:
70        name = os.uname()[1]
71    except:
72        import platform
73        name = platform.uname()[1]
74    from petsc4py.PETSc import COMM_WORLD
75    rank = COMM_WORLD.getRank()
76    return (rank, name)
77
78
79def getlibraryinfo():
80    from petsc4py import PETSc
81    (major, minor, micro) = PETSc.Sys.getVersion()
82    r = PETSc.Sys.getVersionInfo()['release']
83    if r: release = 'release'
84    else: release = 'development'
85    arch = PETSc.__arch__
86    return ("PETSc %d.%d.%d %s (conf: '%s')"
87            % (major, minor, micro, release, arch) )
88
89
90def getpythoninfo():
91    x, y, z = sys.version_info[:3]
92    return ("Python %d.%d.%d (%s)" % (x, y, z, sys.executable))
93
94
95def getpackageinfo(pkg):
96    try:
97        pkg = __import__(pkg)
98    except ImportError:
99        return None
100    name = pkg.__name__
101    version = pkg.__version__
102    path = pkg.__path__[0]
103    return ("%s %s (%s)" % (name, version, path))
104
105
106def setup_python(options):
107    rootdir = os.path.dirname(os.path.dirname(__file__))
108    builddir = os.path.join(rootdir, getbuilddir())
109    if options.builddir and os.path.exists(builddir):
110        sys.path.insert(0, builddir)
111    if options.path:
112        path = options.path[:]
113        path.reverse()
114        for p in path:
115            sys.path.insert(0, p)
116
117
118def setup_unittest(options):
119    from unittest import TestSuite
120    try:
121        from unittest.runner import _WritelnDecorator
122    except ImportError:
123        from unittest import _WritelnDecorator
124    #
125    writeln_orig = _WritelnDecorator.writeln
126    def writeln(self, message=''):
127        try: self.stream.flush()
128        except: pass
129        writeln_orig(self, message)
130        try: self.stream.flush()
131        except: pass
132    _WritelnDecorator.writeln = writeln
133
134
135def import_package(options, pkgname):
136    args = [ sys.argv[0] ]
137    if options.memdebug:
138        args.append('-malloc')
139        args.append('-malloc_debug')
140        args.append('-malloc_dump')
141    if options.summary:
142        args.append('-log_view')
143    package = __import__(pkgname)
144    package.init(args, arch=options.arch)
145
146
147def print_banner(options):
148    r, n = getprocessorinfo()
149    prefix = "[%d@%s]" % (r, n)
150
151    def writeln(message='', endl='\n'):
152        if message is None:
153            return
154        from petsc4py.PETSc import Sys
155        message = "%s %s" % (prefix, message)
156        Sys.syncPrint(message, endl=endl, flush=True)
157
158    if options.verbose:
159        writeln(getpythoninfo())
160        writeln(getpackageinfo('numpy'))
161        writeln(getlibraryinfo())
162        writeln(getpackageinfo('petsc4py'))
163
164
165def load_tests(options, args):
166    from glob import glob
167    import re
168    testsuitedir = os.path.dirname(__file__)
169    sys.path.insert(0, testsuitedir)
170    pattern = 'test_*.py'
171    wildcard = os.path.join(testsuitedir, pattern)
172    testfiles = glob(wildcard)
173    testfiles.sort()
174    testsuite = unittest.TestSuite()
175    testloader = unittest.TestLoader()
176    if options.patterns:
177        testloader.testNamePatterns = [
178            ('*%s*' % p) if ('*' not in p) else p
179            for p in options.patterns]
180    include = exclude = None
181    if options.include:
182        include = re.compile('|'.join(options.include)).search
183    if options.exclude:
184        exclude = re.compile('|'.join(options.exclude)).search
185    for testfile in testfiles:
186        filename = os.path.basename(testfile)
187        testname = os.path.splitext(filename)[0]
188        if ((exclude and exclude(testname)) or
189            (include and not include(testname))):
190            continue
191        module = __import__(testname)
192        for arg in args:
193            try:
194                cases = testloader.loadTestsFromNames((arg,), module)
195                testsuite.addTests(cases)
196            except AttributeError:
197                pass
198        if not args:
199            cases = testloader.loadTestsFromModule(module)
200            testsuite.addTests(cases)
201    return testsuite
202
203
204def run_tests(options, testsuite, runner=None):
205    if runner is None:
206        runner = unittest.TextTestRunner(verbosity=options.verbose)
207        runner.failfast = options.failfast
208    result = runner.run(testsuite)
209    return result.wasSuccessful()
210
211
212
213def abort(code=1):
214    os.abort()
215
216
217def shutdown(success):
218    pass
219
220
221def main(args=None):
222    pkgname = 'petsc4py'
223    parser = getoptionparser()
224    (options, args) = parser.parse_args(args)
225    setup_python(options)
226    setup_unittest(options)
227    import_package(options, pkgname)
228    print_banner(options)
229    testsuite = load_tests(options, args)
230    success = run_tests(options, testsuite)
231    if not success and options.failfast: abort()
232    shutdown(success)
233    return not success
234
235
236if __name__ == '__main__':
237    import sys
238    sys.dont_write_bytecode = True
239    sys.exit(main())
240