diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2021-04-15 10:39:05 +1000 |
---|---|---|
committer | Ran Benita <ran@unusedvar.com> | 2021-04-20 10:30:17 +0300 |
commit | 1cae250052114250b641cbd55d1b9861e7f9084a (patch) | |
tree | 12751eebf831b114e205444f6a5f286aa2447b08 /test | |
parent | 44e8d4b04484270df15c9615ceb1eb7451f6d0f7 (diff) | |
download | libxkbcommon-1cae250052114250b641cbd55d1b9861e7f9084a.tar.gz libxkbcommon-1cae250052114250b641cbd55d1b9861e7f9084a.tar.bz2 libxkbcommon-1cae250052114250b641cbd55d1b9861e7f9084a.zip |
test: rework the output for the xkeyboard-config layout tester
The previous output is largely unusable. The result in the CI test runs is a 6GB
file with every compiled keymap in it and while we can grep for ERROR, it's not
particularly useful.
Let's change this and print out YAML instead - that can be machine-processed.
This patch adds a new parent class that prints itself in YAML format,
the tool invocations are child classes of that class. The result looks like this:
Example output:
- rmlvo: ["evdev", "pc105", "us", "haw", "grp:rwin_switch"]
cmd: "xkbcli-compile-keymap --verbose --rules evdev --model pc105 --layout us --variant haw --options grp:rwin_switch"
status: 0
- rmlvo: ["evdev", "pc105", "us", "foo", ""]
cmd: "xkbcli-compile-keymap --verbose --rules evdev --model pc105 --layout us --variant foo"
status: 1
error: "failed to compile keymap"
Special status codes are: 99 for "unrecognized keysym" and 90 for "Cannot open
display" in the setxkbmap case.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'test')
-rwxr-xr-x | test/xkeyboard-config-test.py.in | 185 |
1 files changed, 111 insertions, 74 deletions
diff --git a/test/xkeyboard-config-test.py.in b/test/xkeyboard-config-test.py.in index 8c02125..cc53da4 100755 --- a/test/xkeyboard-config-test.py.in +++ b/test/xkeyboard-config-test.py.in @@ -1,11 +1,10 @@ #!/usr/bin/env python3 import argparse +import multiprocessing import sys import subprocess import os -import io import xml.etree.ElementTree as ET -from multiprocessing import Pool verbose = False @@ -37,13 +36,83 @@ def create_progress_bar(verbose): return progress_bar -def xkbcommontool(rmlvo): - try: - r = rmlvo.get('r', 'evdev') - m = rmlvo.get('m', 'pc105') - l = rmlvo.get('l', 'us') - v = rmlvo.get('v', None) - o = rmlvo.get('o', None) +class Invocation: + def __init__(self, r, m, l, v, o): + self.command = "" + self.rules = r + self.model = m + self.layout = l + self.variant = v + self.option = o + self.exitstatus = 77 # default to skipped + self.error = None + self.keymap = None # The fully compiled keymap + + @property + def rmlvo(self): + return self.rules, self.model, self.layout, self.variant, self.option + + def __str__(self): + s = [] + rmlvo = [x or "" for x in self.rmlvo] + rmlvo = ', '.join([f'"{x}"' for x in rmlvo]) + s.append(f'- rmlvo: [{rmlvo}]') + s.append(f' cmd: "{escape(self.command)}"') + s.append(f' status: {self.exitstatus}') + if self.error: + s.append(f' error: "{escape(self.error.strip())}"') + return '\n'.join(s) + + def run(self): + raise NotImplementedError + + +class XkbCompInvocation(Invocation): + def run(self): + r, m, l, v, o = self.rmlvo + args = ['setxkbmap', '-print'] + if r is not None: + args.append('-rules') + args.append('{}'.format(r)) + if m is not None: + args.append('-model') + args.append('{}'.format(m)) + if l is not None: + args.append('-layout') + args.append('{}'.format(l)) + if v is not None: + args.append('-variant') + args.append('{}'.format(v)) + if o is not None: + args.append('-option') + args.append('{}'.format(o)) + + xkbcomp_args = ['xkbcomp', '-xkb', '-', '-'] + + self.command = " ".join(args + ["|"] + xkbcomp_args) + + setxkbmap = subprocess.Popen(args, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, universal_newlines=True) + stdout, stderr = setxkbmap.communicate() + if "Cannot open display" in stderr: + self.error = stderr + self.exitstatus = 90 + else: + xkbcomp = subprocess.Popen(xkbcomp_args, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True) + stdout, stderr = xkbcomp.communicate(stdout) + if xkbcomp.returncode != 0: + self.error = "failed to compile keymap" + self.exitstatus = xkbcomp.returncode + else: + self.keymap = stdout + self.exitstatus = 0 + + +class XkbcommonInvocation(Invocation): + def run(self): + r, m, l, v, o = self.rmlvo args = [ 'xkbcli-compile-keymap', # this is run in the builddir '--verbose', @@ -56,28 +125,33 @@ def xkbcommontool(rmlvo): if o is not None: args += ['--options', o] - success = True - out = io.StringIO() - if verbose: - print(':: {}'.format(' '.join(args)), file=out) - + self.command = " ".join(args) try: output = subprocess.check_output(args, stderr=subprocess.STDOUT, universal_newlines=True) - if verbose: - print(output, file=out) - if "unrecognized keysym" in output: for line in output.split('\n'): if "unrecognized keysym" in line: - print('ERROR: {}'.format(line)) - success = False + self.error = line + self.exitstatus = 99 # tool doesn't generate this one + else: + self.exitstatus = 0 + self.keymap = output except subprocess.CalledProcessError as err: - print('ERROR: Failed to compile: {}'.format(' '.join(args)), file=out) - print(err.output, file=out) - success = False + self.error = "failed to compile keymap" + self.exitstatus = err.returncode - return success, out.getvalue() + +def xkbcommontool(rmlvo): + try: + r = rmlvo.get('r', 'evdev') + m = rmlvo.get('m', 'pc105') + l = rmlvo.get('l', 'us') + v = rmlvo.get('v', None) + o = rmlvo.get('o', None) + tool = XkbcommonInvocation(r, m, l, v, o) + tool.run() + return tool except KeyboardInterrupt: pass @@ -89,51 +163,9 @@ def xkbcomp(rmlvo): l = rmlvo.get('l', 'us') v = rmlvo.get('v', None) o = rmlvo.get('o', None) - args = ['setxkbmap', '-print'] - if r is not None: - args.append('-rules') - args.append('{}'.format(r)) - if m is not None: - args.append('-model') - args.append('{}'.format(m)) - if l is not None: - args.append('-layout') - args.append('{}'.format(l)) - if v is not None: - args.append('-variant') - args.append('{}'.format(v)) - if o is not None: - args.append('-option') - args.append('{}'.format(o)) - - success = True - out = io.StringIO() - if verbose: - print(':: {}'.format(' '.join(args)), file=out) - - try: - xkbcomp_args = ['xkbcomp', '-xkb', '-', '-'] - - setxkbmap = subprocess.Popen(args, stdout=subprocess.PIPE) - xkbcomp = subprocess.Popen(xkbcomp_args, stdin=setxkbmap.stdout, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=True) - setxkbmap.stdout.close() - stdout, stderr = xkbcomp.communicate() - if xkbcomp.returncode != 0: - print('ERROR: Failed to compile: {}'.format(' '.join(args)), file=out) - success = False - if xkbcomp.returncode != 0 or verbose: - print(stdout, file=out) - print(stderr, file=out) - - # This catches setxkbmap errors. - except subprocess.CalledProcessError as err: - print('ERROR: Failed to compile: {}'.format(' '.join(args)), file=out) - print(err.output, file=out) - success = False - - return success, out.getvalue() + tool = XkbCompInvocation(r, m, l, v, o) + tool.run() + return tool except KeyboardInterrupt: pass @@ -165,13 +197,18 @@ def parse(path): def run(combos, tool, njobs): failed = False - with Pool(njobs) as p: + with multiprocessing.Pool(njobs) as p: results = p.imap_unordered(tool, combos) - for success, output in progress_bar(results, total=len(combos)): - if not success: + for invocation in progress_bar(results, total=len(combos)): + if invocation.exitstatus != 0: failed = True - if output: - print(output, file=sys.stdout if success else sys.stderr) + target = sys.stderr + else: + target = sys.stdout if verbose else None + + if target: + print(invocation, file=target) + return failed @@ -214,4 +251,4 @@ if __name__ == '__main__': try: main(sys.argv) except KeyboardInterrupt: - print('Exiting after Ctrl+C') + print('# Exiting after Ctrl+C') |