xref: /aosp_15_r20/external/libxkbcommon/test/tool-option-parsing.py (revision 2b949d0487e80d67f1fda82db69e101e761f8064)
1*2b949d04SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*2b949d04SAndroid Build Coastguard Worker#
3*2b949d04SAndroid Build Coastguard Worker# Copyright © 2020 Red Hat, Inc.
4*2b949d04SAndroid Build Coastguard Worker#
5*2b949d04SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a
6*2b949d04SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"),
7*2b949d04SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation
8*2b949d04SAndroid Build Coastguard Worker# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*2b949d04SAndroid Build Coastguard Worker# and/or sell copies of the Software, and to permit persons to whom the
10*2b949d04SAndroid Build Coastguard Worker# Software is furnished to do so, subject to the following conditions:
11*2b949d04SAndroid Build Coastguard Worker#
12*2b949d04SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the next
13*2b949d04SAndroid Build Coastguard Worker# paragraph) shall be included in all copies or substantial portions of the
14*2b949d04SAndroid Build Coastguard Worker# Software.
15*2b949d04SAndroid Build Coastguard Worker#
16*2b949d04SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*2b949d04SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*2b949d04SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*2b949d04SAndroid Build Coastguard Worker# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*2b949d04SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*2b949d04SAndroid Build Coastguard Worker# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22*2b949d04SAndroid Build Coastguard Worker# DEALINGS IN THE SOFTWARE.
23*2b949d04SAndroid Build Coastguard Worker
24*2b949d04SAndroid Build Coastguard Workerimport itertools
25*2b949d04SAndroid Build Coastguard Workerimport os
26*2b949d04SAndroid Build Coastguard Workerimport resource
27*2b949d04SAndroid Build Coastguard Workerimport sys
28*2b949d04SAndroid Build Coastguard Workerimport subprocess
29*2b949d04SAndroid Build Coastguard Workerimport logging
30*2b949d04SAndroid Build Coastguard Workerimport tempfile
31*2b949d04SAndroid Build Coastguard Workerimport unittest
32*2b949d04SAndroid Build Coastguard Worker
33*2b949d04SAndroid Build Coastguard Worker
34*2b949d04SAndroid Build Coastguard Workertry:
35*2b949d04SAndroid Build Coastguard Worker    top_builddir = os.environ['top_builddir']
36*2b949d04SAndroid Build Coastguard Worker    top_srcdir = os.environ['top_srcdir']
37*2b949d04SAndroid Build Coastguard Workerexcept KeyError:
38*2b949d04SAndroid Build Coastguard Worker    print('Required environment variables not found: top_srcdir/top_builddir', file=sys.stderr)
39*2b949d04SAndroid Build Coastguard Worker    from pathlib import Path
40*2b949d04SAndroid Build Coastguard Worker    top_srcdir = '.'
41*2b949d04SAndroid Build Coastguard Worker    try:
42*2b949d04SAndroid Build Coastguard Worker        top_builddir = next(Path('.').glob('**/meson-logs/')).parent
43*2b949d04SAndroid Build Coastguard Worker    except StopIteration:
44*2b949d04SAndroid Build Coastguard Worker        sys.exit(1)
45*2b949d04SAndroid Build Coastguard Worker    print('Using srcdir "{}", builddir "{}"'.format(top_srcdir, top_builddir), file=sys.stderr)
46*2b949d04SAndroid Build Coastguard Worker
47*2b949d04SAndroid Build Coastguard Worker
48*2b949d04SAndroid Build Coastguard Workerlogging.basicConfig(level=logging.DEBUG)
49*2b949d04SAndroid Build Coastguard Workerlogger = logging.getLogger('test')
50*2b949d04SAndroid Build Coastguard Workerlogger.setLevel(logging.DEBUG)
51*2b949d04SAndroid Build Coastguard Worker
52*2b949d04SAndroid Build Coastguard Worker# Permutation of RMLVO that we use in multiple tests
53*2b949d04SAndroid Build Coastguard Workerrmlvos = [list(x) for x in itertools.permutations(
54*2b949d04SAndroid Build Coastguard Worker    ['--rules=evdev', '--model=pc104',
55*2b949d04SAndroid Build Coastguard Worker     '--layout=ch', '--options=eurosign:5']
56*2b949d04SAndroid Build Coastguard Worker)]
57*2b949d04SAndroid Build Coastguard Worker
58*2b949d04SAndroid Build Coastguard Worker
59*2b949d04SAndroid Build Coastguard Workerdef _disable_coredump():
60*2b949d04SAndroid Build Coastguard Worker    resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
61*2b949d04SAndroid Build Coastguard Worker
62*2b949d04SAndroid Build Coastguard Worker
63*2b949d04SAndroid Build Coastguard Workerdef run_command(args):
64*2b949d04SAndroid Build Coastguard Worker    logger.debug('run command: {}'.format(' '.join(args)))
65*2b949d04SAndroid Build Coastguard Worker
66*2b949d04SAndroid Build Coastguard Worker    try:
67*2b949d04SAndroid Build Coastguard Worker        p = subprocess.run(args, preexec_fn=_disable_coredump,
68*2b949d04SAndroid Build Coastguard Worker                           capture_output=True, text=True,
69*2b949d04SAndroid Build Coastguard Worker                           timeout=0.7)
70*2b949d04SAndroid Build Coastguard Worker        return p.returncode, p.stdout, p.stderr
71*2b949d04SAndroid Build Coastguard Worker    except subprocess.TimeoutExpired as e:
72*2b949d04SAndroid Build Coastguard Worker        return 0, e.stdout, e.stderr
73*2b949d04SAndroid Build Coastguard Worker
74*2b949d04SAndroid Build Coastguard Worker
75*2b949d04SAndroid Build Coastguard Workerclass XkbcliTool:
76*2b949d04SAndroid Build Coastguard Worker    xkbcli_tool = 'xkbcli'
77*2b949d04SAndroid Build Coastguard Worker    subtool = None
78*2b949d04SAndroid Build Coastguard Worker
79*2b949d04SAndroid Build Coastguard Worker    def __init__(self, subtool=None, skipIf=(), skipError=()):
80*2b949d04SAndroid Build Coastguard Worker        self.tool_path = top_builddir
81*2b949d04SAndroid Build Coastguard Worker        self.subtool = subtool
82*2b949d04SAndroid Build Coastguard Worker        self.skipIf = skipIf
83*2b949d04SAndroid Build Coastguard Worker        self.skipError = skipError
84*2b949d04SAndroid Build Coastguard Worker
85*2b949d04SAndroid Build Coastguard Worker    def run_command(self, args):
86*2b949d04SAndroid Build Coastguard Worker        for condition, reason in self.skipIf:
87*2b949d04SAndroid Build Coastguard Worker            if condition:
88*2b949d04SAndroid Build Coastguard Worker                raise unittest.SkipTest(reason)
89*2b949d04SAndroid Build Coastguard Worker        if self.subtool is not None:
90*2b949d04SAndroid Build Coastguard Worker            tool = '{}-{}'.format(self.xkbcli_tool, self.subtool)
91*2b949d04SAndroid Build Coastguard Worker        else:
92*2b949d04SAndroid Build Coastguard Worker            tool = self.xkbcli_tool
93*2b949d04SAndroid Build Coastguard Worker        args = [os.path.join(self.tool_path, tool)] + args
94*2b949d04SAndroid Build Coastguard Worker
95*2b949d04SAndroid Build Coastguard Worker        return run_command(args)
96*2b949d04SAndroid Build Coastguard Worker
97*2b949d04SAndroid Build Coastguard Worker    def run_command_success(self, args):
98*2b949d04SAndroid Build Coastguard Worker        rc, stdout, stderr = self.run_command(args)
99*2b949d04SAndroid Build Coastguard Worker        if rc != 0:
100*2b949d04SAndroid Build Coastguard Worker            for testfunc, reason in self.skipError:
101*2b949d04SAndroid Build Coastguard Worker                if testfunc(rc, stdout, stderr):
102*2b949d04SAndroid Build Coastguard Worker                    raise unittest.SkipTest(reason)
103*2b949d04SAndroid Build Coastguard Worker        assert rc == 0, (rc, stdout, stderr)
104*2b949d04SAndroid Build Coastguard Worker        return stdout, stderr
105*2b949d04SAndroid Build Coastguard Worker
106*2b949d04SAndroid Build Coastguard Worker    def run_command_invalid(self, args):
107*2b949d04SAndroid Build Coastguard Worker        rc, stdout, stderr = self.run_command(args)
108*2b949d04SAndroid Build Coastguard Worker        assert rc == 2, (rc, stdout, stderr)
109*2b949d04SAndroid Build Coastguard Worker        return rc, stdout, stderr
110*2b949d04SAndroid Build Coastguard Worker
111*2b949d04SAndroid Build Coastguard Worker    def run_command_unrecognized_option(self, args):
112*2b949d04SAndroid Build Coastguard Worker        rc, stdout, stderr = self.run_command(args)
113*2b949d04SAndroid Build Coastguard Worker        assert rc == 2, (rc, stdout, stderr)
114*2b949d04SAndroid Build Coastguard Worker        assert stdout.startswith('Usage') or stdout == ''
115*2b949d04SAndroid Build Coastguard Worker        assert 'unrecognized option' in stderr
116*2b949d04SAndroid Build Coastguard Worker
117*2b949d04SAndroid Build Coastguard Worker    def run_command_missing_arg(self, args):
118*2b949d04SAndroid Build Coastguard Worker        rc, stdout, stderr = self.run_command(args)
119*2b949d04SAndroid Build Coastguard Worker        assert rc == 2, (rc, stdout, stderr)
120*2b949d04SAndroid Build Coastguard Worker        assert stdout.startswith('Usage') or stdout == ''
121*2b949d04SAndroid Build Coastguard Worker        assert 'requires an argument' in stderr
122*2b949d04SAndroid Build Coastguard Worker
123*2b949d04SAndroid Build Coastguard Worker    def __str__(self):
124*2b949d04SAndroid Build Coastguard Worker        return str(self.subtool)
125*2b949d04SAndroid Build Coastguard Worker
126*2b949d04SAndroid Build Coastguard Worker
127*2b949d04SAndroid Build Coastguard Workerclass TestXkbcli(unittest.TestCase):
128*2b949d04SAndroid Build Coastguard Worker    @classmethod
129*2b949d04SAndroid Build Coastguard Worker    def setUpClass(cls):
130*2b949d04SAndroid Build Coastguard Worker        cls.xkbcli = XkbcliTool()
131*2b949d04SAndroid Build Coastguard Worker        cls.xkbcli_list = XkbcliTool('list', skipIf=(
132*2b949d04SAndroid Build Coastguard Worker            (not int(os.getenv('HAVE_XKBCLI_LIST', '1')), 'xkbregistory not enabled'),
133*2b949d04SAndroid Build Coastguard Worker        ))
134*2b949d04SAndroid Build Coastguard Worker        cls.xkbcli_how_to_type = XkbcliTool('how-to-type')
135*2b949d04SAndroid Build Coastguard Worker        cls.xkbcli_compile_keymap = XkbcliTool('compile-keymap')
136*2b949d04SAndroid Build Coastguard Worker        cls.xkbcli_interactive_evdev = XkbcliTool('interactive-evdev', skipIf=(
137*2b949d04SAndroid Build Coastguard Worker            (not int(os.getenv('HAVE_XKBCLI_INTERACTIVE_EVDEV', '1')), 'evdev not enabled'),
138*2b949d04SAndroid Build Coastguard Worker            (not os.path.exists('/dev/input/event0'), 'event node required'),
139*2b949d04SAndroid Build Coastguard Worker            (not os.access('/dev/input/event0', os.R_OK), 'insufficient permissions'),
140*2b949d04SAndroid Build Coastguard Worker        ), skipError=(
141*2b949d04SAndroid Build Coastguard Worker            (lambda rc, stdout, stderr: 'Couldn\'t find any keyboards' in stderr,
142*2b949d04SAndroid Build Coastguard Worker                'No keyboards available'),
143*2b949d04SAndroid Build Coastguard Worker        ),
144*2b949d04SAndroid Build Coastguard Worker        )
145*2b949d04SAndroid Build Coastguard Worker        cls.xkbcli_interactive_x11 = XkbcliTool('interactive-x11', skipIf=(
146*2b949d04SAndroid Build Coastguard Worker            (not int(os.getenv('HAVE_XKBCLI_INTERACTIVE_X11', '1')), 'x11 not enabled'),
147*2b949d04SAndroid Build Coastguard Worker            (not os.getenv('DISPLAY'), 'DISPLAY not set'),
148*2b949d04SAndroid Build Coastguard Worker        ))
149*2b949d04SAndroid Build Coastguard Worker        cls.xkbcli_interactive_wayland = XkbcliTool('interactive-wayland', skipIf=(
150*2b949d04SAndroid Build Coastguard Worker            (not int(os.getenv('HAVE_XKBCLI_INTERACTIVE_WAYLAND', '1')), 'wayland not enabled'),
151*2b949d04SAndroid Build Coastguard Worker            (not os.getenv('WAYLAND_DISPLAY'), 'WAYLAND_DISPLAY not set'),
152*2b949d04SAndroid Build Coastguard Worker        ))
153*2b949d04SAndroid Build Coastguard Worker        cls.all_tools = [
154*2b949d04SAndroid Build Coastguard Worker            cls.xkbcli,
155*2b949d04SAndroid Build Coastguard Worker            cls.xkbcli_list,
156*2b949d04SAndroid Build Coastguard Worker            cls.xkbcli_how_to_type,
157*2b949d04SAndroid Build Coastguard Worker            cls.xkbcli_compile_keymap,
158*2b949d04SAndroid Build Coastguard Worker            cls.xkbcli_interactive_evdev,
159*2b949d04SAndroid Build Coastguard Worker            cls.xkbcli_interactive_x11,
160*2b949d04SAndroid Build Coastguard Worker            cls.xkbcli_interactive_wayland,
161*2b949d04SAndroid Build Coastguard Worker        ]
162*2b949d04SAndroid Build Coastguard Worker
163*2b949d04SAndroid Build Coastguard Worker    def test_help(self):
164*2b949d04SAndroid Build Coastguard Worker        # --help is supported by all tools
165*2b949d04SAndroid Build Coastguard Worker        for tool in self.all_tools:
166*2b949d04SAndroid Build Coastguard Worker            with self.subTest(tool=tool):
167*2b949d04SAndroid Build Coastguard Worker                stdout, stderr = tool.run_command_success(['--help'])
168*2b949d04SAndroid Build Coastguard Worker                assert stdout.startswith('Usage:')
169*2b949d04SAndroid Build Coastguard Worker                assert stderr == ''
170*2b949d04SAndroid Build Coastguard Worker
171*2b949d04SAndroid Build Coastguard Worker    def test_invalid_option(self):
172*2b949d04SAndroid Build Coastguard Worker        # --foobar generates "Usage:" for all tools
173*2b949d04SAndroid Build Coastguard Worker        for tool in self.all_tools:
174*2b949d04SAndroid Build Coastguard Worker            with self.subTest(tool=tool):
175*2b949d04SAndroid Build Coastguard Worker                tool.run_command_unrecognized_option(['--foobar'])
176*2b949d04SAndroid Build Coastguard Worker
177*2b949d04SAndroid Build Coastguard Worker    def test_xkbcli_version(self):
178*2b949d04SAndroid Build Coastguard Worker        # xkbcli --version
179*2b949d04SAndroid Build Coastguard Worker        stdout, stderr = self.xkbcli.run_command_success(['--version'])
180*2b949d04SAndroid Build Coastguard Worker        assert stdout.startswith('1')
181*2b949d04SAndroid Build Coastguard Worker        assert stderr == ''
182*2b949d04SAndroid Build Coastguard Worker
183*2b949d04SAndroid Build Coastguard Worker    def test_xkbcli_too_many_args(self):
184*2b949d04SAndroid Build Coastguard Worker        self.xkbcli.run_command_invalid(['a'] * 64)
185*2b949d04SAndroid Build Coastguard Worker
186*2b949d04SAndroid Build Coastguard Worker    def test_compile_keymap_args(self):
187*2b949d04SAndroid Build Coastguard Worker        for args in (
188*2b949d04SAndroid Build Coastguard Worker            ['--verbose'],
189*2b949d04SAndroid Build Coastguard Worker            ['--rmlvo'],
190*2b949d04SAndroid Build Coastguard Worker            # ['--kccgst'],
191*2b949d04SAndroid Build Coastguard Worker            ['--verbose', '--rmlvo'],
192*2b949d04SAndroid Build Coastguard Worker            # ['--verbose', '--kccgst'],
193*2b949d04SAndroid Build Coastguard Worker        ):
194*2b949d04SAndroid Build Coastguard Worker            with self.subTest(args=args):
195*2b949d04SAndroid Build Coastguard Worker                self.xkbcli_compile_keymap.run_command_success(args)
196*2b949d04SAndroid Build Coastguard Worker
197*2b949d04SAndroid Build Coastguard Worker    def test_compile_keymap_rmlvo(self):
198*2b949d04SAndroid Build Coastguard Worker        for rmlvo in rmlvos:
199*2b949d04SAndroid Build Coastguard Worker            with self.subTest(rmlvo=rmlvo):
200*2b949d04SAndroid Build Coastguard Worker                self.xkbcli_compile_keymap.run_command_success(rmlvo)
201*2b949d04SAndroid Build Coastguard Worker
202*2b949d04SAndroid Build Coastguard Worker    def test_compile_keymap_include(self):
203*2b949d04SAndroid Build Coastguard Worker        for args in (
204*2b949d04SAndroid Build Coastguard Worker            ['--include', '.', '--include-defaults'],
205*2b949d04SAndroid Build Coastguard Worker            ['--include', '/tmp', '--include-defaults'],
206*2b949d04SAndroid Build Coastguard Worker        ):
207*2b949d04SAndroid Build Coastguard Worker            with self.subTest(args=args):
208*2b949d04SAndroid Build Coastguard Worker                # Succeeds thanks to include-defaults
209*2b949d04SAndroid Build Coastguard Worker                self.xkbcli_compile_keymap.run_command_success(args)
210*2b949d04SAndroid Build Coastguard Worker
211*2b949d04SAndroid Build Coastguard Worker    def test_compile_keymap_include_invalid(self):
212*2b949d04SAndroid Build Coastguard Worker        # A non-directory is rejected by default
213*2b949d04SAndroid Build Coastguard Worker        args = ['--include', '/proc/version']
214*2b949d04SAndroid Build Coastguard Worker        rc, stdout, stderr = self.xkbcli_compile_keymap.run_command(args)
215*2b949d04SAndroid Build Coastguard Worker        assert rc == 1, (stdout, stderr)
216*2b949d04SAndroid Build Coastguard Worker        assert "There are no include paths to search" in stderr
217*2b949d04SAndroid Build Coastguard Worker
218*2b949d04SAndroid Build Coastguard Worker        # A non-existing directory is rejected by default
219*2b949d04SAndroid Build Coastguard Worker        args = ['--include', '/tmp/does/not/exist']
220*2b949d04SAndroid Build Coastguard Worker        rc, stdout, stderr = self.xkbcli_compile_keymap.run_command(args)
221*2b949d04SAndroid Build Coastguard Worker        assert rc == 1, (stdout, stderr)
222*2b949d04SAndroid Build Coastguard Worker        assert "There are no include paths to search" in stderr
223*2b949d04SAndroid Build Coastguard Worker
224*2b949d04SAndroid Build Coastguard Worker        # Valid dir, but missing files
225*2b949d04SAndroid Build Coastguard Worker        args = ['--include', '/tmp']
226*2b949d04SAndroid Build Coastguard Worker        rc, stdout, stderr = self.xkbcli_compile_keymap.run_command(args)
227*2b949d04SAndroid Build Coastguard Worker        assert rc == 1, (stdout, stderr)
228*2b949d04SAndroid Build Coastguard Worker        assert "Couldn't look up rules" in stderr
229*2b949d04SAndroid Build Coastguard Worker
230*2b949d04SAndroid Build Coastguard Worker    def test_how_to_type(self):
231*2b949d04SAndroid Build Coastguard Worker        # Unicode codepoint conversions, we support whatever strtol does
232*2b949d04SAndroid Build Coastguard Worker        for args in (['123'], ['0x123'], ['0123']):
233*2b949d04SAndroid Build Coastguard Worker            with self.subTest(args=args):
234*2b949d04SAndroid Build Coastguard Worker                self.xkbcli_how_to_type.run_command_success(args)
235*2b949d04SAndroid Build Coastguard Worker
236*2b949d04SAndroid Build Coastguard Worker    def test_how_to_type_rmlvo(self):
237*2b949d04SAndroid Build Coastguard Worker        for rmlvo in rmlvos:
238*2b949d04SAndroid Build Coastguard Worker            with self.subTest(rmlvo=rmlvo):
239*2b949d04SAndroid Build Coastguard Worker                args = rmlvo + ['0x1234']
240*2b949d04SAndroid Build Coastguard Worker                self.xkbcli_how_to_type.run_command_success(args)
241*2b949d04SAndroid Build Coastguard Worker
242*2b949d04SAndroid Build Coastguard Worker    def test_list_rmlvo(self):
243*2b949d04SAndroid Build Coastguard Worker        for args in (
244*2b949d04SAndroid Build Coastguard Worker            ['--verbose'],
245*2b949d04SAndroid Build Coastguard Worker            ['-v'],
246*2b949d04SAndroid Build Coastguard Worker            ['--verbose', '--load-exotic'],
247*2b949d04SAndroid Build Coastguard Worker            ['--load-exotic'],
248*2b949d04SAndroid Build Coastguard Worker            ['--ruleset=evdev'],
249*2b949d04SAndroid Build Coastguard Worker            ['--ruleset=base'],
250*2b949d04SAndroid Build Coastguard Worker        ):
251*2b949d04SAndroid Build Coastguard Worker            with self.subTest(args=args):
252*2b949d04SAndroid Build Coastguard Worker                self.xkbcli_list.run_command_success(args)
253*2b949d04SAndroid Build Coastguard Worker
254*2b949d04SAndroid Build Coastguard Worker    def test_list_rmlvo_includes(self):
255*2b949d04SAndroid Build Coastguard Worker        args = ['/tmp/']
256*2b949d04SAndroid Build Coastguard Worker        self.xkbcli_list.run_command_success(args)
257*2b949d04SAndroid Build Coastguard Worker
258*2b949d04SAndroid Build Coastguard Worker    def test_list_rmlvo_includes_invalid(self):
259*2b949d04SAndroid Build Coastguard Worker        args = ['/proc/version']
260*2b949d04SAndroid Build Coastguard Worker        rc, stdout, stderr = self.xkbcli_list.run_command(args)
261*2b949d04SAndroid Build Coastguard Worker        assert rc == 1
262*2b949d04SAndroid Build Coastguard Worker        assert "Failed to append include path" in stderr
263*2b949d04SAndroid Build Coastguard Worker
264*2b949d04SAndroid Build Coastguard Worker    def test_list_rmlvo_includes_no_defaults(self):
265*2b949d04SAndroid Build Coastguard Worker        args = ['--skip-default-paths', '/tmp']
266*2b949d04SAndroid Build Coastguard Worker        rc, stdout, stderr = self.xkbcli_list.run_command(args)
267*2b949d04SAndroid Build Coastguard Worker        assert rc == 1
268*2b949d04SAndroid Build Coastguard Worker        assert "Failed to parse XKB description" in stderr
269*2b949d04SAndroid Build Coastguard Worker
270*2b949d04SAndroid Build Coastguard Worker    def test_interactive_evdev_rmlvo(self):
271*2b949d04SAndroid Build Coastguard Worker        for rmlvo in rmlvos:
272*2b949d04SAndroid Build Coastguard Worker            with self.subTest(rmlvo=rmlvo):
273*2b949d04SAndroid Build Coastguard Worker                self.xkbcli_interactive_evdev.run_command_success(rmlvo)
274*2b949d04SAndroid Build Coastguard Worker
275*2b949d04SAndroid Build Coastguard Worker    def test_interactive_evdev(self):
276*2b949d04SAndroid Build Coastguard Worker        # Note: --enable-compose fails if $prefix doesn't have the compose tables
277*2b949d04SAndroid Build Coastguard Worker        # installed
278*2b949d04SAndroid Build Coastguard Worker        for args in (
279*2b949d04SAndroid Build Coastguard Worker            ['--report-state-changes'],
280*2b949d04SAndroid Build Coastguard Worker            ['--enable-compose'],
281*2b949d04SAndroid Build Coastguard Worker            ['--consumed-mode=xkb'],
282*2b949d04SAndroid Build Coastguard Worker            ['--consumed-mode=gtk'],
283*2b949d04SAndroid Build Coastguard Worker            ['--without-x11-offset'],
284*2b949d04SAndroid Build Coastguard Worker        ):
285*2b949d04SAndroid Build Coastguard Worker            with self.subTest(args=args):
286*2b949d04SAndroid Build Coastguard Worker                self.xkbcli_interactive_evdev.run_command_success(args)
287*2b949d04SAndroid Build Coastguard Worker
288*2b949d04SAndroid Build Coastguard Worker    def test_interactive_x11(self):
289*2b949d04SAndroid Build Coastguard Worker        # To be filled in if we handle something other than --help
290*2b949d04SAndroid Build Coastguard Worker        pass
291*2b949d04SAndroid Build Coastguard Worker
292*2b949d04SAndroid Build Coastguard Worker    def test_interactive_wayland(self):
293*2b949d04SAndroid Build Coastguard Worker        # To be filled in if we handle something other than --help
294*2b949d04SAndroid Build Coastguard Worker        pass
295*2b949d04SAndroid Build Coastguard Worker
296*2b949d04SAndroid Build Coastguard Worker
297*2b949d04SAndroid Build Coastguard Workerif __name__ == '__main__':
298*2b949d04SAndroid Build Coastguard Worker    with tempfile.TemporaryDirectory() as tmpdir:
299*2b949d04SAndroid Build Coastguard Worker        # Use our own test xkeyboard-config copy.
300*2b949d04SAndroid Build Coastguard Worker        os.environ['XKB_CONFIG_ROOT'] = top_srcdir + '/test/data'
301*2b949d04SAndroid Build Coastguard Worker        # Use our own X11 locale copy.
302*2b949d04SAndroid Build Coastguard Worker        os.environ['XLOCALEDIR'] = top_srcdir + '/test/data/locale'
303*2b949d04SAndroid Build Coastguard Worker        # Use our own locale.
304*2b949d04SAndroid Build Coastguard Worker        os.environ['LC_CTYPE'] = 'en_US.UTF-8'
305*2b949d04SAndroid Build Coastguard Worker        # libxkbcommon has fallbacks when XDG_CONFIG_HOME isn't set so we need
306*2b949d04SAndroid Build Coastguard Worker        # to override it with a known (empty) directory. Otherwise our test
307*2b949d04SAndroid Build Coastguard Worker        # behavior depends on the system the test is run on.
308*2b949d04SAndroid Build Coastguard Worker        os.environ['XDG_CONFIG_HOME'] = tmpdir
309*2b949d04SAndroid Build Coastguard Worker        # Prevent the legacy $HOME/.xkb from kicking in.
310*2b949d04SAndroid Build Coastguard Worker        del os.environ['HOME']
311*2b949d04SAndroid Build Coastguard Worker        # This needs to be separated if we do specific extra path testing
312*2b949d04SAndroid Build Coastguard Worker        os.environ['XKB_CONFIG_EXTRA_PATH'] = tmpdir
313*2b949d04SAndroid Build Coastguard Worker
314*2b949d04SAndroid Build Coastguard Worker        unittest.main()
315