# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import pprint

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


class firmware_Cr50CheckCap(Cr50Test):
    """Verify cr50 capabilities"""
    version = 1

    # The default requirements for these capabilities change between prod and
    # prepvt images. Make sure they match the expected values.
    SPECIAL_CAPS = ['OpenNoDevMode', 'OpenFromUSB']
    EXPECTED_REQ_PREPVT = 'Always'
    EXPECTED_REQ_PROD = 'IfOpened'

    def check_cap_command(self, enable_factory, reset_caps):
        """Verify the cr50 cap response after running the given command"""
        if enable_factory:
            self.gsc.ccd_reset_factory()
            self.servo.get_power_state_controller().reset()
        else:
            # Testlab mode is enabled, so it's ok to reset ccd without enabling
            # capabilities necessary for ccd.
            self.fast_ccd_open(True)
            self.gsc.ccd_reset(servo_en=False)
        caps = self.gsc.get_cap_dict()
        logging.info(caps)
        in_factory_mode, is_reset = self.gsc.get_cap_overview(caps)
        if reset_caps and not is_reset:
            raise error.TestFail('did not reset capabilities')
        if enable_factory and not in_factory_mode:
            raise error.TestFail('did not enable factory mode')


    def check_cap_req(self, cap_dict, cap, expected_req):
        """Check the current cap requirement against the expected requirement"""
        req = cap_dict[cap]
        if req != expected_req:
            raise error.TestFail('%r should be %r not %r' % (cap, expected_req,
                                                             req))


    def ccd_ec_uart_works(self):
        """Returns True if the CCD ec uart works."""
        logging.info('checking ec console')
        try:
            self.servo.get('ec_board', self._ec_prefix)
            logging.info('ccd ec console is responsive')
            return True
        except:
            logging.info('ccd ec console is unresponsive')
            return False


    def check_cap_accessiblity(self, ccd_level, cap_setting, expect_accessible):
        """Check setting cap requirements restricts the capabilities correctly.

        Set each ccd capability to cap_setting. Set the ccd state to ccd_level.
        Then verify the capability accessiblity matches expect_accessible.

        Args:
            ccd_level: a ccd state level: 'lock', 'unlock', or 'open'.
            cap_setting: A ccd cap setting: 'IfOpened', 'Always', 'Never', or
                         'UnlessLocked'.
            expect_accessible: True if capabilities should be accessible

        Raises:
            TestFail if expect_accessible doesn't match the accessibility state.
        """

        if (ccd_level == 'unlock' or cap_setting == 'UnlessLocked') \
            and not self.gsc.unlock_is_supported():
            return

        # Run testlab open, so we won't have to do physical presence stuff.
        self.gsc.send_command('ccd testlab open')

        # Set all capabilities to cap_setting
        caps = self.gsc.get_cap_dict().keys()
        cap_settings = {}
        for cap in caps:
            cap_settings[cap] = cap_setting
        self.gsc.set_caps(cap_settings)

        # Set the ccd state to ccd_level
        self.gsc.set_ccd_level(ccd_level, self.CCD_PASSWORD)
        cap_dict = self.gsc.get_cap_dict()
        logging.info('Cap state with console %r req %r:\n%s', ccd_level,
                     cap_setting, pprint.pformat(cap_dict))

        # Check the accessiblity
        for cap, cap_info in cap_dict.items():
            if cap_info[self.gsc.CAP_IS_ACCESSIBLE] != expect_accessible:
                raise error.TestFail('%r is %raccessible' % (cap,
                                     'not ' if expect_accessible else ''))

        if (self.check_ec_uart and
            expect_accessible != self.ccd_ec_uart_works()):
            raise error.TestFail('EC UART is %saccessible when it should%s be' %
                                 ('not ' if expect_accessible else '',
                                  '' if expect_accessible else "n't"))


    def run_once(self, ccd_open_restricted=False):
        """Check cr50 capabilities work correctly."""
        self.fast_ccd_open(enable_testlab=True)


        # Check servo monitoring before changing the active device. There's no
        # need for servo detection if ccd is the only device.
        servo_detect_ok = (self.servo.main_device_is_ccd()
                           or self.gsc.check_servo_monitor())

        set_ccd = self.servo.enable_ccd_servo_device()
        self._ec_prefix = self.servo.get_active_device_prefix()
        # Only check EC uart if the board has a working EC and cr50 can detect
        # servo connect/disconnect.
        self.check_ec_uart = (
                set_ccd and servo_detect_ok
                and self.check_ec_capability(suppress_warning=True)
                and self.servo.active_device_is_ccd()
                and self.servo.has_control('ec_board', self._ec_prefix))

        # Make sure factory reset sets all capabilities to Always
        self.check_cap_command(True, False)

        # Make sure ccd reset sets all capabilities to Default
        self.check_cap_command(False, True)

        expected_req = (self.EXPECTED_REQ_PROD if ccd_open_restricted else
                        self.EXPECTED_REQ_PREPVT)
        cap_dict = self.gsc.get_cap_dict(info=self.gsc.CAP_REQ)
        # Make sure the special ccd capabilities match ccd_open_restricted
        for cap in self.SPECIAL_CAPS:
            self.check_cap_req(cap_dict, cap, expected_req)

        # Set the password so we can change the ccd level from the console
        self.gsc.send_command('ccd testlab open')
        # Testlab mode is enabled, so it's ok to reset ccd without enabling
        # capabilities necessary for ccd.
        self.gsc.ccd_reset(servo_en=False)
        self.set_ccd_password(self.CCD_PASSWORD)

        # Make sure ccd accessiblity behaves as expected based on the cap
        # settings and the ccd state.
        self.check_cap_accessiblity('open', 'IfOpened', True)
        self.check_cap_accessiblity('open', 'UnlessLocked', True)
        self.check_cap_accessiblity('open', 'Always', True)

        self.check_cap_accessiblity('unlock', 'IfOpened', False)
        self.check_cap_accessiblity('unlock', 'UnlessLocked', True)
        self.check_cap_accessiblity('unlock', 'Always', True)

        self.check_cap_accessiblity('lock', 'IfOpened', False)
        self.check_cap_accessiblity('lock', 'UnlessLocked', False)
        self.check_cap_accessiblity('lock', 'Always', True)
