blob: 0aca9b7b418acbb7228d97e1677c0eceea03fe28 [file] [log] [blame]
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Tests keyboard pin connectivity in SMT factory test.
Unlike keyboard test, it only expects a key sequence where keys are the keyboard
scan lines' row-column crossing points. It also can trigger a SMT testing
fixture to send out signals to simulate key presses on the key sequence.
"""
from __future__ import print_function
import factory_common # pylint: disable=unused-import
from cros.factory.test.fixture import bft_fixture
from cros.factory.test import session
from cros.factory.test import test_case
from cros.factory.test.utils import evdev_utils
from cros.factory.utils.arg_utils import Arg
from cros.factory.external import evdev
class KeyboardSMTTest(test_case.TestCase):
"""Tests each keyboard scan lines are connected.
It triggers a keyboard scan module by sending 0xC1 to fixture via RS-232.
The keyboard scan module will send a sequence of keycodes. This test checks
if the upcoming keyup events match the expected keycode sequence.
"""
ARGS = [
Arg('device_filter', (int, str),
'Keyboard input event id or evdev name.',
default=None),
Arg('timeout_secs', int, 'Timeout for the test.', default=30),
Arg('keycode_sequence', list,
'Expected keycode sequence generated by a keyboard scan module in '
'the fixture.'),
Arg('bft_fixture', dict, bft_fixture.TEST_ARG_HELP, default=None),
Arg('debug', bool,
'True to disable timeout and never fail. Used to observe keystrokes.',
default=False)
]
def setUp(self):
self.debug = self.args.debug
self.expected_sequence = self.args.keycode_sequence
self.received_sequence = []
self.fixture = None
if self.args.bft_fixture:
self.fixture = bft_fixture.CreateBFTFixture(**self.args.bft_fixture)
# Get the keyboard input device.
self.event_dev = evdev_utils.FindDevice(self.args.device_filter,
evdev_utils.IsKeyboardDevice)
# Monitor keyboard event within specified time period.
self.event_dev.grab()
self.dispatcher = evdev_utils.InputDeviceDispatcher(
self.event_dev, self.event_loop.CatchException(self.HandleEvdevEvent))
self.dispatcher.StartDaemon()
self.UpdateUI()
def tearDown(self):
self.dispatcher.close()
self.event_dev.ungrab()
def UpdateUI(self):
expected_sequence = self.expected_sequence
if not self.debug:
expected_sequence = expected_sequence[len(self.received_sequence):]
self.ui.CallJSFunction('setMatchedSequence', self.received_sequence)
self.ui.CallJSFunction('setExpectedSequence', expected_sequence)
def HandleEvdevEvent(self, event):
"""Handles evdev event.
Args:
event: evdev event.
"""
if event.type == evdev.ecodes.EV_KEY and event.value == 0:
self.HandleKey(event.code)
def HandleKey(self, key):
"""Handles keyup event."""
if self.debug:
session.console.info('keycode: %s', key)
self.received_sequence.append(key)
else:
self.received_sequence.append(key)
if key != self.expected_sequence[len(self.received_sequence) - 1]:
self.FailTask('Keycode sequence mismatches. expected: %r, actual: %r.' %
(self.expected_sequence, self.received_sequence))
if self.received_sequence == self.expected_sequence:
self.PassTask()
self.UpdateUI()
def runTest(self):
if not self.debug:
self.ui.StartFailingCountdownTimer(self.args.timeout_secs)
if self.fixture:
self.fixture.SimulateKeystrokes()
self.WaitTaskEnd()