# Copyright 2015 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 time

from autotest_lib.client.common_lib import utils
from autotest_lib.server.cros import vboot_constants as vboot
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
from autotest_lib.server.cros.faft.firmware_test import ConnectionError


class firmware_ConsecutiveBoot(FirmwareTest):
    """
    Servo based consecutive boot test via power button to turn on DUT and
    /sbin/shutdown command to turn off DUT.

    This test is intended to be run with many iterations to ensure that the DUT
    does boot into Chrome OS and then does power off later.

    The iteration should be specified by the parameter -a "faft_iterations=10".
    """
    version = 1
    # Number of power button press to boot before declare test fail.
    POWER_ON_RETRY = 3


    def initialize(self, host, cmdline_args, dev_mode=False):
        # Parse arguments from command line
        dict_args = utils.args_to_dict(cmdline_args)
        self.faft_iterations = int(dict_args.get('faft_iterations', 1))
        self.faft_waitup_time = int(dict_args.get('faft_waitup_time', 0))
        self.faft_localrun = int(dict_args.get('faft_localrun', 0))
        super(firmware_ConsecutiveBoot, self).initialize(host, cmdline_args)
        self.switcher.setup_mode('dev' if dev_mode else 'normal',
                                 allow_gbb_force=True)
        if dev_mode:
            self.clear_set_gbb_flags(0, vboot.GBB_FLAG_DEV_SCREEN_SHORT_DELAY)
        self.setup_usbkey(usbkey=False)

    def wait_for_client_aux(self):
        """Use test specific timeout to wait for system to come up,
           otherwise use default (180s).
        """
        logging.info('wait_for_client %d start.', self.faft_waitup_time)
        if self.faft_waitup_time:
            self.switcher.wait_for_client(self.faft_waitup_time)
        else:
            self.switcher.wait_for_client()

    def shutdown_power_on(self):
        """
        Use /sbin/shutdown to turn off device follow by power button press to
        turn on device.  Do not want to call full_power_off_and_on since we
        are testing firmware and mainly want to focus on power on sequence.
        """
        boot_id = self.get_bootid()

        # Call shutdown instead of long press the power key, since we're
        # testing the firmware, not the power manager and button handling.
        logging.info("Sending /sbin/shutdown -P now")
        self.run_shutdown_cmd()
        logging.info('Wait for client to go offline')
        self.switcher.wait_for_client_offline(timeout=100, orig_boot_id=boot_id)
        if self.check_ec_capability(['x86'], suppress_warning=True):
            self.check_shutdown_power_state(
                    self.POWER_STATE_G3, pwr_retries=13, orig_boot_id=boot_id)

        # Retry in case power_short_press was not registered.
        for i in range(self.POWER_ON_RETRY):
            logging.info("sleep %d, tap power key to boot.",
                         self.faft_config.powerup_ready)
            time.sleep(self.faft_config.powerup_ready)
            self.servo.power_key(self.faft_config.hold_pwr_button_poweron)
            try:
                self.wait_for_client_aux()
            except ConnectionError:
                logging.error('wait_for_client exception %d.', i)
            else:
                logging.info('wait_for_client online done %d.', i)
                return
        raise ConnectionError()

    def cleanup(self):
        try:
            # Restore the GBB flag in developer mode test.
            self.clear_set_gbb_flags(vboot.GBB_FLAG_DEV_SCREEN_SHORT_DELAY, 0)
        except Exception as e:
            logging.error("Caught exception: %s", str(e))
        super(firmware_ConsecutiveBoot, self).cleanup()

    def run_once(self, host, dev_mode=False):
        """Runs a single iteration of the test."""
        for i in range(self.faft_iterations):
            logging.info('======== Running FAFT ITERATION %d/%s ========',
                         i+1, self.faft_iterations)
            logging.info("Expected boot fine, full power off DUT and on.")
            self.check_state((self.checkers.crossystem_checker, {
                        'mainfw_type': 'developer' if dev_mode else 'normal',
                        }))
            self.shutdown_power_on()

            logging.info("Expected boot fine.")
            self.check_state((self.checkers.crossystem_checker, {
                        'mainfw_type': 'developer' if dev_mode else 'normal',
                        }))
