summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2021-04-15 10:39:05 +1000
committerRan Benita <ran@unusedvar.com>2021-04-20 10:30:17 +0300
commit1cae250052114250b641cbd55d1b9861e7f9084a (patch)
tree12751eebf831b114e205444f6a5f286aa2447b08
parent44e8d4b04484270df15c9615ceb1eb7451f6d0f7 (diff)
downloadxorg-lib-libxkbcommon-1cae250052114250b641cbd55d1b9861e7f9084a.tar.gz
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>
-rwxr-xr-xtest/xkeyboard-config-test.py.in185
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')