# Copyright (c) 2013 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 re

from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest


class firmware_ECHash(FirmwareTest):
    """
    Servo based EC hash recompute test.

    This test ensures that the AP will ask the EC to recompute the hash if
    the current hash isn't the right size/offset. Use the 'echash' command
    of EC tool to request the hash of some other part of EC EEPROM, then
    warm-reboot the AP and check what hash the EC has after booting.
    AP-RW should have requested the EC recompute the hash of EC-RW.
    """
    version = 1

    def initialize(self, host, cmdline_args):
        super(firmware_ECHash, self).initialize(host, cmdline_args)
        self.backup_firmware()
        self.switcher.setup_mode('normal')
        self.setup_usbkey(usbkey=False)
        self.setup_rw_boot()

    def cleanup(self):
        try:
            if self.is_firmware_saved():
                self.restore_firmware()
        except Exception as e:
            logging.error("Caught exception: %s", str(e))
        super(firmware_ECHash, self).cleanup()

    def get_echash(self):
        """Get the current EC hash via ectool/fwtool."""
        command = 'ectool echash'
        lines = self.faft_client.system.run_shell_command_get_output(command)
        pattern = re.compile('hash:    ([0-9a-f]{64})')
        for line in lines:
            matched = pattern.match(line)
            if matched:
                return matched.group(1)
        raise error.TestError("Wrong output of '%s': \n%s" %
                              (command, '\n'.join(lines)))

    def invalidate_echash(self):
        """Invalidate the EC hash by requesting hashing some other part."""
        command = 'ectool echash recalc 0 4'
        self.faft_client.system.run_shell_command(command)

    def save_echash_and_invalidate(self):
        """Save the current EC hash and invalidate it."""
        self.original_echash = self.get_echash()
        logging.info("Original EC hash: %s", self.original_echash)
        self.invalidate_echash()
        invalid_echash = self.get_echash()
        logging.info("Invalid EC hash: %s", invalid_echash)
        if invalid_echash == self.original_echash:
            raise error.TestFail("Failed to invalidate EC hash")

    def compare_echashes(self):
        """Compare the current EC with the original one."""
        recomputed_echash = self.get_echash()
        logging.info("Recomputed EC hash: %s", recomputed_echash)
        return recomputed_echash == self.original_echash

    def run_once(self):
        """Runs a single iteration of the test."""
        if not self.check_ec_capability():
            raise error.TestNAError("Nothing needs to be tested on this device")
        logging.info("Save the EC hash, invalidate it, and warm reboot.")
        self.save_echash_and_invalidate()
        self.switcher.mode_aware_reboot()

        logging.info("Compare the recomputed EC hash with the original one.")
        self.check_state(self.compare_echashes)
