diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 43c1bfe34..01105e56e 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -1167,6 +1167,9 @@ foreach test_name, extra_args : gio_tests ) endforeach +python_test_env = test_env +python_test_env.prepend('PYTHONPATH', python_test_libraries_path) + foreach test_name, extra_args : python_tests depends = [extra_args.get('depends', [])] suite = ['gio', 'no-valgrind'] + extra_args.get('suite', []) @@ -1186,7 +1189,7 @@ foreach test_name, extra_args : python_tests protocol : extra_args.get('protocol', test_protocol), depends: depends, args: ['-B', files(test_name)], - env: test_env, + env: python_test_env, timeout: timeout, suite: suite, ) @@ -1213,15 +1216,6 @@ foreach test_name, extra_args : python_tests endif endforeach -# TAP test runner for Python tests -if installed_tests_enabled - install_data( - files('taptestrunner.py'), - install_dir: installed_tests_execdir, - install_tag: 'tests', - ) -endif - if have_bash and have_pkg_config prefix = get_option('prefix') if prefix.endswith(':/') diff --git a/gio/tests/taptestrunner.py b/gio/tests/taptestrunner.py deleted file mode 100644 index 9ce3b43a4..000000000 --- a/gio/tests/taptestrunner.py +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 - -# Copyright (c) 2015 Remko Tronçon (https://el-tramo.be) -# Copied from https://github.com/remko/pycotap/ -# -# Released under the MIT license -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - - -import unittest -import sys -import base64 -from io import StringIO - - -# Log modes -class LogMode(object): - LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4) - - -class TAPTestResult(unittest.TestResult): - def __init__(self, output_stream, error_stream, message_log, test_output_log): - super(TAPTestResult, self).__init__(self, output_stream) - self.output_stream = output_stream - self.error_stream = error_stream - self.orig_stdout = None - self.orig_stderr = None - self.message = None - self.test_output = None - self.message_log = message_log - self.test_output_log = test_output_log - self.output_stream.write("TAP version 13\n") - self._set_streams() - - def printErrors(self): - self.print_raw("1..%d\n" % self.testsRun) - self._reset_streams() - - def _set_streams(self): - self.orig_stdout = sys.stdout - self.orig_stderr = sys.stderr - if self.message_log == LogMode.LogToError: - self.message = self.error_stream - else: - self.message = StringIO() - if self.test_output_log == LogMode.LogToError: - self.test_output = self.error_stream - else: - self.test_output = StringIO() - - if self.message_log == self.test_output_log: - self.test_output = self.message - sys.stdout = sys.stderr = self.test_output - - def _reset_streams(self): - sys.stdout = self.orig_stdout - sys.stderr = self.orig_stderr - - def print_raw(self, text): - self.output_stream.write(text) - self.output_stream.flush() - - def print_result(self, result, test, directive=None): - self.output_stream.write("%s %d %s" % (result, self.testsRun, test.id())) - if directive: - self.output_stream.write(" # " + directive) - self.output_stream.write("\n") - self.output_stream.flush() - - def ok(self, test, directive=None): - self.print_result("ok", test, directive) - - def not_ok(self, test): - self.print_result("not ok", test) - - def startTest(self, test): - super(TAPTestResult, self).startTest(test) - - def stopTest(self, test): - super(TAPTestResult, self).stopTest(test) - if self.message_log == self.test_output_log: - logs = [(self.message_log, self.message, "output")] - else: - logs = [ - (self.test_output_log, self.test_output, "test_output"), - (self.message_log, self.message, "message"), - ] - for log_mode, log, log_name in logs: - if log_mode != LogMode.LogToError: - output = log.getvalue() - if len(output): - if log_mode == LogMode.LogToYAML: - self.print_raw(" ---\n") - self.print_raw(" " + log_name + ": |\n") - self.print_raw( - " " + output.rstrip().replace("\n", "\n ") + "\n" - ) - self.print_raw(" ...\n") - elif log_mode == LogMode.LogToAttachment: - self.print_raw(" ---\n") - self.print_raw(" " + log_name + ":\n") - self.print_raw(" File-Name: " + log_name + ".txt\n") - self.print_raw(" File-Type: text/plain\n") - self.print_raw( - " File-Content: " + base64.b64encode(output) + "\n" - ) - self.print_raw(" ...\n") - else: - self.print_raw( - "# " + output.rstrip().replace("\n", "\n# ") + "\n" - ) - # Truncate doesn't change the current stream position. - # Seek to the beginning to avoid extensions on subsequent writes. - log.seek(0) - log.truncate(0) - - def addSuccess(self, test): - super(TAPTestResult, self).addSuccess(test) - self.ok(test) - - def addError(self, test, err): - super(TAPTestResult, self).addError(test, err) - self.message.write(self.errors[-1][1] + "\n") - self.not_ok(test) - - def addFailure(self, test, err): - super(TAPTestResult, self).addFailure(test, err) - self.message.write(self.failures[-1][1] + "\n") - self.not_ok(test) - - def addSkip(self, test, reason): - super(TAPTestResult, self).addSkip(test, reason) - self.ok(test, "SKIP " + reason) - - def addExpectedFailure(self, test, err): - super(TAPTestResult, self).addExpectedFailure(test, err) - self.ok(test) - - def addUnexpectedSuccess(self, test): - super(TAPTestResult, self).addUnexpectedSuccess(test) - self.message.write("Unexpected success" + "\n") - self.not_ok(test) - - -class TAPTestRunner(object): - def __init__( - self, - message_log=LogMode.LogToYAML, - test_output_log=LogMode.LogToDiagnostics, - output_stream=sys.stdout, - error_stream=sys.stderr, - ): - self.output_stream = output_stream - self.error_stream = error_stream - self.message_log = message_log - self.test_output_log = test_output_log - - def run(self, test): - result = TAPTestResult( - self.output_stream, - self.error_stream, - self.message_log, - self.test_output_log, - ) - test(result) - result.printErrors() - - return result diff --git a/glib/tests/meson.build b/glib/tests/meson.build index 4b77cd93f..5734001e2 100644 --- a/glib/tests/meson.build +++ b/glib/tests/meson.build @@ -512,6 +512,9 @@ if 'messages-low-memory' in test_extra_programs } endif +python_test_env = test_env +python_test_env.prepend('PYTHONPATH', python_test_libraries_path) + foreach test_name, extra_args : python_tests depends = [extra_args.get('depends', [])] suite = ['glib', 'core', 'no-valgrind'] @@ -520,7 +523,7 @@ foreach test_name, extra_args : python_tests suite += 'failing' endif - local_test_env = test_env + local_test_env = python_test_env foreach var, value : extra_args.get('env', {}) local_test_env.append(var, value) endforeach diff --git a/gobject/tests/meson.build b/gobject/tests/meson.build index a163e5f91..f59fa72aa 100644 --- a/gobject/tests/meson.build +++ b/gobject/tests/meson.build @@ -227,6 +227,9 @@ foreach test_name, extra_args : gobject_tests ) endforeach +python_test_env = test_env +python_test_env.prepend('PYTHONPATH', python_test_libraries_path) + foreach test_name, extra_args : python_tests depends = [extra_args.get('depends', [])] suite = ['gobject', 'no-valgrind'] @@ -241,7 +244,7 @@ foreach test_name, extra_args : python_tests protocol : extra_args.get('protocol', test_protocol), depends: depends, args: ['-B', files(test_name)], - env: test_env, + env: python_test_env, suite: suite, ) @@ -266,12 +269,3 @@ foreach test_name, extra_args : python_tests ) endif endforeach - -# TAP test runner for Python tests -if installed_tests_enabled - install_data( - files('taptestrunner.py'), - install_dir: installed_tests_execdir, - install_tag: 'tests', - ) -endif diff --git a/gobject/tests/taptestrunner.py b/gobject/tests/taptestrunner.py deleted file mode 100644 index 9adbd8daa..000000000 --- a/gobject/tests/taptestrunner.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python -# coding=utf-8 - -# Copyright (c) 2015 Remko Tronçon (https://el-tramo.be) -# Copied from https://github.com/remko/pycotap/ -# -# SPDX-License-Identifier: MIT -# -# Released under the MIT license -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - - -import unittest -import sys -import base64 -from io import StringIO - - -# Log modes -class LogMode(object): - LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4) - - -class TAPTestResult(unittest.TestResult): - def __init__(self, output_stream, error_stream, message_log, test_output_log): - super(TAPTestResult, self).__init__(self, output_stream) - self.output_stream = output_stream - self.error_stream = error_stream - self.orig_stdout = None - self.orig_stderr = None - self.message = None - self.test_output = None - self.message_log = message_log - self.test_output_log = test_output_log - self.output_stream.write("TAP version 13\n") - self._set_streams() - - def printErrors(self): - self.print_raw("1..%d\n" % self.testsRun) - self._reset_streams() - - def _set_streams(self): - self.orig_stdout = sys.stdout - self.orig_stderr = sys.stderr - if self.message_log == LogMode.LogToError: - self.message = self.error_stream - else: - self.message = StringIO() - if self.test_output_log == LogMode.LogToError: - self.test_output = self.error_stream - else: - self.test_output = StringIO() - - if self.message_log == self.test_output_log: - self.test_output = self.message - sys.stdout = sys.stderr = self.test_output - - def _reset_streams(self): - sys.stdout = self.orig_stdout - sys.stderr = self.orig_stderr - - def print_raw(self, text): - self.output_stream.write(text) - self.output_stream.flush() - - def print_result(self, result, test, directive=None): - self.output_stream.write("%s %d %s" % (result, self.testsRun, test.id())) - if directive: - self.output_stream.write(" # " + directive) - self.output_stream.write("\n") - self.output_stream.flush() - - def ok(self, test, directive=None): - self.print_result("ok", test, directive) - - def not_ok(self, test): - self.print_result("not ok", test) - - def startTest(self, test): - super(TAPTestResult, self).startTest(test) - - def stopTest(self, test): - super(TAPTestResult, self).stopTest(test) - if self.message_log == self.test_output_log: - logs = [(self.message_log, self.message, "output")] - else: - logs = [ - (self.test_output_log, self.test_output, "test_output"), - (self.message_log, self.message, "message"), - ] - for log_mode, log, log_name in logs: - if log_mode != LogMode.LogToError: - output = log.getvalue() - if len(output): - if log_mode == LogMode.LogToYAML: - self.print_raw(" ---\n") - self.print_raw(" " + log_name + ": |\n") - self.print_raw( - " " + output.rstrip().replace("\n", "\n ") + "\n" - ) - self.print_raw(" ...\n") - elif log_mode == LogMode.LogToAttachment: - self.print_raw(" ---\n") - self.print_raw(" " + log_name + ":\n") - self.print_raw(" File-Name: " + log_name + ".txt\n") - self.print_raw(" File-Type: text/plain\n") - self.print_raw( - " File-Content: " + base64.b64encode(output) + "\n" - ) - self.print_raw(" ...\n") - else: - self.print_raw( - "# " + output.rstrip().replace("\n", "\n# ") + "\n" - ) - # Truncate doesn't change the current stream position. - # Seek to the beginning to avoid extensions on subsequent writes. - log.seek(0) - log.truncate(0) - - def addSuccess(self, test): - super(TAPTestResult, self).addSuccess(test) - self.ok(test) - - def addError(self, test, err): - super(TAPTestResult, self).addError(test, err) - self.message.write(self.errors[-1][1] + "\n") - self.not_ok(test) - - def addFailure(self, test, err): - super(TAPTestResult, self).addFailure(test, err) - self.message.write(self.failures[-1][1] + "\n") - self.not_ok(test) - - def addSkip(self, test, reason): - super(TAPTestResult, self).addSkip(test, reason) - self.ok(test, "SKIP " + reason) - - def addExpectedFailure(self, test, err): - super(TAPTestResult, self).addExpectedFailure(test, err) - self.ok(test) - - def addUnexpectedSuccess(self, test): - super(TAPTestResult, self).addUnexpectedSuccess(test) - self.message.write("Unexpected success" + "\n") - self.not_ok(test) - - -class TAPTestRunner(object): - def __init__( - self, - message_log=LogMode.LogToYAML, - test_output_log=LogMode.LogToDiagnostics, - output_stream=sys.stdout, - error_stream=sys.stderr, - ): - self.output_stream = output_stream - self.error_stream = error_stream - self.message_log = message_log - self.test_output_log = test_output_log - - def run(self, test): - result = TAPTestResult( - self.output_stream, - self.error_stream, - self.message_log, - self.test_output_log, - ) - test(result) - result.printErrors() - - return result diff --git a/meson.build b/meson.build index 484e7e8ed..00c97d370 100644 --- a/meson.build +++ b/meson.build @@ -2495,6 +2495,8 @@ python_shebang = '/usr/bin/env python3' python_version = python.language_version() python_version_req = '>=3.7' +python_test_libraries_path = meson.project_source_root() / 'tests' / 'lib' +assert(fs.exists(python_test_libraries_path)) if not python_version.version_compare(python_version_req) error('Requires Python @0@, @1@ found.'.format(python_version_req, python_version)) endif diff --git a/glib/tests/taptestrunner.py b/tests/lib/taptestrunner.py similarity index 100% rename from glib/tests/taptestrunner.py rename to tests/lib/taptestrunner.py diff --git a/tests/meson.build b/tests/meson.build index d807d33b4..376925863 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -33,3 +33,14 @@ test( suite : ['lint', 'no-valgrind'], protocol : 'tap', ) + +# TAP test runner for Python tests +if installed_tests_enabled + install_data( + files(fs.relative_to( + meson.project_source_root() / python_test_libraries_path, + meson.current_source_dir()) / 'taptestrunner.py'), + install_dir: installed_tests_execdir, + install_tag: 'tests', + ) +endif