f236712ff84e336c4b202317299b52f4162cc5ea
[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('--parallel', action="store_true", default=False,
55                     help='Ignored.  For compatibility with run-tests.scm.')
56
57 args = parser.parse_args()
58 if not args.interpreters:
59     args.interpreters = [sys.executable]
60
61 out = sys.stdout if args.verbose else None
62 err = sys.stderr if args.verbose else None
63
64 def status_to_str(code):
65     return {0: "PASS", 77: "SKIP", 99: "ERROR"}.get(code, "FAIL")
66
67 results = list()
68 for interpreter in args.interpreters:
69     version = subprocess.check_output(
70         [interpreter, "-c", "import sys; print('{0}.{1}'.format(sys.version_info[0], sys.version_info[1]))"]).strip().decode()
71
72     pattern = os.path.join(args.builddir, "..",
73                            "{0}-gpg".format(os.path.basename(interpreter)),
74                            "lib*")
75     builddirs = glob.glob(pattern)
76     if len(builddirs) == 0:
77         sys.exit("Build directory matching {0!r} not found.".format(pattern))
78     elif len(builddirs) > 1:
79         sys.exit("Multiple build directories matching {0!r} found: {1}".format(
80             pattern, builddirs))
81
82     env = dict(os.environ)
83     env["PYTHONPATH"] = builddirs[0]
84
85     if not args.quiet:
86         print("Running tests using {0} ({1})...".format(interpreter, version))
87
88     for test in args.tests:
89         status = subprocess.call(
90             [interpreter, os.path.join(args.srcdir, test)],
91             env=env, stdout=out, stderr=err)
92         if not args.quiet:
93             print("{0}: {1}".format(status_to_str(status), test))
94         results.append(status)
95
96 def count(status):
97     return len(list(filter(lambda x: x == status, results)))
98 def failed():
99     return len(list(filter(lambda x: x not in (0, 77, 99), results)))
100
101 if not args.quiet:
102     print("{0} tests run, {1} succeeded, {2} failed, {3} skipped.".format(
103         len(results), count(0), failed(), count(77)))
104     sys.exit(len(results) - count(0) - count(77))
105 sys.exit(results[0])