blob: 6aee381c6ae84923438908db9b01c698359761a2 [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.
import logging
import os
import pyudev
import re
from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from collections import defaultdict
from operator import attrgetter
def natural_key(string_):
"""
Derive key for natural sorting.
@param string_: String to derive sort key for.
From http://stackoverflow.com/questions/34518/natural-sorting-algorithm.
"""
return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_)]
class platform_UdevVars(test.test):
"""Verify ChromeOS-specific udev variables."""
version = 1
def _input_devices(self):
"""Obtain a list of all /dev/input/event* udev devices."""
devices = self.udev.list_devices(subsystem='input')
# only consider the event devices
devices = filter(attrgetter('device_node'), devices)
devices = sorted(devices, key=lambda device: natural_key(device.device_node))
return devices
def _get_roles(self):
"""Get information on input devices and roles from udev."""
self.devices_with_role = defaultdict(list)
logging.debug('Input devices:')
for device in self._input_devices():
name = device.parent.attributes.get('name', '')
logging.debug(' %s [%s]', device.device_node, name)
role = device.get('POWERD_ROLE', None)
if role:
logging.debug(' POWERD_ROLE=%s', role)
self.devices_with_role[role].append(device)
def _dump_roles(self):
"""Log devices grouped by role for easier debugging."""
logging.info('Roles:')
for role in sorted(self.devices_with_role.keys()):
for device in self.devices_with_role[role]:
path = device.device_node
name = device.parent.attributes.get('name', '')
logging.info(' %-21s %s [%s]', role + ':', path, name)
def _dump_udev_attrs(self):
"""Log udev attributes for selected devices to the debug directory."""
for device in self._input_devices():
devname = os.path.basename(device.device_node)
outfile = os.path.join(self.debugdir, "udevattrs.%s" % devname)
utils.system('udevadm info --attribute-walk --path=%s > %s' % (
device.sys_path, outfile))
outfile = os.path.join(self.debugdir, "udevprops.%s" % devname)
utils.system('udevadm info --query=property --path=%s > %s' % (
device.sys_path, outfile))
def _verify_roles(self):
"""Verify that POWERD_ROLE was set on devices as expected."""
# TODO(chromium:410968): Consider moving this to USE flags instead of
# listing devices here.
boards_with_touchscreen = ['link', 'samus']
boards_maybe_touchscreen = ['rambi', 'peppy', 'glimmer', 'clapper',
'nyan_big', 'nyan_blaze', 'expresso']
boards_chromebox = ['beltino', 'guado', 'mccloud', 'panther', 'rikku',
'stumpy', 'tidus', 'tricky', 'zako']
boards_aio = ['nyan_kitty', 'tiny', 'anglar', 'monroe']
expect_keyboard = None
expect_touchpad = None
expect_touchscreen = None
board = utils.get_board()
if board in boards_chromebox or board in boards_aio:
expect_keyboard = [0]
expect_touchpad = [0]
else:
expect_keyboard = [1]
expect_touchpad = [1]
if board in boards_with_touchscreen:
expect_touchscreen = [1]
elif board in boards_maybe_touchscreen:
expect_touchscreen = [0, 1]
else:
expect_touchscreen = [0]
expected_num_per_role = [
('internal_keyboard', expect_keyboard),
('internal_touchpad', expect_touchpad),
('internal_touchscreen', expect_touchscreen),
]
for role, expected_num in expected_num_per_role:
num = len(self.devices_with_role[role])
if num not in expected_num:
self.errors += 1
logging.error('POWERD_ROLE=%s is present %d times, expected '
'one of %s', role, num, repr(expected_num))
if len(self.devices_with_role['external_input']) != 0:
logging.warn('%d external input devices detected',
len(self.devices_with_role['external_input']))
def initialize(self):
self.udev = pyudev.Context()
def run_once(self):
"""
Check that udev variables are assigned correctly by udev rules. In
particular, verifies that powerd tags are set correctly.
"""
logging.debug('Board: %s', utils.get_board())
self._get_roles()
self._dump_roles()
self._dump_udev_attrs()
self.errors = 0
self._verify_roles()
if self.errors != 0:
raise error.TestFail('Verification of udev variables failed; see '
'logs for details')