diff options
-rwxr-xr-x | bin/multitap_test.py | 89 | ||||
-rwxr-xr-x | bin/network | 6 | ||||
-rwxr-xr-x | bin/network_predictable_names | 45 | ||||
-rwxr-xr-x | bin/pm_test | 116 | ||||
-rwxr-xr-x | bin/socketcan_test.py | 6 | ||||
-rwxr-xr-x | manage.py | 2 | ||||
-rw-r--r-- | units/cpu/jobs.pxu | 1 | ||||
-rw-r--r-- | units/graphics/jobs.pxu | 4 | ||||
-rw-r--r-- | units/networking/jobs.pxu | 7 | ||||
-rw-r--r-- | units/socketcan/jobs.pxu | 74 | ||||
-rw-r--r-- | units/socketcan/test-plan.pxu | 33 | ||||
-rw-r--r-- | units/stress/jobs.pxu | 4 | ||||
-rw-r--r-- | units/touchscreen/jobs.pxu | 26 |
13 files changed, 367 insertions, 46 deletions
diff --git a/bin/multitap_test.py b/bin/multitap_test.py new file mode 100755 index 0000000..15759cf --- /dev/null +++ b/bin/multitap_test.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +# Copyright 2018 Canonical Ltd. +# Written by: +# Maciej Kisielewski <maciej.kisielewski@canonical.com> + +""" +Run `xinput test-xi2` and monitor it for multifinger tap on a touchscreen. +""" + +import re +import subprocess +import sys + +EVENT_HEADER_RE = re.compile(r'^EVENT type (\d+) \((\w+)\)') + + +class Xi2Parser: + def __init__(self): + self._current_payload = '' + self._current_event = () + self._callbacks = dict() + + def register_callback(self, event_type, fn): + self._callbacks[event_type] = fn + + def parse_line(self, line): + if line.startswith(' '): + self._current_payload += line + else: + matches = EVENT_HEADER_RE.match(line) + if not matches: + return + if self._current_event: + self._emit_event() + self._current_event = (matches.groups()) + + def eof(self): + if self._current_event: + self._emit_event() + + def _emit_event(self): + event_data = dict() + for line in self._current_payload.split('\n'): + if ':' in line: + k, v = line.strip().split(':', 1) + event_data[k] = v + cb = self._callbacks.get(self._current_event[1]) + if cb: + cb(event_data) + self._current_payload = '' + self._current_event = () + + +def main(): + if len(sys.argv) != 2 or not sys.argv[1].isnumeric(): + raise SystemExit('Usage {} FINGER_COUNT'.format(sys.argv[0])) + print('Waiting for {}-finger tap'.format(sys.argv[1])) + + parser = Xi2Parser() + fingers = 0 + + def begin(ev): + nonlocal fingers + fingers += 1 + if fingers == int(sys.argv[1]): + print('SUCCESS! {}-finger tap detected!'.format(sys.argv[1])) + raise SystemExit(0) + + def end(ev): + nonlocal fingers + fingers -= 1 + if fingers < 0: + # it may happen if the program started with finger already touching + fingers = 0 + + parser.register_callback('TouchBegin', begin) + parser.register_callback('TouchEnd', end) + proc = subprocess.Popen( + ['xinput', 'test-xi2', '--root'], stdout=subprocess.PIPE) + while not proc.stdout.closed: + line = proc.stdout.readline().decode(sys.stdout.encoding) + if not line: + break + parser.parse_line(line) + parser.eof() + + +if __name__ == '__main__': + main() diff --git a/bin/network b/bin/network index 72df643..5e02690 100755 --- a/bin/network +++ b/bin/network @@ -112,7 +112,7 @@ class IPerfPerformanceTest(object): # time without timeout to catch devices that slow down, and also # not prematurely end iperf on low-bandwidth devices. self.timeout = 1080*int(self.data_size) - cmd = "timeout {} {} -c {} -n {}G -i 1 -f -m -P {}".format( + cmd = "timeout -k 1 {} {} -c {} -n {}G -i 1 -f -m -P {}".format( self.timeout, self.executable, self.target, self.data_size, threads) @@ -208,9 +208,9 @@ class StressPerformanceTest: def run(self): if self.iperf3: - iperf_cmd = 'timeout 320 iperf3 -c {} -t 300'.format(self.target) + iperf_cmd = 'timeout -k 1 320 iperf3 -c {} -t 300'.format(self.target) else: - iperf_cmd = 'timeout 320 iperf -c {} -t 300'.format(self.target) + iperf_cmd = 'timeout -k 1 320 iperf -c {} -t 300'.format(self.target) print("Running iperf...") iperf = subprocess.Popen(shlex.split(iperf_cmd)) diff --git a/bin/network_predictable_names b/bin/network_predictable_names new file mode 100755 index 0000000..20c52df --- /dev/null +++ b/bin/network_predictable_names @@ -0,0 +1,45 @@ +#!/bin/sh + +set -e + +# Script to verify that all network interfaces have predictable names +# +# Copyright (c) 2018 Canonical Ltd. +# +# Authors +# dann frazier <dann.frazier@canonical.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# The purpose of this script is to identify any network interfaces +# that do not have a predictable name. See: +# https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/ +# +# Usage: +# network_predictable_names +# +# Parameters: +# None + +failed=0 + +for iface in /sys/class/net/*; do + iface=${iface##*/} + + if [ "${iface}" != "${iface#eth}" ]; then + echo "** Error: Network interface $iface is not a predictable name" + failed=1 + fi +done + +exit $failed diff --git a/bin/pm_test b/bin/pm_test index 70cd121..dd9e1a0 100755 --- a/bin/pm_test +++ b/bin/pm_test @@ -66,8 +66,24 @@ def main(): title = '{0} test'.format(args.pm_operation.capitalize()) MessageDialog(title, message, Gtk.MessageType.ERROR).run() operation.teardown() - - return exception.RETURN_CODE + result = { + 'outcome': 'fail', + 'comment': message, + } + with open(os.path.join(args.log_dir, '__result'), 'wt') as f: + json.dump(result, f) + env = os.environ.copy() + # remove following envvars + for key in ['LD_LIBRARY_PATH', 'PYTHONPATH', 'PYTHONHOME']: + if key in env.keys(): + del env[key] + env['DISPLAY'] = ':0' + sudo_cmd = 'sudo -u {} bash -c "source {}; exec bash"'.format( + operation.user, args.checkbox_respawn_cmd) + args = ['x-terminal-emulator', '-e', sudo_cmd] + print("\nCheckbox will resume in another window.") + print("It's safe to close this one.", flush=True) + os.execvpe('x-terminal-emulator', args, env) return 0 @@ -80,11 +96,19 @@ class PowerManagementOperation(): self.extra_args = extra_args self.user = user self.dry_run = dry_run + self.hw_list_start = os.path.join( + self.args.log_dir, 'hardware.at_start') def setup(self): """ Enable configuration file """ + if self.args.check_hardware_list: + if not os.path.exists(self.hw_list_start): + # create baseline list once per session + with open(self.hw_list_start, 'wt') as f: + f.write(self.get_hw_list()) + # Enable autologin and sudo on first cycle if self.args.total == self.args.repetitions: AutoLoginConfigurator(user=self.user).enable() @@ -111,6 +135,8 @@ class PowerManagementOperation(): self.run_suspend_cycles(self.args.suspends_before_reboot, self.args.fwts) self.run_pm_command() + if self.args.check_hardware_list: + self.check_hw_list() else: self.summary() @@ -223,28 +249,30 @@ class PowerManagementOperation(): message = ('{0} test complete' .format(self.args.pm_operation.capitalize())) - total_suspends_expected = ( - self.args.suspends_before_reboot * self.args.total) - problems = '' - fwts_log_path = os.path.join(self.args.log_dir, 'fwts.log') - try: - with open(fwts_log_path, 'rt') as f: - magic_line = 'Completed S3 cycle(s) \n' - count = f.readlines().count(magic_line) - if count != total_suspends_expected: - problems = ( - "Found {} occurrences of '{}'. Expected {}".format( - count, magic_line.strip(), - total_suspends_expected)) - except FileNotFoundError: - problems = "Error opening {}".format(fwts_log_path) - if problems: - result = { - 'outcome': 'fail' if problems else 'pass', - 'comment': problems, - } - with open(os.path.join(self.args.log_dir, '__result'), 'wt') as f: - json.dump(result, f) + if self.args.suspends_before_reboot: + total_suspends_expected = ( + self.args.suspends_before_reboot * self.args.total) + problems = '' + fwts_log_path = os.path.join(self.args.log_dir, 'fwts.log') + try: + with open(fwts_log_path, 'rt') as f: + magic_line = 'Completed S3 cycle(s) \n' + count = f.readlines().count(magic_line) + if count != total_suspends_expected: + problems = ( + "Found {} occurrences of '{}'. Expected {}".format( + count, magic_line.strip(), + total_suspends_expected)) + except FileNotFoundError: + problems = "Error opening {}".format(fwts_log_path) + if problems: + result = { + 'outcome': 'fail' if problems else 'pass', + 'comment': problems, + } + result_filename = os.path.join(self.args.log_dir, '__result') + with open(result_filename, 'wt') as f: + json.dump(result, f) if self.args.silent: logging.info(message) @@ -271,6 +299,35 @@ class PowerManagementOperation(): SudoersConfigurator().disable() AutoLoginConfigurator().disable() + def get_hw_list(self): + try: + content = subprocess.check_output( + 'lspci', encoding=sys.stdout.encoding) + content += subprocess.check_output( + 'lsusb', encoding=sys.stdout.encoding) + return content + except subprocess.CalledProcessError as exc: + logging.warning("Problem running lspci or lsusb: %s", exc) + return '' + + def check_hw_list(self): + with open(self.hw_list_start, 'rt') as f: + before = set(f.read().split('\n')) + after = set(self.get_hw_list().split('\n')) + if after != before: + message = "Hardware changed!" + only_before = before - after + if only_before: + message += "\nHardware lost after pm operation:" + for item in sorted(list(only_before)): + message += '\n\t{}'.format(item) + only_after = after - before + if only_after: + message += "\nNew hardware found after pm operation:" + for item in sorted(list(only_after)): + message += '\n\t{}'.format(item) + raise TestFailed(message) + class TestCancelled(Exception): RETURN_CODE = 1 @@ -703,7 +760,7 @@ class AutoStartFile(): [Desktop Entry] Name={pm_operation} test Comment=Verify {pm_operation} works properly -Exec=sudo {script} -r {repetitions} -w {wakeup} --hardware-delay {hardware_delay} --pm-delay {pm_delay} --min-pm-time {min_pm_time} --max-pm-time {max_pm_time} --append --total {total} --start {start} --pm-timestamp {pm_timestamp} {silent} --log-level={log_level} --log-dir={log_dir} --suspends-before-reboot={suspend_cycles} --checkbox-respawn-cmd={checkbox_respawn} {fwts} {pm_operation} +Exec=sudo {script} -r {repetitions} -w {wakeup} --hardware-delay {hardware_delay} --pm-delay {pm_delay} --min-pm-time {min_pm_time} --max-pm-time {max_pm_time} --append --total {total} --start {start} --pm-timestamp {pm_timestamp} {silent} --log-level={log_level} --log-dir={log_dir} --suspends-before-reboot={suspend_cycles} --checkbox-respawn-cmd={checkbox_respawn} {check_hardware} {fwts} {pm_operation} Type=Application X-GNOME-Autostart-enabled=true Hidden=false @@ -761,7 +818,11 @@ Hidden=false fwts='--fwts' if self.args.fwts else '', suspend_cycles=self.args.suspends_before_reboot, pm_operation=self.args.pm_operation, - checkbox_respawn=self.args.checkbox_respawn_cmd)) + checkbox_respawn=self.args.checkbox_respawn_cmd, + check_hardware='--check-hardware-list' if + self.args.check_hardware_list else '', + ) + ) logging.debug(contents) with open(self.desktop_filename, 'w') as f: @@ -902,6 +963,9 @@ class MyArgumentParser(): parser.add_argument('--checkbox-respawn-cmd', type=str, help=( 'path to a file telling how to return to checkbox after the' ' test is done'), default='') + parser.add_argument('--check-hardware-list', action='store_true', + help=('Look for changes in the list of devices ' + 'after each PM action'), default=False) self.parser = parser def parse(self): diff --git a/bin/socketcan_test.py b/bin/socketcan_test.py index 232fc2c..25c79b2 100755 --- a/bin/socketcan_test.py +++ b/bin/socketcan_test.py @@ -92,12 +92,12 @@ class CANSocket(): self.sock.send(can_pkt) def recv(self): - if self._fdmode: - can_pkt = self.sock.recv(self.CANFD_MTU) + can_pkt = self.sock.recv(self.CANFD_MTU) + nbytes = len(can_pkt) + if nbytes == self.CANFD_MTU: can_id, length, fd_flags, data = struct.unpack(self.FD_FORMAT, can_pkt) else: - can_pkt = self.sock.recv(self.CAN_MTU) can_id, length, data = struct.unpack(self.FORMAT, can_pkt) can_id &= socket.CAN_EFF_MASK return (can_id, data[:length]) @@ -5,7 +5,7 @@ from plainbox.provider_manager import N_ setup( name='plainbox-provider-checkbox', namespace='com.canonical.certification', - version="0.46.0rc1", + version="0.46.0rc2", description=N_("Checkbox provider"), gettext_domain='plainbox-provider-checkbox', strict=False, deprecated=False, diff --git a/units/cpu/jobs.pxu b/units/cpu/jobs.pxu index a64757e..5cd80a0 100644 --- a/units/cpu/jobs.pxu +++ b/units/cpu/jobs.pxu @@ -152,6 +152,7 @@ plugin: attachment category_id: com.canonical.plainbox::cpu estimated_duration: 0.5 id: cpu/cstates_results.log +after: cpu/cstates command: [ -e ${PLAINBOX_SESSION_SHARE}/fwts_cstates_results.log ] && cat ${PLAINBOX_SESSION_SHARE}/fwts_cstates_results.log _summary: diff --git a/units/graphics/jobs.pxu b/units/graphics/jobs.pxu index 88efe86..40f7299 100644 --- a/units/graphics/jobs.pxu +++ b/units/graphics/jobs.pxu @@ -250,7 +250,7 @@ _description: 1. Click "Test" to test display rotation. The display will be rotated every 4 seconds. 2. Check if all rotations (normal right inverted left) took place without permanent screen corruption VERIFICATION: - Did the display rotation take place without without permanent screen corruption? + Did the display rotation take place without permanent screen corruption? unit: template template-resource: graphics_card @@ -456,7 +456,7 @@ plugin: manual category_id: com.canonical.plainbox::graphics id: graphics/{index}_switch_card_{product_slug}_xenial requires: - graphics_card.driver in ['nouveau', 'nvidia', 'amdgpu-pro'] + graphics_card.driver in ['nouveau', 'nvidia', 'amdgpu-pro', 'pcieport'] lsb.codename == 'xenial' _summary: Test GPU switching for {vendor} {product} _description: diff --git a/units/networking/jobs.pxu b/units/networking/jobs.pxu index 92eadd4..360aaf2 100644 --- a/units/networking/jobs.pxu +++ b/units/networking/jobs.pxu @@ -77,3 +77,10 @@ requires: package.name == 'cups-client' command: network_printer_test -s $CHECKBOX_SERVER _description: Try to enable a remote printer on the network and print a test page. +plugin: shell +category_id: com.canonical.plainbox::networking +id: networking/predictable_names +command: network_predictable_names +_summary: Verify that all network interfaces have predictable names. +_description: Verify that all network interfaces have predictable names. + diff --git a/units/socketcan/jobs.pxu b/units/socketcan/jobs.pxu index 0bf22a1..74fd8ca 100644 --- a/units/socketcan/jobs.pxu +++ b/units/socketcan/jobs.pxu @@ -16,7 +16,6 @@ command: if ! ip link show vcan0 &> /dev/null ; then ip link add vcan0 type vcan fi - ip link set vcan0 up id: socketcan/send_packet_local_sff_virtual @@ -28,8 +27,15 @@ _description: the broadcast packet is received on the same device category_id: socketcan plugin: shell +user: root estimated_duration: 2.0 +flags: also-after-suspend command: + BASH_XTRACEFD=1 + set -ex + ip link set vcan0 down + ip link set dev vcan0 mtu 16 + ip link set vcan0 up socketcan_test.py vcan0 111 @@ -42,8 +48,15 @@ _description: the broadcast packet is received on the same device category_id: socketcan plugin: shell +user: root estimated_duration: 2.0 +flags: also-after-suspend command: + BASH_XTRACEFD=1 + set -ex + ip link set vcan0 down + ip link set dev vcan0 mtu 16 + ip link set vcan0 up socketcan_test.py vcan0 1F334455 --effid @@ -56,8 +69,15 @@ _description: the broadcast packet is received on the same device category_id: socketcan plugin: shell +user: root estimated_duration: 2.0 +flags: also-after-suspend command: + BASH_XTRACEFD=1 + set -ex + ip link set vcan0 down + ip link set dev vcan0 mtu 72 + ip link set vcan0 up socketcan_test.py vcan0 1A --fdmode @@ -71,10 +91,17 @@ _description: local test as the broadcast packet is received on the same device category_id: socketcan plugin: shell +user: root estimated_duration: 2.0 +flags: also-after-suspend imports: from com.canonical.plainbox import manifest requires: manifest.socket_can_echo_server_running == 'False' command: + BASH_XTRACEFD=1 + set -ex + ip link set {interface} down + ip link set dev {interface} mtu 16 + ip link set {interface} up socketcan_test.py {interface} 111 @@ -88,10 +115,17 @@ _description: local test as the broadcast packet is received on the same device category_id: socketcan plugin: shell +user: root estimated_duration: 2.0 +flags: also-after-suspend imports: from com.canonical.plainbox import manifest requires: manifest.socket_can_echo_server_running == 'False' command: + BASH_XTRACEFD=1 + set -ex + ip link set {interface} down + ip link set dev {interface} mtu 16 + ip link set {interface} up socketcan_test.py {interface} FA123 --effid @@ -105,10 +139,19 @@ _description: local test as the broadcast packet is received on the same device category_id: socketcan plugin: shell +user: root estimated_duration: 2.0 +flags: also-after-suspend imports: from com.canonical.plainbox import manifest requires: manifest.socket_can_echo_server_running == 'False' command: + BASH_XTRACEFD=1 + set -ex + ip link set {interface} down + # Following command is only supported configuration method when using the + # IXXAT driver from HMS + ip link set {interface} type can bitrate 1000000 dbitrate 2000000 fd on + ip link set {interface} up socketcan_test.py {interface} 1B --fdmode @@ -123,10 +166,20 @@ _description: as to return the predicted packet. category_id: socketcan plugin: shell +user: root estimated_duration: 5.0 +flags: also-after-suspend imports: from com.canonical.plainbox import manifest requires: manifest.socket_can_echo_server_running == 'True' command: + BASH_XTRACEFD=1 + set -ex + ip link set {interface} down + # Following command is only supported configuration method when using the + # IXXAT driver from HMS + ip link set {interface} type can bitrate 1000000 + ip link set dev {interface} mtu 16 + ip link set {interface} up socketcan_test.py {interface} 111 --remote @@ -141,10 +194,20 @@ _description: as to return the predicted packet. category_id: socketcan plugin: shell +user: root estimated_duration: 5.0 +flags: also-after-suspend imports: from com.canonical.plainbox import manifest requires: manifest.socket_can_echo_server_running == 'True' command: + BASH_XTRACEFD=1 + set -ex + ip link set {interface} down + # Following command is only supported configuration method when using the + # IXXAT driver from HMS + ip link set {interface} type can bitrate 1000000 + ip link set dev {interface} mtu 16 + ip link set {interface} up socketcan_test.py {interface} E407DB --remote --effid @@ -159,8 +222,17 @@ _description: as to return the predicted packet. category_id: socketcan plugin: shell +user: root estimated_duration: 5.0 +flags: also-after-suspend imports: from com.canonical.plainbox import manifest requires: manifest.socket_can_echo_server_running == 'True' command: + BASH_XTRACEFD=1 + set -ex + ip link set {interface} down + # Following command is only supported configuration method when using the + # IXXAT driver from HMS + ip link set {interface} type can bitrate 1000000 dbitrate 2000000 fd on + ip link set {interface} up socketcan_test.py {interface} 19F --remote --fdmode diff --git a/units/socketcan/test-plan.pxu b/units/socketcan/test-plan.pxu index c4e343e..0e60f3b 100644 --- a/units/socketcan/test-plan.pxu +++ b/units/socketcan/test-plan.pxu @@ -8,15 +8,33 @@ include: socketcan/send_packet_remote_.* +id: after-suspend-socketcan-auto-remote +unit: test plan +_name: SocketCAN Tests (Automated, Remote, After Suspend) +_description: + SocketCAN Tests (Automated, Remote, After Suspend) +include: + after-suspend-socketcan/send_packet_remote_.* + + id: socketcan-auto-local unit: test plan -_name: SocketCAN Tests, (Automated, Local) +_name: SocketCAN Tests (Automated, Local) _description: - SocketCAN Tests, (Automated, Local) + SocketCAN Tests (Automated, Local) include: socketcan/send_packet_local_.* +id: after-suspend-socketcan-auto-local +unit: test plan +_name: SocketCAN Tests (Automated, Local, After Suspend) +_description: + SocketCAN Tests (Automated, Local, After Suspend) +include: + after-suspend-socketcan/send_packet_local_.* + + id: socketcan-full unit: test plan _name: SocketCAN Tests @@ -26,3 +44,14 @@ include: nested_part: socketcan-auto-remote socketcan-auto-local + + +id: after-suspend-socketcan-full +unit: test plan +_name: SocketCAN Tests (After Suspend) +_description: + SocketCAN Tests (After Suspend) +include: +nested_part: + after-suspend-socketcan-auto-remote + after-suspend-socketcan-auto-local diff --git a/units/stress/jobs.pxu b/units/stress/jobs.pxu index e0c2e0a..261a0a3 100644 --- a/units/stress/jobs.pxu +++ b/units/stress/jobs.pxu @@ -78,7 +78,7 @@ flags: noreturn user: root environ: PM_TEST_DRY_RUN command: - pm_test reboot --checkbox-respawn-cmd $PLAINBOX_SESSION_SHARE/__respawn_checkbox --fwts --log-level=debug --log-dir=$PLAINBOX_SESSION_SHARE --suspends-before-reboot=30 -r 3 --silent + pm_test reboot --checkbox-respawn-cmd $PLAINBOX_SESSION_SHARE/__respawn_checkbox --fwts --log-level=debug --log-dir=$PLAINBOX_SESSION_SHARE --suspends-before-reboot=30 -r 3 --silent --check-hardware-list _description: This is an automated stress test that will run a sequence of '30 suspend/resume cycles and one reboot' 3 times. @@ -94,7 +94,7 @@ user: root command: if type -P fwts >/dev/null; then echo "Calling fwts" - set -o pipefail; checkbox-support-fwts_test -l $PLAINBOX_SESSION_SHARE/suspend_30_cycles -f none -s s3 --s3-device-check --s3-device-check-delay=45 --s3-sleep-delay=30 --s3-multiple=30 | tee $PLAINBOX_SESSION_SHARE/suspend_30_cycles_times.log + set -o pipefail; checkbox-support-fwts_test -l $PLAINBOX_SESSION_SHARE/suspend_30_cycles -f none -s s3 --s3-device-check --s3-device-check-delay=60 --s3-sleep-delay=60 --s3-multiple=30 | tee $PLAINBOX_SESSION_SHARE/suspend_30_cycles_times.log else echo "Calling sleep_test" set -o pipefail; sleep_test -p -s mem -i 30 | tee $PLAINBOX_SESSION_SHARE/suspend_30_cycles.log diff --git a/units/touchscreen/jobs.pxu b/units/touchscreen/jobs.pxu index 98a2d4f..225c168 100644 --- a/units/touchscreen/jobs.pxu +++ b/units/touchscreen/jobs.pxu @@ -135,19 +135,27 @@ _description: Validate that 3-touch tap is operating as expected STEPS: 1. Commence the test + {%- if 'Unity' in __system_env__["XDG_CURRENT_DESKTOP"] %} 2. Tap the screen within the test area with 3 fingers simultaneously. 3. Once 3 fingers are on the screen you should see the indicator they are recognized. VERIFICATION: Did you see the green circles around the three fingers? + {%- else %} + 2. Tap the screen with 3 fingers simultaneously. + 3. If the tap is not detected the test will time out after 20 seconds. + VERIFICATION: + Was the tap detected? + {% endif %} command: - {%- if __system_env__["XDG_CURRENT_DESKTOP"] == 'Unity' %} + {%- if 'Unity' in __system_env__["XDG_CURRENT_DESKTOP"] %} manage_compiz_plugin unityshell disable - {% endif %} qmlscene -qt5 3 $PLAINBOX_PROVIDER_DATA/touch_tap_test.qml 2>&1 | grep -o PASS EXIT=$? sleep 5 - {%- if __system_env__["XDG_CURRENT_DESKTOP"] == 'Unity' %} manage_compiz_plugin unityshell enable + {%- else %} + timeout 20 multitap_test.py 3 || (>&2 echo "FAILED TO DETECT TAP"; false) + EXIT=$? {% endif %} exit $EXIT @@ -163,18 +171,24 @@ _description: Validate that 4-touch tap is operating as expected STEPS: 1. Commence the test + {%- if 'Unity' in __system_env__["XDG_CURRENT_DESKTOP"] %} 2. Tap the screen within the test area with 4 fingers simultaneously. 3. Once 4 fingers are on the screen you should see the indicator they are recognized. VERIFICATION: Did you see the green circles around the four fingers? + {%- else %} + 2. Tap the screen with 4 fingers simultaneously. + 3. If the tap is not detected the test will time out after 20 seconds. + {% endif %} command: - {%- if __system_env__["XDG_CURRENT_DESKTOP"] == 'Unity' %} + {%- if 'Unity' in __system_env__["XDG_CURRENT_DESKTOP"] %} manage_compiz_plugin unityshell disable - {% endif %} qmlscene -qt5 4 $PLAINBOX_PROVIDER_DATA/touch_tap_test.qml 2>&1 | grep -o PASS EXIT=$? sleep 5 - {%- if __system_env__["XDG_CURRENT_DESKTOP"] == 'Unity' %} manage_compiz_plugin unityshell enable + {%- else %} + timeout 20 multitap_test.py 4 || (>&2 echo "FAILED TO DETECT TAP"; false) + EXIT=$? {% endif %} exit $EXIT |