Blame tools/test-tool-option-parsing.py

Packit Service ce9a3e
#! /usr/libexec/platform-python
Packit Service f6b565
# vim: set expandtab shiftwidth=4:
Packit Service f6b565
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
Packit Service f6b565
#
Packit Service f6b565
# Copyright © 2018 Red Hat, Inc.
Packit Service f6b565
#
Packit Service f6b565
# Permission is hereby granted, free of charge, to any person obtaining a
Packit Service f6b565
# copy of this software and associated documentation files (the "Software"),
Packit Service f6b565
# to deal in the Software without restriction, including without limitation
Packit Service f6b565
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
Packit Service f6b565
# and/or sell copies of the Software, and to permit persons to whom the
Packit Service f6b565
# Software is furnished to do so, subject to the following conditions:
Packit Service f6b565
#
Packit Service f6b565
# The above copyright notice and this permission notice (including the next
Packit Service f6b565
# paragraph) shall be included in all copies or substantial portions of the
Packit Service f6b565
# Software.
Packit Service f6b565
#
Packit Service f6b565
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service f6b565
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service f6b565
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
Packit Service f6b565
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit Service f6b565
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit Service f6b565
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Packit Service f6b565
# DEALINGS IN THE SOFTWARE.
Packit Service f6b565
Packit Service f6b565
import argparse
Packit Service f6b565
import os
Packit Service f6b565
import unittest
Packit Service f6b565
import resource
Packit Service f6b565
import sys
Packit Service f6b565
import subprocess
Packit Service f6b565
import time
Packit Service f6b565
Packit Service f6b565
Packit Service f6b565
def _disable_coredump():
Packit Service f6b565
    resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
Packit Service f6b565
Packit Service f6b565
Packit Service f6b565
def run_command(args):
Packit Service f6b565
    with subprocess.Popen(args, preexec_fn=_disable_coredump,
Packit Service f6b565
                          stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p:
Packit Service f6b565
        try:
Packit Service f6b565
            p.wait(0.7)
Packit Service f6b565
        except subprocess.TimeoutExpired:
Packit Service f6b565
            p.send_signal(3)  # SIGQUIT
Packit Service f6b565
        stdout, stderr = p.communicate(timeout=5)
Packit Service f6b565
        if p.returncode == -3:
Packit Service f6b565
            p.returncode = 0
Packit Service f6b565
        return p.returncode, stdout.decode('UTF-8'), stderr.decode('UTF-8')
Packit Service f6b565
Packit Service f6b565
Packit Service f6b565
class TestLibinputTool(unittest.TestCase):
Packit Service f6b565
    libinput_tool = 'libinput'
Packit Service f6b565
    subtool = None
Packit Service f6b565
Packit Service f6b565
    def run_command(self, args):
Packit Service f6b565
        args = [self.libinput_tool] + args
Packit Service f6b565
        if self.subtool is not None:
Packit Service f6b565
            args.insert(1, self.subtool)
Packit Service f6b565
Packit Service f6b565
        return run_command(args)
Packit Service f6b565
Packit Service f6b565
    def run_command_success(self, args):
Packit Service f6b565
        rc, stdout, stderr = self.run_command(args)
Packit Service f6b565
        # if we're running as user, we might fail the command but we should
Packit Service f6b565
        # never get rc 2 (invalid usage)
Packit Service f6b565
        self.assertIn(rc, [0, 1])
Packit Service f6b565
Packit Service f6b565
    def run_command_unrecognized_option(self, args):
Packit Service f6b565
        rc, stdout, stderr = self.run_command(args)
Packit Service f6b565
        self.assertEqual(rc, 2)
Packit Service f6b565
        self.assertTrue(stdout.startswith('Usage') or stdout == '')
Packit Service f6b565
        self.assertIn('unrecognized option', stderr)
Packit Service f6b565
Packit Service f6b565
    def run_command_missing_arg(self, args):
Packit Service f6b565
        rc, stdout, stderr = self.run_command(args)
Packit Service f6b565
        self.assertEqual(rc, 2)
Packit Service f6b565
        self.assertTrue(stdout.startswith('Usage') or stdout == '')
Packit Service f6b565
        self.assertIn('requires an argument', stderr)
Packit Service f6b565
Packit Service f6b565
    def run_command_unrecognized_tool(self, args):
Packit Service f6b565
        rc, stdout, stderr = self.run_command(args)
Packit Service f6b565
        self.assertEqual(rc, 2)
Packit Service f6b565
        self.assertTrue(stdout.startswith('Usage') or stdout == '')
Packit Service f6b565
        self.assertIn('is not a libinput command', stderr)
Packit Service f6b565
Packit Service f6b565
Packit Service f6b565
class TestLibinputCommand(TestLibinputTool):
Packit Service f6b565
    subtool = None
Packit Service f6b565
Packit Service f6b565
    def test_help(self):
Packit Service f6b565
        rc, stdout, stderr = self.run_command(['--help'])
Packit Service f6b565
        self.assertEqual(rc, 0)
Packit Service f6b565
        self.assertTrue(stdout.startswith('Usage:'))
Packit Service f6b565
        self.assertEqual(stderr, '')
Packit Service f6b565
Packit Service f6b565
    def test_version(self):
Packit Service f6b565
        rc, stdout, stderr = self.run_command(['--version'])
Packit Service f6b565
        self.assertEqual(rc, 0)
Packit Service f6b565
        self.assertTrue(stdout.startswith('1'))
Packit Service f6b565
        self.assertEqual(stderr, '')
Packit Service f6b565
Packit Service f6b565
    def test_invalid_arguments(self):
Packit Service f6b565
        self.run_command_unrecognized_option(['--banana'])
Packit Service f6b565
        self.run_command_unrecognized_option(['--foo'])
Packit Service f6b565
        self.run_command_unrecognized_option(['--quiet'])
Packit Service f6b565
        self.run_command_unrecognized_option(['--verbose'])
Packit Service f6b565
        self.run_command_unrecognized_option(['--quiet', 'foo'])
Packit Service f6b565
Packit Service f6b565
    def test_invalid_tools(self):
Packit Service f6b565
        self.run_command_unrecognized_tool(['foo'])
Packit Service f6b565
        self.run_command_unrecognized_tool(['debug'])
Packit Service f6b565
        self.run_command_unrecognized_tool(['foo', '--quiet'])
Packit Service f6b565
Packit Service f6b565
Packit Service f6b565
class TestToolWithOptions(object):
Packit Service f6b565
    options = {
Packit Service f6b565
            'pattern': ['sendevents'],
Packit Service f6b565
            # enable/disable options
Packit Service f6b565
            'enable-disable': [
Packit Service f6b565
                        'tap',
Packit Service f6b565
                        'drag',
Packit Service f6b565
                        'drag-lock',
Packit Service f6b565
                        'middlebutton',
Packit Service f6b565
                        'natural-scrolling',
Packit Service f6b565
                        'left-handed',
Packit Service f6b565
                        'dwt'
Packit Service f6b565
            ],
Packit Service f6b565
            # options with distinct values
Packit Service f6b565
            'enums': {
Packit Service f6b565
                'set-click-method': ['none', 'clickfinger', 'buttonareas'],
Packit Service f6b565
                'set-scroll-method': ['none', 'twofinger', 'edge', 'button'],
Packit Service f6b565
                'set-profile': ['adaptive', 'flat'],
Packit Service f6b565
                'set-tap-map': ['lrm', 'lmr'],
Packit Service f6b565
            },
Packit Service f6b565
            # options with a range
Packit Service f6b565
            'ranges': {
Packit Service f6b565
                'set-speed': (float, -1.0, +1.0),
Packit Service f6b565
            }
Packit Service f6b565
    }
Packit Service f6b565
Packit Service f6b565
    def test_udev_seat(self):
Packit Service f6b565
        self.run_command_missing_arg(['--udev'])
Packit Service f6b565
        self.run_command_success(['--udev', 'seat0'])
Packit Service f6b565
        self.run_command_success(['--udev', 'seat1'])
Packit Service f6b565
Packit Service f6b565
    @unittest.skipIf(os.environ.get('UDEV_NOT_AVAILABLE'), "udev required")
Packit Service f6b565
    def test_device(self):
Packit Service f6b565
        self.run_command_missing_arg(['--device'])
Packit Service f6b565
        self.run_command_success(['--device', '/dev/input/event0'])
Packit Service f6b565
        self.run_command_success(['--device', '/dev/input/event1'])
Packit Service f6b565
        self.run_command_success(['/dev/input/event0'])
Packit Service f6b565
Packit Service f6b565
    def test_options_pattern(self):
Packit Service f6b565
        for option in self.options['pattern']:
Packit Service f6b565
            self.run_command_success(['--disable-{}'.format(option), '*'])
Packit Service f6b565
            self.run_command_success(['--disable-{}'.format(option), 'abc*'])
Packit Service f6b565
Packit Service f6b565
    def test_options_enable_disable(self):
Packit Service f6b565
        for option in self.options['enable-disable']:
Packit Service f6b565
            self.run_command_success(['--enable-{}'.format(option)])
Packit Service f6b565
            self.run_command_success(['--disable-{}'.format(option)])
Packit Service f6b565
Packit Service f6b565
    def test_options_enums(self):
Packit Service f6b565
        for option, values in self.options['enums'].items():
Packit Service f6b565
            for v in values:
Packit Service f6b565
                self.run_command_success(['--{}'.format(option), v])
Packit Service f6b565
                self.run_command_success(['--{}={}'.format(option, v)])
Packit Service f6b565
Packit Service f6b565
    def test_options_ranges(self):
Packit Service f6b565
        for option, values in self.options['ranges'].items():
Packit Service f6b565
            range_type, minimum, maximum = values
Packit Service f6b565
            self.assertEqual(range_type, float)
Packit Service f6b565
            step = (maximum - minimum)/10.0
Packit Service f6b565
            value = minimum
Packit Service f6b565
            while value < maximum:
Packit Service f6b565
                self.run_command_success(['--{}'.format(option), str(value)])
Packit Service f6b565
                self.run_command_success(['--{}={}'.format(option, value)])
Packit Service f6b565
                value += step
Packit Service f6b565
            self.run_command_success(['--{}'.format(option), str(maximum)])
Packit Service f6b565
            self.run_command_success(['--{}={}'.format(option, maximum)])
Packit Service f6b565
Packit Service f6b565
    def test_apply_to(self):
Packit Service f6b565
        self.run_command_missing_arg(['--apply-to'])
Packit Service f6b565
        self.run_command_success(['--apply-to', '*foo*'])
Packit Service f6b565
        self.run_command_success(['--apply-to', 'foobar'])
Packit Service f6b565
        self.run_command_success(['--apply-to', 'any'])
Packit Service f6b565
Packit Service f6b565
Packit Service f6b565
class TestDebugEvents(TestToolWithOptions, TestLibinputTool):
Packit Service f6b565
    subtool = 'debug-events'
Packit Service f6b565
Packit Service f6b565
    def test_verbose_quiet(self):
Packit Service f6b565
        rc, stdout, stderr = self.run_command(['--verbose'])
Packit Service f6b565
        self.assertEqual(rc, 0)
Packit Service f6b565
        rc, stdout, stderr = self.run_command(['--quiet'])
Packit Service f6b565
        self.assertEqual(rc, 0)
Packit Service f6b565
        rc, stdout, stderr = self.run_command(['--verbose', '--quiet'])
Packit Service f6b565
        self.assertEqual(rc, 0)
Packit Service f6b565
        rc, stdout, stderr = self.run_command(['--quiet', '--verbose'])
Packit Service f6b565
        self.assertEqual(rc, 0)
Packit Service f6b565
Packit Service f6b565
    def test_invalid_arguments(self):
Packit Service f6b565
        self.run_command_unrecognized_option(['--banana'])
Packit Service f6b565
        self.run_command_unrecognized_option(['--foo'])
Packit Service f6b565
        self.run_command_unrecognized_option(['--version'])
Packit Service f6b565
Packit Service f6b565
Packit Service f6b565
class TestDebugGUI(TestToolWithOptions, TestLibinputTool):
Packit Service f6b565
    subtool = 'debug-gui'
Packit Service f6b565
Packit Service f6b565
    @classmethod
Packit Service f6b565
    def setUpClass(cls):
Packit Service f6b565
        # This is set by meson
Packit Service f6b565
        debug_gui_enabled = @MESON_ENABLED_DEBUG_GUI@
Packit Service f6b565
        if not debug_gui_enabled:
Packit Service f6b565
            raise unittest.SkipTest()
Packit Service f6b565
Packit Service f6b565
        if not os.getenv('DISPLAY') and not os.getenv('WAYLAND_DISPLAY'):
Packit Service f6b565
            raise unittest.SkipTest()
Packit Service f6b565
Packit Service f6b565
        # 77 means gtk_init() failed, which is probably because you can't
Packit Service f6b565
        # connect to the display server.
Packit Service f6b565
        rc, _, _ = run_command([TestLibinputTool.libinput_tool, cls.subtool, '--help'])
Packit Service f6b565
        if rc == 77:
Packit Service f6b565
            raise unittest.SkipTest()
Packit Service f6b565
Packit Service f6b565
    def test_verbose_quiet(self):
Packit Service f6b565
        rc, stdout, stderr = self.run_command(['--verbose'])
Packit Service f6b565
        self.assertEqual(rc, 0)
Packit Service f6b565
Packit Service f6b565
    def test_invalid_arguments(self):
Packit Service f6b565
        self.run_command_unrecognized_option(['--quiet'])
Packit Service f6b565
        self.run_command_unrecognized_option(['--banana'])
Packit Service f6b565
        self.run_command_unrecognized_option(['--foo'])
Packit Service f6b565
        self.run_command_unrecognized_option(['--version'])
Packit Service f6b565
Packit Service f6b565
Packit Service f6b565
if __name__ == '__main__':
Packit Service f6b565
    parser = argparse.ArgumentParser(description='Verify a libinput tool\'s option parsing')
Packit Service f6b565
    parser.add_argument('--tool-path', metavar='/path/to/builddir/libinput',
Packit Service f6b565
                        type=str,
Packit Service f6b565
                        help='Path to the libinput tool in the builddir')
Packit Service f6b565
    parser.add_argument('--verbose', action='store_true')
Packit Service f6b565
    args, remainder = parser.parse_known_args()
Packit Service f6b565
    if args.tool_path is not None:
Packit Service f6b565
        TestLibinputTool.libinput_tool = args.tool_path
Packit Service f6b565
    verbosity = 1
Packit Service f6b565
    if args.verbose:
Packit Service f6b565
        verbosity = 3
Packit Service f6b565
Packit Service f6b565
    argv = [sys.argv[0], *remainder]
Packit Service f6b565
    unittest.main(verbosity=verbosity, argv=argv)