# See the documentation here: #
# https://wayland.freedesktop.org/libinput/doc/latest/building_libinput.html #
###############################################################################
- FEDORA_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel diffutils'
- FEDORA_QEMU_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel diffutils valgrind'
- UBUNTU_CUSTOM_DEBS: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev'
- ARCH_PKGS: 'git gcc pkgconfig meson check libsystemd libevdev doxygen graphviz python-sphinx python-recommonmark python-sphinx_rtd_theme libwacom gtk3 mtdev diffutils'
+ FEDORA_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme python3-pytest-xdist libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel diffutils'
+ FEDORA_QEMU_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme python3-pytest-xdist libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel diffutils valgrind'
+ UBUNTU_CUSTOM_DEBS: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme python3-pytest-xdist libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev'
+ ARCH_PKGS: 'git gcc pkgconfig meson check libsystemd libevdev doxygen graphviz python-sphinx python-recommonmark python-sphinx_rtd_theme python-pytest-xdist libwacom gtk3 mtdev diffutils'
FREEBSD_BUILD_PKGS: 'meson'
FREEBSD_PKGS: 'libepoll-shim libudev-devd libevdev libwacom gtk3 libmtdev '
ALPINE_PKGS: 'git gcc build-base pkgconfig meson check-dev eudev-dev libevdev-dev libwacom-dev cairo-dev gtk+3.0-dev mtdev-dev bash'
# changing these will force rebuilding the associated image
# Note: these tags have no meaning and are not tied to a particular
# libinput version
- FEDORA_TAG: '2020-02-26.0'
- UBUNTU_TAG: '2020-02-26.0'
- ARCH_TAG: '2020-02-26.0'
+ FEDORA_TAG: '2020-03-16.0'
+ UBUNTU_TAG: '2020-03-16.0'
+ ARCH_TAG: '2020-03-16.0'
ALPINE_TAG: '2020-02-26.0'
FREEBSD_TAG: '2020-02-26.0'
- QEMU_TAG: 'qemu-vm-2020-02-26.0'
+ QEMU_TAG: 'qemu-vm-2020-03-16.0'
UBUNTU_EXEC: "bash .gitlab-ci/ubuntu_install.sh $UBUNTU_CUSTOM_DEBS"
# See the documentation here: #
# https://wayland.freedesktop.org/libinput/doc/latest/building_libinput.html #
###############################################################################
- FEDORA_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel diffutils'
- FEDORA_QEMU_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel diffutils valgrind'
- UBUNTU_CUSTOM_DEBS: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev'
- ARCH_PKGS: 'git gcc pkgconfig meson check libsystemd libevdev doxygen graphviz python-sphinx python-recommonmark python-sphinx_rtd_theme libwacom gtk3 mtdev diffutils'
+ FEDORA_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme python3-pytest-xdist libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel diffutils'
+ FEDORA_QEMU_RPMS: 'git gcc gcc-c++ pkgconf-pkg-config meson check-devel libudev-devel libevdev-devel doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx_rtd_theme python3-pytest-xdist libwacom-devel cairo-devel gtk3-devel glib2-devel mtdev-devel diffutils valgrind'
+ UBUNTU_CUSTOM_DEBS: 'git gcc g++ pkg-config meson check libudev-dev libevdev-dev doxygen graphviz python3-sphinx python3-recommonmark python3-sphinx-rtd-theme python3-pytest-xdist libwacom-dev libcairo2-dev libgtk-3-dev libglib2.0-dev libmtdev-dev'
+ ARCH_PKGS: 'git gcc pkgconfig meson check libsystemd libevdev doxygen graphviz python-sphinx python-recommonmark python-sphinx_rtd_theme python-pytest-xdist libwacom gtk3 mtdev diffutils'
FREEBSD_BUILD_PKGS: 'meson'
FREEBSD_PKGS: 'libepoll-shim libudev-devd libevdev libwacom gtk3 libmtdev '
ALPINE_PKGS: 'git gcc build-base pkgconfig meson check-dev eudev-dev libevdev-dev libwacom-dev cairo-dev gtk+3.0-dev mtdev-dev bash'
# changing these will force rebuilding the associated image
# Note: these tags have no meaning and are not tied to a particular
# libinput version
- FEDORA_TAG: '2020-02-26.0'
- UBUNTU_TAG: '2020-02-26.0'
- ARCH_TAG: '2020-02-26.0'
+ FEDORA_TAG: '2020-03-16.0'
+ UBUNTU_TAG: '2020-03-16.0'
+ ARCH_TAG: '2020-03-16.0'
ALPINE_TAG: '2020-02-26.0'
FREEBSD_TAG: '2020-02-26.0'
- QEMU_TAG: 'qemu-vm-2020-02-26.0'
+ QEMU_TAG: 'qemu-vm-2020-03-16.0'
UBUNTU_EXEC: "bash .gitlab-ci/ubuntu_install.sh $UBUNTU_CUSTOM_DEBS"
# subtool lookup
if get_option('buildtype') == 'debug' or get_option('buildtype') == 'debugoptimized'
config_tool_option_test = configuration_data()
+ config_tool_option_test.set('DISABLE_WARNING', 'yes')
config_tool_option_test.set('MESON_ENABLED_DEBUG_GUI', get_option('debug-gui'))
- tool_option_test = configure_file(input: 'tools/test-tool-option-parsing.py',
- output: '@BASENAME@',
+ config_tool_option_test.set('MESON_BUILD_ROOT', meson.current_build_dir())
+ config_tool_option_test.set('TOOL_PATH', libinput_tool.full_path())
+ tool_option_test = configure_file(input: 'tools/test_tool_option_parsing.py',
+ output: '@PLAINNAME@',
configuration : config_tool_option_test)
test('tool-option-parsing',
tool_option_test,
- args : ['--tool-path', libinput_tool.full_path()],
+ args : [tool_option_test, '-n', 'auto'],
suite : ['all', 'root'],
timeout : 240)
endif
+++ /dev/null
-#!/usr/bin/env python3
-# vim: set expandtab shiftwidth=4:
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-#
-# Copyright © 2018 Red Hat, Inc.
-#
-# 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 (including the next
-# paragraph) 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 argparse
-import os
-import unittest
-import resource
-import sys
-import subprocess
-import tempfile
-from pathlib import Path
-
-
-def _disable_coredump():
- resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
-
-
-def run_command(args):
- with subprocess.Popen(args, preexec_fn=_disable_coredump,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p:
- try:
- p.wait(0.7)
- except subprocess.TimeoutExpired:
- p.send_signal(3) # SIGQUIT
- stdout, stderr = p.communicate(timeout=5)
- if p.returncode == -3:
- p.returncode = 0
- return p.returncode, stdout.decode('UTF-8'), stderr.decode('UTF-8')
-
-
-class TestLibinputTool(unittest.TestCase):
- libinput_tool = 'libinput'
- subtool = None
-
- def run_command(self, args):
- args = [self.libinput_tool] + args
- if self.subtool is not None:
- args.insert(1, self.subtool)
-
- return run_command(args)
-
- def run_command_success(self, args):
- rc, stdout, stderr = self.run_command(args)
- # if we're running as user, we might fail the command but we should
- # never get rc 2 (invalid usage)
- self.assertIn(rc, [0, 1], msg=(stdout, stderr))
-
- def run_command_unrecognized_option(self, args):
- rc, stdout, stderr = self.run_command(args)
- self.assertEqual(rc, 2)
- self.assertTrue(stdout.startswith('Usage') or stdout == '')
- self.assertIn('unrecognized option', stderr)
-
- def run_command_missing_arg(self, args):
- rc, stdout, stderr = self.run_command(args)
- self.assertEqual(rc, 2)
- self.assertTrue(stdout.startswith('Usage') or stdout == '')
- self.assertIn('requires an argument', stderr)
-
- def run_command_unrecognized_tool(self, args):
- rc, stdout, stderr = self.run_command(args)
- self.assertEqual(rc, 2)
- self.assertTrue(stdout.startswith('Usage') or stdout == '')
- self.assertIn('is not a libinput command', stderr)
-
-
-class TestLibinputCommand(TestLibinputTool):
- subtool = None
-
- def test_help(self):
- rc, stdout, stderr = self.run_command(['--help'])
- self.assertEqual(rc, 0)
- self.assertTrue(stdout.startswith('Usage:'))
- self.assertEqual(stderr, '')
-
- def test_version(self):
- rc, stdout, stderr = self.run_command(['--version'])
- self.assertEqual(rc, 0)
- self.assertTrue(stdout.startswith('1'))
- self.assertEqual(stderr, '')
-
- def test_invalid_arguments(self):
- self.run_command_unrecognized_option(['--banana'])
- self.run_command_unrecognized_option(['--foo'])
- self.run_command_unrecognized_option(['--quiet'])
- self.run_command_unrecognized_option(['--verbose'])
- self.run_command_unrecognized_option(['--quiet', 'foo'])
-
- def test_invalid_tools(self):
- self.run_command_unrecognized_tool(['foo'])
- self.run_command_unrecognized_tool(['debug'])
- self.run_command_unrecognized_tool(['foo', '--quiet'])
-
-
-class TestToolWithOptions(object):
- options = {
- 'pattern': ['sendevents'],
- # enable/disable options
- 'enable-disable': [
- 'tap',
- 'drag',
- 'drag-lock',
- 'middlebutton',
- 'natural-scrolling',
- 'left-handed',
- 'dwt'
- ],
- # options with distinct values
- 'enums': {
- 'set-click-method': ['none', 'clickfinger', 'buttonareas'],
- 'set-scroll-method': ['none', 'twofinger', 'edge', 'button'],
- 'set-profile': ['adaptive', 'flat'],
- 'set-tap-map': ['lrm', 'lmr'],
- },
- # options with a range
- 'ranges': {
- 'set-speed': (float, -1.0, +1.0),
- }
- }
-
- def test_udev_seat(self):
- self.run_command_missing_arg(['--udev'])
- self.run_command_success(['--udev', 'seat0'])
- self.run_command_success(['--udev', 'seat1'])
-
- @unittest.skipIf(os.environ.get('UDEV_NOT_AVAILABLE'), "udev required")
- def test_device(self):
- self.run_command_missing_arg(['--device'])
- self.run_command_success(['--device', '/dev/input/event0'])
- self.run_command_success(['--device', '/dev/input/event1'])
- self.run_command_success(['/dev/input/event0'])
-
- def test_options_pattern(self):
- for option in self.options['pattern']:
- self.run_command_success(['--disable-{}'.format(option), '*'])
- self.run_command_success(['--disable-{}'.format(option), 'abc*'])
-
- def test_options_enable_disable(self):
- for option in self.options['enable-disable']:
- self.run_command_success(['--enable-{}'.format(option)])
- self.run_command_success(['--disable-{}'.format(option)])
-
- def test_options_enums(self):
- for option, values in self.options['enums'].items():
- for v in values:
- self.run_command_success(['--{}'.format(option), v])
- self.run_command_success(['--{}={}'.format(option, v)])
-
- def test_options_ranges(self):
- for option, values in self.options['ranges'].items():
- range_type, minimum, maximum = values
- self.assertEqual(range_type, float)
- step = (maximum - minimum) / 10.0
- value = minimum
- while value < maximum:
- self.run_command_success(['--{}'.format(option), str(value)])
- self.run_command_success(['--{}={}'.format(option, value)])
- value += step
- self.run_command_success(['--{}'.format(option), str(maximum)])
- self.run_command_success(['--{}={}'.format(option, maximum)])
-
- def test_apply_to(self):
- self.run_command_missing_arg(['--apply-to'])
- self.run_command_success(['--apply-to', '*foo*'])
- self.run_command_success(['--apply-to', 'foobar'])
- self.run_command_success(['--apply-to', 'any'])
-
-
-class TestDebugEvents(TestToolWithOptions, TestLibinputTool):
- subtool = 'debug-events'
-
- def test_verbose_quiet(self):
- rc, stdout, stderr = self.run_command(['--verbose'])
- self.assertEqual(rc, 0)
- rc, stdout, stderr = self.run_command(['--quiet'])
- self.assertEqual(rc, 0)
- rc, stdout, stderr = self.run_command(['--verbose', '--quiet'])
- self.assertEqual(rc, 0)
- rc, stdout, stderr = self.run_command(['--quiet', '--verbose'])
- self.assertEqual(rc, 0)
-
- def test_invalid_arguments(self):
- self.run_command_unrecognized_option(['--banana'])
- self.run_command_unrecognized_option(['--foo'])
- self.run_command_unrecognized_option(['--version'])
-
- def test_multiple_devices(self):
- self.run_command_success(['--device', '/dev/input/event0', '/dev/input/event1'])
- # same event path multiple times? meh, your problem
- self.run_command_success(['--device', '/dev/input/event0', '/dev/input/event0'])
- self.run_command_success(['/dev/input/event0', '/dev/input/event1'])
-
- def test_too_many_devices(self):
- # Too many arguments just bails with the usage message
- rc, stdout, stderr = self.run_command(['/dev/input/event0'] * 61)
- self.assertEqual(rc, 2, msg=(stdout, stderr))
-
-
-class TestDebugGUI(TestToolWithOptions, TestLibinputTool):
- subtool = 'debug-gui'
-
- @classmethod
- def setUpClass(cls):
- # This is set by meson
- debug_gui_enabled = @MESON_ENABLED_DEBUG_GUI@ # noqa
- if not debug_gui_enabled:
- raise unittest.SkipTest()
-
- if not os.getenv('DISPLAY') and not os.getenv('WAYLAND_DISPLAY'):
- raise unittest.SkipTest()
-
- # 77 means gtk_init() failed, which is probably because you can't
- # connect to the display server.
- rc, _, _ = run_command([TestLibinputTool.libinput_tool, cls.subtool, '--help'])
- if rc == 77:
- raise unittest.SkipTest()
-
- def test_verbose_quiet(self):
- rc, stdout, stderr = self.run_command(['--verbose'])
- self.assertEqual(rc, 0)
-
- def test_invalid_arguments(self):
- self.run_command_unrecognized_option(['--quiet'])
- self.run_command_unrecognized_option(['--banana'])
- self.run_command_unrecognized_option(['--foo'])
- self.run_command_unrecognized_option(['--version'])
-
-
-class TestRecord(TestLibinputTool):
- subtool = 'record'
-
- def setUp(self):
- self.tmpdir = tempfile.TemporaryDirectory()
- self.outfile = Path(self.tmpdir.name, 'record.out')
-
- def tearDown(self):
- self.tmpdir.cleanup()
-
- def test_args(self):
- self.run_command_success(['--help'])
- self.run_command_success(['--show-keycodes'])
- self.run_command_success(['--with-libinput'])
-
- def test_multiple_deprecated(self):
- # this arg is deprecated and a noop
- self.run_command_success(['--multiple'])
-
- def test_all(self):
- self.run_command_success(['--all', '-o', self.outfile])
- self.run_command_success(['--all', self.outfile])
-
- def test_autorestart(self):
- self.run_command_success(['--autorestart=2'])
-
- def test_outfile(self):
- self.run_command_success(['-o', self.outfile])
- self.run_command_success(['--output-file', self.outfile])
- self.run_command_success(['--output-file={}'.format(self.outfile)])
-
- def test_device_single(self):
- self.run_command_success(['/dev/input/event0'])
- self.run_command_success(['/dev/input/event0', self.outfile])
- self.run_command_success([self.outfile, '/dev/input/event0'])
- self.run_command_success([self.outfile, '/dev/input/event0'])
-
- def test_device_multiple(self):
- self.run_command_success(['-o', self.outfile, '/dev/input/event0', '/dev/input/event1'])
- self.run_command_success([self.outfile, '/dev/input/event0', '/dev/input/event1'])
- self.run_command_success(['/dev/input/event0', '/dev/input/event1', self.outfile])
-
-
-if __name__ == '__main__':
- parser = argparse.ArgumentParser(description='Verify a libinput tool\'s option parsing')
- parser.add_argument('--tool-path', metavar='/path/to/builddir/libinput',
- type=str,
- help='Path to the libinput tool in the builddir')
- parser.add_argument('--verbose', action='store_true')
- args, remainder = parser.parse_known_args()
- if args.tool_path is not None:
- TestLibinputTool.libinput_tool = args.tool_path
- verbosity = 1
- if args.verbose:
- verbosity = 3
-
- argv = [sys.argv[0], *remainder]
- unittest.main(verbosity=verbosity, argv=argv)
--- /dev/null
+#!/usr/bin/env python3
+# vim: set expandtab shiftwidth=4:
+# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
+#
+# Copyright © 2018 Red Hat, Inc.
+#
+# 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 (including the next
+# paragraph) 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 os
+import pytest
+import resource
+import sys
+import subprocess
+import logging
+
+logger = logging.getLogger('test')
+logger.setLevel(logging.DEBUG)
+
+if '@DISABLE_WARNING@' != 'yes':
+ print('This is the source file, run the one in the meson builddir instead')
+ sys.exit(1)
+
+
+def _disable_coredump():
+ resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
+
+
+def run_command(args):
+ logger.debug('run command: {}'.format(' '.join(args)))
+ with subprocess.Popen(args, preexec_fn=_disable_coredump,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p:
+ try:
+ p.wait(0.7)
+ except subprocess.TimeoutExpired:
+ p.send_signal(3) # SIGQUIT
+ stdout, stderr = p.communicate(timeout=5)
+ if p.returncode == -3:
+ p.returncode = 0
+ return p.returncode, stdout.decode('UTF-8'), stderr.decode('UTF-8')
+
+
+class LibinputTool(object):
+ libinput_tool = 'libinput'
+ subtool = None
+
+ def __init__(self, subtool=None):
+ self.libinput_tool = "@TOOL_PATH@"
+ self.subtool = subtool
+
+ def run_command(self, args):
+ args = [self.libinput_tool] + args
+ if self.subtool is not None:
+ args.insert(1, self.subtool)
+
+ return run_command(args)
+
+ def run_command_success(self, args):
+ rc, stdout, stderr = self.run_command(args)
+ # if we're running as user, we might fail the command but we should
+ # never get rc 2 (invalid usage)
+ assert rc in [0, 1], (stdout, stderr)
+ return stdout, stderr
+
+ def run_command_invalid(self, args):
+ rc, stdout, stderr = self.run_command(args)
+ assert rc == 2, (rc, stdout, stderr)
+ return rc, stdout, stderr
+
+ def run_command_unrecognized_option(self, args):
+ rc, stdout, stderr = self.run_command(args)
+ assert rc == 2, (rc, stdout, stderr)
+ assert stdout.startswith('Usage') or stdout == ''
+ assert 'unrecognized option' in stderr
+
+ def run_command_missing_arg(self, args):
+ rc, stdout, stderr = self.run_command(args)
+ assert rc == 2, (rc, stdout, stderr)
+ assert stdout.startswith('Usage') or stdout == ''
+ assert 'requires an argument' in stderr
+
+ def run_command_unrecognized_tool(self, args):
+ rc, stdout, stderr = self.run_command(args)
+ assert rc == 2, (rc, stdout, stderr)
+ assert stdout.startswith('Usage') or stdout == ''
+ assert 'is not a libinput command' in stderr
+
+
+class LibinputDebugGui(LibinputTool):
+ def __init__(self, subtool='debug-gui'):
+ assert subtool == 'debug-gui'
+ super().__init__(subtool)
+
+ debug_gui_enabled = '@MESON_ENABLED_DEBUG_GUI@' == 'True'
+ if not debug_gui_enabled:
+ pytest.skip()
+
+ if not os.getenv('DISPLAY') and not os.getenv('WAYLAND_DISPLAY'):
+ pytest.skip()
+
+ # 77 means gtk_init() failed, which is probably because you can't
+ # connect to the display server.
+ rc, _, _ = self.run_command(['--help'])
+ if rc == 77:
+ pytest.skip()
+
+
+def get_tool(subtool=None):
+ if subtool == 'debug-gui':
+ return LibinputDebugGui()
+ else:
+ return LibinputTool(subtool)
+
+
+@pytest.fixture
+def libinput():
+ return get_tool()
+
+
+@pytest.fixture(params=['debug-events', 'debug-gui'])
+def libinput_debug_tool(request):
+ yield get_tool(request.param)
+
+
+@pytest.fixture
+def libinput_debug_events():
+ return get_tool('debug-events')
+
+
+@pytest.fixture
+def libinput_debug_gui():
+ return get_tool('debug-gui')
+
+
+@pytest.fixture
+def libinput_record():
+ return get_tool('record')
+
+
+def test_help(libinput):
+ stdout, stderr = libinput.run_command_success(['--help'])
+ assert stdout.startswith('Usage:')
+ assert stderr == ''
+
+
+def test_version(libinput):
+ stdout, stderr = libinput.run_command_success(['--version'])
+ assert stdout.startswith('1')
+ assert stderr == ''
+
+
+@pytest.mark.parametrize('argument', ['--banana', '--foo', '--quiet', '--verbose'])
+def test_invalid_arguments(libinput, argument):
+ libinput.run_command_unrecognized_option([argument])
+
+
+@pytest.mark.parametrize('tool', [['foo'], ['debug'], ['foo', '--quiet']])
+def test_invalid_tool(libinput, tool):
+ libinput.run_command_unrecognized_tool(tool)
+
+
+def test_udev_seat(libinput_debug_tool):
+ libinput_debug_tool.run_command_missing_arg(['--udev'])
+ libinput_debug_tool.run_command_success(['--udev', 'seat0'])
+ libinput_debug_tool.run_command_success(['--udev', 'seat1'])
+
+
+@pytest.mark.skipif(os.environ.get('UDEV_NOT_AVAILABLE'), reason='udev required')
+def test_device_arg(libinput_debug_tool):
+ libinput_debug_tool.run_command_missing_arg(['--device'])
+ libinput_debug_tool.run_command_success(['--device', '/dev/input/event0'])
+ libinput_debug_tool.run_command_success(['--device', '/dev/input/event1'])
+ libinput_debug_tool.run_command_success(['/dev/input/event0'])
+
+
+options = {
+ 'pattern': ['sendevents'],
+ # enable/disable options
+ 'enable-disable': [
+ 'tap',
+ 'drag',
+ 'drag-lock',
+ 'middlebutton',
+ 'natural-scrolling',
+ 'left-handed',
+ 'dwt'
+ ],
+ # options with distinct values
+ 'enums': {
+ 'set-click-method': ['none', 'clickfinger', 'buttonareas'],
+ 'set-scroll-method': ['none', 'twofinger', 'edge', 'button'],
+ 'set-profile': ['adaptive', 'flat'],
+ 'set-tap-map': ['lrm', 'lmr'],
+ },
+ # options with a range
+ 'ranges': {
+ 'set-speed': (float, -1.0, +1.0),
+ }
+}
+
+
+# Options that allow for glob patterns
+@pytest.mark.parametrize('option', options['pattern'])
+def test_options_pattern(libinput_debug_tool, option):
+ libinput_debug_tool.run_command_success(['--disable-{}'.format(option), '*'])
+ libinput_debug_tool.run_command_success(['--disable-{}'.format(option), 'abc*'])
+
+
+@pytest.mark.parametrize('option', options['enable-disable'])
+def test_options_enable_disable(libinput_debug_tool, option):
+ libinput_debug_tool.run_command_success(['--enable-{}'.format(option)])
+ libinput_debug_tool.run_command_success(['--disable-{}'.format(option)])
+
+
+@pytest.mark.parametrize('option', options['enums'].items())
+def test_options_enums(libinput_debug_tool, option):
+ name, values = option
+ for v in values:
+ libinput_debug_tool.run_command_success(['--{}'.format(name), v])
+ libinput_debug_tool.run_command_success(['--{}={}'.format(name, v)])
+
+
+@pytest.mark.parametrize('option', options['ranges'].items())
+def test_options_ranges(libinput_debug_tool, option):
+ name, values = option
+ range_type, minimum, maximum = values
+ assert range_type == float
+ step = (maximum - minimum) / 10.0
+ value = minimum
+ while value < maximum:
+ libinput_debug_tool.run_command_success(['--{}'.format(name), str(value)])
+ libinput_debug_tool.run_command_success(['--{}={}'.format(name, value)])
+ value += step
+ libinput_debug_tool.run_command_success(['--{}'.format(name), str(maximum)])
+ libinput_debug_tool.run_command_success(['--{}={}'.format(name, maximum)])
+
+
+def test_apply_to(libinput_debug_tool):
+ libinput_debug_tool.run_command_missing_arg(['--apply-to'])
+ libinput_debug_tool.run_command_success(['--apply-to', '*foo*'])
+ libinput_debug_tool.run_command_success(['--apply-to', 'foobar'])
+ libinput_debug_tool.run_command_success(['--apply-to', 'any'])
+
+
+@pytest.mark.parametrize('args', [['--verbose'], ['--quiet'],
+ ['--verbose', '--quiet'],
+ ['--quiet', '--verbose']])
+def test_debug_events_verbose_quiet(libinput_debug_events, args):
+ libinput_debug_events.run_command_success(args)
+
+
+@pytest.mark.parametrize('arg', ['--banana', '--foo', '--version'])
+def test_invalid_args(libinput_debug_tool, arg):
+ libinput_debug_tool.run_command_unrecognized_option([arg])
+
+
+def test_libinput_debug_events_multiple_devices(libinput_debug_events):
+ libinput_debug_events.run_command_success(['--device', '/dev/input/event0', '/dev/input/event1'])
+ # same event path multiple times? meh, your problem
+ libinput_debug_events.run_command_success(['--device', '/dev/input/event0', '/dev/input/event0'])
+ libinput_debug_events.run_command_success(['/dev/input/event0', '/dev/input/event1'])
+
+
+def test_libinput_debug_events_too_many_devices(libinput_debug_events):
+ # Too many arguments just bails with the usage message
+ rc, stdout, stderr = libinput_debug_events.run_command(['/dev/input/event0'] * 61)
+ assert rc == 2, (stdout, stderr)
+
+
+@pytest.mark.parametrize('arg', ['--quiet'])
+def test_libinput_debug_gui_invalid_arg(libinput_debug_gui, arg):
+ libinput_debug_gui.run_command_unrecognized_option([arg])
+
+
+def test_libinput_debug_gui_verbose(libinput_debug_gui):
+ libinput_debug_gui.run_command_success(['--verbose'])
+
+
+@pytest.mark.parametrize('arg', ['--help', '--show-keycodes', '--with-libinput'])
+def test_libinput_record_args(libinput_record, arg):
+ libinput_record.run_command_success([arg])
+
+
+def test_libinput_record_multiple_arg(libinput_record):
+ # this arg is deprecated and a noop
+ libinput_record.run_command_success(['--multiple'])
+
+
+@pytest.fixture
+def recording(tmp_path):
+ return str((tmp_path / 'record.out').resolve())
+
+
+def test_libinput_record_all(libinput_record, recording):
+ libinput_record.run_command_success(['--all', '-o', recording])
+ libinput_record.run_command_success(['--all', recording])
+
+
+def test_libinput_record_outfile(libinput_record, recording):
+ libinput_record.run_command_success(['-o', recording])
+ libinput_record.run_command_success(['--output-file', recording])
+ libinput_record.run_command_success(['--output-file={}'.format(recording)])
+
+
+def test_libinput_record_single(libinput_record, recording):
+ libinput_record.run_command_success(['/dev/input/event0'])
+ libinput_record.run_command_success(['-o', recording, '/dev/input/event0'])
+ libinput_record.run_command_success(['/dev/input/event0', recording])
+ libinput_record.run_command_success([recording, '/dev/input/event0'])
+
+
+def test_libinput_record_multiple(libinput_record, recording):
+ libinput_record.run_command_success(['-o', recording, '/dev/input/event0', '/dev/input/event1'])
+ libinput_record.run_command_success([recording, '/dev/input/event0', '/dev/input/event1'])
+ libinput_record.run_command_success(['/dev/input/event0', '/dev/input/event1', recording])
+
+
+def test_libinput_record_autorestart(libinput_record, recording):
+ libinput_record.run_command_invalid(['--autorestart'])
+ libinput_record.run_command_invalid(['--autorestart=2'])
+ libinput_record.run_command_success(['-o', recording, '--autorestart=2'])
+
+
+def main():
+ args = ['-m', 'pytest']
+ try:
+ import xdist # noqa
+ args += ['-n', 'auto']
+ except ImportError:
+ logger.info('python-xdist missing, this test will be slow')
+ pass
+
+ args += ['@MESON_BUILD_ROOT@']
+
+ return subprocess.run([sys.executable] + args).returncode
+
+
+if __name__ == '__main__':
+ raise SystemExit(main())