diff options
author | Benjamin Berg <bberg@redhat.com> | 2018-04-06 17:01:29 +0200 |
---|---|---|
committer | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2018-05-02 22:29:33 +0000 |
commit | 7630bf963e7e29faddc178f9c7ec9b93d6669249 (patch) | |
tree | 2e8d66c531da412f73eb9643a81ad754feb6195a /tests | |
parent | 8c9be792f25ce4d636e55d0872944936e45517a4 (diff) | |
download | gnome-control-center-7630bf963e7e29faddc178f9c7ec9b93d6669249.tar.gz |
tests: Add helper for glib based test binaries
This makes running glib based tests inside a dbusmock environment easier
and more beautiful (i.e. output is supressed unless an error occurs).
This helper has been submitted for inclusion in dbusmock. If it cannot$
live there in some form, then we should try to find a home in the GNOME$
project for it.$
Diffstat (limited to 'tests')
-rw-r--r-- | tests/shared/gtest.py | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/tests/shared/gtest.py b/tests/shared/gtest.py new file mode 100644 index 000000000..bb7130daf --- /dev/null +++ b/tests/shared/gtest.py @@ -0,0 +1,113 @@ +#!/usr/bin/python3 +# Copyright © 2018 Red Hat, Inc +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# Authors: Benjamin Berg <bberg@redhat.com> + +import os +import sys +import subprocess +import functools + +class _GTestSingleProp(object): + """Property which creates a bound method for calling the specified test.""" + def __init__(self, test): + self.test = test + + @staticmethod + def __func(self, test): + self._gtest_single(test) + + def __get__(self, obj, cls): + bound_method = self.__func.__get__(obj, cls) + partial_method = functools.partial(bound_method, self.test) + partial_method.__doc__ = bound_method.__doc__ + + return partial_method + + +class _GTestMeta(type): + def __new__(cls, name, bases, namespace, **kwds): + result = type.__new__(cls, name, bases, dict(namespace)) + + if result.g_test_exe is not None: + try: + _GTestMeta.make_tests(result.g_test_exe, result) + except Exception as e: + print('') + print(e) + print('Error generating separate test funcs, will call binary once.') + result.test_all = result._gtest_all + + return result + + @staticmethod + def make_tests(exe, result): + env = os.environ.copy() + env['G_MESSAGES_DEBUG'] = '' + test = subprocess.Popen([exe, '-l'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, env=env) + stdout, stderr = test.communicate() + + if test.returncode != 0: + raise AssertionError('Execution of GTest executable to query the tests returned non-zero exit code!') + + stdout = stdout.decode('utf-8') + + for i, test in enumerate(stdout.split('\n')): + if not test: + continue + + # Number it and make sure the function name is prefixed with 'test'. + # Keep the rest as is, we don't care about the fact that the function + # names cannot be typed in. + name = 'test_%03d_' % (i + 1) + test + setattr(result, name, _GTestSingleProp(test)) + + +class GTest(metaclass = _GTestMeta): + """Helper class to run GLib test. A test function will be created for each + test from the executable. + + Use by using this class as a mixin and setting g_test_exe to an appropriate + value. + """ + + #: The GTest based executable + g_test_exe = None + #: Timeout when running a single test + g_test_single_timeout = None + #: Timeout when running all tests in one go + g_test_all_timeout = None + + def _gtest_single(self, test): + assert(test) + p = subprocess.Popen([self.g_test_exe, '-q', '-p', test], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + try: + stdout, stderr = p.communicate(timeout=self.g_test_single_timeout) + except subprocess.TimeoutExpired: + p.kill() + stdout, stderr = p.communicate() + stdout += b'\n\nTest was aborted due to timeout' + + try: + stdout = stdout.decode('utf-8') + except UnicodeDecodeError: + pass + + if p.returncode != 0: + self.fail(stdout) + + def _gtest_all(self): + subprocess.check_call([self.g_test_exe], timeout=self.g_test_all_timeout) |