blob: 7674e3c8081d67e431162ef67c205f581ae89490 [file] [log] [blame]
# Copyright 2020 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""The autotest performing uart_stress_tester on EC uart port. """
import logging
import re
from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
FLAG_FILENAME = '/tmp/chargen_testing'
# A ChromeOS TPM command to burden CR50.
TPM_CMD = ('trunks_client --stress_test')
# A command line to burden Cr50 with TPM_CMD as long as FLAG_FILENAME exists.
CR50_LOAD_GEN_CMD = 'while [ -f %s ]; do %s; done &' % (FLAG_FILENAME, TPM_CMD)
# Character generator
CHARGEN_CMD = 'chargen'
# The uart stress tester failure line will start with FAIL.
ERR_RE = r'(FAIL|ERROR).*'
class firmware_Cr50CCDUartStress(FirmwareTest):
"""A test that checks character loss with a UART and TPM stress workload."""
version = 1
flag_filename = '/tmp/chargen_testing'
def initialize(self, host, cmdline_args, use_ccd=False, console=''):
"""Initialize the test
Raises:
TestNAError: if the test environment is not properly set.
e.g. the servo type doesn't support this test, or
EC Uart command, chargen is not available.
"""
self.host = host
self.console = console
super(firmware_Cr50CCDUartStress,
self).initialize(host, cmdline_args)
# Don't bother if there is no Chrome EC or if EC hibernate doesn't work.
check_cap = getattr(self, 'check_%s_capability' % self.console, None)
if not check_cap or not check_cap():
raise error.TestNAError('Nothing needs to be tested on this device')
# Check EC chargen is available.
servo_console = getattr(self, console, None)
if not servo_console or not servo_console.has_command(CHARGEN_CMD):
raise error.TestNAError('chargen command is not available in %s.' %
console)
logging.info('Checked %s has the uart command, %r.', console, CHARGEN_CMD)
# Check CCD is in servo_type.
servo_type = self.servo.get_servo_version()
logging.info('Checked the servo type is %r.', servo_type)
if use_ccd:
if 'ccd' not in servo_type:
raise error.TestNAError('unsupported servo type: %s' % servo_type)
# Fast open cr50 and enable testlab.
self.fast_ccd_open(enable_testlab=True)
logging.info('CCD opened.')
# Change active device to the ccd device
if not self.servo.enable_ccd_servo_device():
raise error.TestNAError('Cannot make ccd active')
self.active_dev = self.servo.get_active_device_prefix()
self.interp_control = self.console + '_ec3po_interp_connect'
if self.active_dev:
self._interp_name = '%s.%s' % (self.active_dev,
self.interp_control)
else:
self._interp_name = self.interp_control
logging.info('Checking %s %s uart', self.servo.get_servo_version(True),
self.console)
logging.info('Device prefix %r', self.active_dev)
# Store the original status of EC ec3po_interp_connect.
self.ec3po_connect = self.servo.get(self.interp_control,
prefix=self.active_dev)
# turn off EC ec3po_interp_connect
self.servo.set(self.interp_control, 'off', prefix=self.active_dev)
logging.info('Turned off %s.', self._interp_name)
def cleanup(self):
"""Clean up Uart stress test, then cleanup Cr50Test"""
try:
# Terminate cr50 stressing command run.
self.host.run('rm -f ' + FLAG_FILENAME)
# Restore EC ec3po interpreter connect config.
if hasattr(self, '_interp_name'):
self.servo.set(self.interp_control, self.ec3po_connect,
prefix=self.active_dev)
logging.info('Recovered %s.', self._interp_name)
finally:
# Cleanup super class
super(firmware_Cr50CCDUartStress, self).cleanup()
def run_once(self, duration):
"""The method called by the control file to start the test.
Args:
duration: time in seconds to run uart_stress_tester.
Raises:
TestFail: uart_stress_tester returned non-zero exit code for
character loss or other reasons.
"""
# Run TPM command to stress cr50 in CPU.
self.host.run('touch ' + FLAG_FILENAME)
self.host.run('nohup sh -c %r &> /dev/null' % CR50_LOAD_GEN_CMD)
# Run uart_stress_tester.
uart_pty = self.servo.get('raw_%s_uart_pty' % self.console,
prefix=self.active_dev)
logging.info('PTY: %s', uart_pty)
testcmd = 'uart_stress_tester.py -t %d -d %s' % (duration, uart_pty)
logging.info('Run Uart stress tester for %d seconds.', duration)
logging.info(testcmd)
try:
self.servo.system(testcmd, timeout=duration*2)
except error.AutoservRunError as e:
msg = ''
if e and e.result_obj:
m = re.search(ERR_RE, e.result_obj.stderr)
if m:
err = m.group(0)
else:
# Use the error if 'FAIL', didn't show up in stderr.
err = e
msg = ' (%d): %r' % (e.result_obj.exit_status, err)
raise error.TestFail('Uart stress tester failed %s' % msg)
finally:
# Reboot the GSC to kill the chargen command on the EC.
self.gsc.reboot()
logging.info('Uart stress tester passed.')