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