# Copyright 2020 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.


"""The autotest performing uart_stress_tester on EC uart port. """
import logging

from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.cr50_test import Cr50Test


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'

class firmware_Cr50CCDUartStress(Cr50Test):
    """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, full_args):
        """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.
        """
        super(firmware_Cr50CCDUartStress,
              self).initialize(host, cmdline_args, full_args)

        # Don't bother if there is no Chrome EC or if EC hibernate doesn't work.
        if not self.check_ec_capability():
            raise error.TestNAError('Nothing needs to be tested on this device')

        # Check EC chargen is available.
        if not self.ec.has_command(CHARGEN_CMD):
            raise error.TestNAError('chargen command is not available in EC.')
        logging.info('Checked EC has the uart command, %r.', CHARGEN_CMD)

        # Check CCD is in servo_type.
        servo_type = self.servo.get_servo_version()
        if 'ccd_cr50' not in servo_type:
            raise error.TestNAError('unsupported servo type: %s' % servo_type)
        logging.info('Checked the servo type is %r.', servo_type)

        # Fast open cr50 and enable testlab.
        self.fast_ccd_open(enable_testlab=True)
        logging.info('CCD opened.')

        # Change active device as ccd_cr50.
        if self.servo.has_control('active_v4_device'):
            try:
                self.active_dev = 'ccd_cr50'
                self.servo.set('active_v4_device', self.active_dev)
            except error.TestFail as e:
                raise error.TestNAError('cannot change active_v4_device: %s' %
                                        str(e))
            logging.info('Set the active v4 device as %r.', self.active_dev)
        else:
            self.active_dev = ''

        # Store the original status of EC ec3po_interp_connect.
        self.ec_ec3po_connect = self.servo.get('ec_ec3po_interp_connect',
                                               prefix=self.active_dev)
        # turn off EC ec3po_interp_connect
        self.servo.set('ec_ec3po_interp_connect', 'off', prefix=self.active_dev)
        logging.info('Turned off ec3po.')

    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, 'ec_ec3po_connect'):
                self.servo.set('ec_ec3po_interp_connect', self.ec_ec3po_connect,
                               prefix=self.active_dev)
            logging.info('Recovered ec3po.')
        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.
        logging.info('Start to stress cr50 with TPM commands.')
        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_ec_uart_pty', prefix=self.active_dev)
        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:
            raise error.TestFail('Uart stress tester failed.')

        logging.info('Uart stress tester passed.')
