blob: 2ed5407172bd181d71a6d39b6f4c7b8aa25957c4 [file] [log] [blame]
# Copyright (c) 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 evdev
import unittest
import factory_common # pylint: disable=unused-import
from cros.factory.test import countdown_timer
from cros.factory.test import factory
from cros.factory.test.fixture import bft_fixture
from cros.factory.test.i18n import test_ui as i18n_test_ui
from cros.factory.test import test_ui
from cros.factory.test import ui_templates
from cros.factory.test.utils import evdev_utils
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import process_utils
_ID_CONTAINER = 'keyboard-test-container'
_ID_EXPECTED_SEQUENCE = 'expected-sequence'
_ID_MATCHED_SEQUENCE = 'matched-sequence'
_ID_COUNTDOWN_TIMER = 'keyboard-test-timer'
_MSG_EXPECTED_SEQUENCE = i18n_test_ui.MakeI18nLabelWithClass(
'Expected keycode sequence:', 'test-info')
_HTML_KEYBOARD = '<br>\n'.join([
'<div>%s <span id="%s"></span><span id="%s"></span></div>' % (
_MSG_EXPECTED_SEQUENCE, _ID_MATCHED_SEQUENCE, _ID_EXPECTED_SEQUENCE),
'<div id="%s" class="test-info"></div>' % _ID_COUNTDOWN_TIMER])
_KEYBOARD_TEST_DEFAULT_CSS = (
'.test-info { font-size: 1.4em; }\n'
'#expected-sequence { color: grey; font-size: 1.4em }\n'
'#matched-sequence { color: black; font-size: 1.4em }\n')
class KeyboardSMTTest(unittest.TestCase):
"""Tests each keyboard scan lines are connected.
It triggers akeyboard 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 matche the expected keycode sequence.
"""
ARGS = [
Arg(
'keyboard_event_id', int, 'Keyboard input event id.', default=None,
optional=True),
Arg('timeout_secs', int, 'Timeout for the test.', default=30),
Arg(
'keycode_sequence', tuple,
'Expected keycode sequence generated by a keyboard scan module in '
'the fixture.'),
Arg('bft_fixture', dict, bft_fixture.TEST_ARG_HELP, optional=True),
Arg(
'debug', bool,
'True to disable timeout and never fail. Used to observe keystrokes.',
default=False)]
def setUp(self):
self.ui = test_ui.UI()
self.template = ui_templates.OneSection(self.ui)
self.ui.AppendCSS(_KEYBOARD_TEST_DEFAULT_CSS)
# Initialize frontend presentation.
self.template.SetState(_HTML_KEYBOARD)
self.ui.CallJSFunction('setUpKeyboardTest', self.args.keycode_sequence,
self.args.debug)
self.fixture = None
if self.args.bft_fixture:
self.fixture = bft_fixture.CreateBFTFixture(**self.args.bft_fixture)
# Get the keyboard input device.
if self.args.keyboard_event_id is None:
keyboard_devices = evdev_utils.GetKeyboardDevices()
assert len(keyboard_devices) == 1, 'Multiple keyboards detected.'
self.event_dev = keyboard_devices[0]
else:
self.event_dev = evdev.InputDevice(
'/dev/input/event%d' % self.args.keyboard_event_id)
# Monitor keyboard event within specified time period.
self.event_dev.grab()
process_utils.StartDaemonThread(target=self.PollEvdevEvent)
if not self.args.debug:
countdown_timer.StartCountdownTimer(
self.args.timeout_secs, self.TimeoutHandler, self.ui,
_ID_COUNTDOWN_TIMER)
def tearDown(self):
self.event_dev.ungrab()
def TimeoutHandler(self):
"""Called to fail the test when a timeout is reached."""
self.ui.CallJSFunction(
'failTest',
'Timeout after %d seconds.' % self.args.timeout_secs)
def PollEvdevEvent(self):
"""Polls evdev event."""
for event in self.event_dev.read_loop():
self.HandleEvdevEvent(event)
def HandleEvdevEvent(self, event):
"""Handles evdev event.
Notifies JS if a keyup event is received.
Args:
event: evdev event.
"""
if event.type == evdev.ecodes.EV_KEY and event.value == 0:
if self.args.debug:
factory.console.info('keycode: %s', event.code)
self.ui.CallJSFunction('markKeyup', event.code)
def runTest(self):
if self.fixture:
self.fixture.SimulateKeystrokes()
self.ui.Run()