python: Support alternatate libdir for tests
[gpgme.git] / lang / python / tests / run-tests.py
1 #!/usr/bin/env python
2
3 # Copyright (C) 2016 g10 Code GmbH
4 #
5 # This file is part of GPGME.
6 #
7 # GPGME is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # GPGME is distributed in the hope that it will be useful, but WITHOUT
13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
15 # Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this program; if not, see <http://www.gnu.org/licenses/>.
19
20 from __future__ import absolute_import
21 from __future__ import division
22 from __future__ import print_function
23 from __future__ import unicode_literals
24
25 import argparse
26 import glob
27 import os
28 import subprocess
29 import sys
30
31 class SplitAndAccumulate(argparse.Action):
32     def __call__(self, parser, namespace, values, option_string=None):
33         current = getattr(namespace, self.dest, list())
34         current.extend(values.split())
35         setattr(namespace, self.dest, current)
36
37 parser = argparse.ArgumentParser(description='Run tests.')
38 parser.add_argument('tests', metavar='TEST', type=str, nargs='+',
39                     help='A test to run')
40 parser.add_argument('-v', '--verbose', action="store_true", default=False,
41                     help='Be verbose.')
42 parser.add_argument('-q', '--quiet', action="store_true", default=False,
43                     help='Be quiet.')
44 parser.add_argument('--interpreters', metavar='PYTHON', type=str,
45                     default=[], action=SplitAndAccumulate,
46                     help='Use these interpreters to run the tests, ' +
47                     'separated by spaces.')
48 parser.add_argument('--srcdir', type=str,
49                     default=os.environ.get("srcdir", ""),
50                     help='Location of the tests.')
51 parser.add_argument('--builddir', type=str,
52                     default=os.environ.get("abs_builddir", ""),
53                     help='Location of the tests.')
54 parser.add_argument('--python-libdir', type=str,
55                     default=None,
56                     help='Optional location of the in-tree module lib directory.')
57 parser.add_argument('--parallel', action="store_true", default=False,
58                     help='Ignored.  For compatibility with run-tests.scm.')
59
60 args = parser.parse_args()
61 if not args.interpreters:
62     args.interpreters = [sys.executable]
63
64 out = sys.stdout if args.verbose else None
65 err = sys.stderr if args.verbose else None
66
67 def status_to_str(code):
68     return {0: "PASS", 77: "SKIP", 99: "ERROR"}.get(code, "FAIL")
69
70 results = list()
71 for interpreter in args.interpreters:
72     version = subprocess.check_output(
73         [interpreter, "-c", "import sys; print('{0}.{1}'.format(sys.version_info[0], sys.version_info[1]))"]).strip().decode()
74
75     if not args.python_libdir:
76         pattern = os.path.join(args.builddir, "..",
77                                "{0}-gpg".format(os.path.basename(interpreter)),
78                                "lib*")
79         libdirs = glob.glob(pattern)
80         if len(libdirs) == 0:
81             sys.exit("Build directory matching {0!r} not found.".format(pattern))
82         elif len(libdirs) > 1:
83             sys.exit("Multiple build directories matching {0!r} found: {1}".format(
84                 pattern, libdirs))
85         python_libdir = libdirs[0]
86
87     env = dict(os.environ)
88     env["PYTHONPATH"] = python_libdir
89
90     if not args.quiet:
91         print("Running tests using {0} ({1})...".format(interpreter, version))
92
93     for test in args.tests:
94         status = subprocess.call(
95             [interpreter, os.path.join(args.srcdir, test)],
96             env=env, stdout=out, stderr=err)
97         if not args.quiet:
98             print("{0}: {1}".format(status_to_str(status), test))
99         results.append(status)
100
101 def count(status):
102     return len(list(filter(lambda x: x == status, results)))
103 def failed():
104     return len(list(filter(lambda x: x not in (0, 77, 99), results)))
105
106 if not args.quiet:
107     print("{0} tests run, {1} succeeded, {2} failed, {3} skipped.".format(
108         len(results), count(0), failed(), count(77)))
109     sys.exit(len(results) - count(0) - count(77))
110 sys.exit(results[0])