# Copyright 2014 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 error
from autotest_lib.server import test


# Timeout for commands run on the host.
_COMMAND_TIMEOUT = 60

# Lock file created by flashrom to tell powerd not to suspend or shut down the
# system.
_LOCK_FILE = '/run/lock/flashrom_powerd.lock'

# Time in seconds to perform a flashrom write and to wait for the system to
# suspend and resume.
_SUSPEND_FLASHROM_SEC = 15
_SUSPEND_DOWN_SEC = 60
_SUSPEND_UP_SEC = 60

# Time in seconds to perform a flashrom write and to wait for the system to
# power down and reboot.
_REBOOT_FLASHROM_SEC = 15
_REBOOT_DOWN_SEC = 60
_REBOOT_UP_SEC = 60


class power_DeferForFlashrom(test.test):
    """Test that powerd defers suspend and shutdown for flashrom."""
    version = 1

    def initialize(self, host):
        """
        Initial settings before running test.

        @param host: Host/DUT object to use for test.
        """
        self.host = host


    def create_temp_file(self, base_name, source_path, size):
        """
        Create a temporary file on the host and returns its path.

        @param base_name: String containing the base name for the temp file.
        @param source_path: String containing the path to the device from
                which file contents should be read.
        @param size: Number of bytes to write to the file.
        """
        logging.info('Creating %d-byte temp file from %s', size, source_path)
        temp_file = self.host.run(
            'mktemp --tmpdir %s.XXXXXXXXXX' % base_name,
            timeout=_COMMAND_TIMEOUT).stdout.strip()
        self.host.run('dd if=%s of=%s bs=%d count=1 2>&1' %
            (source_path, temp_file, size))
        logging.info('Created %s', temp_file)
        return temp_file


    def run_in_background(self, cmd):
        """
        Asynchronously run a command on the host.

        @param cmd: Command to run (as a string).
        """
        bg_cmd = '(%s) </dev/null >/dev/null 2>&1 &' % (cmd)
        logging.info("Running %s", bg_cmd)
        self.host.run(bg_cmd, timeout=_COMMAND_TIMEOUT)


    def start_fake_flashrom_write(self, duration_sec):
        """
        Start a fake flashrom write.

        @param duration_sec: Duration for the write in seconds.
        """
        # flashrom simulates a 4096-byte block size, so the file size needs to
        # be a multiple of that.
        BLOCK_SIZE = 4096

        # flashrom will write one bit per cycle. Convert the block size to bits
        # (yielding the frequency for a one-second write) and then scale it as
        # needed.
        frequency_hz = int(BLOCK_SIZE * 8 / float(duration_sec))

        # To avoid flashrom needing to read (slowly) from the dummy device, pass
        # a custom diff file filled with zeroes.
        zero_file = self.create_temp_file(
            'power_DeferForFlashrom.zero', '/dev/zero', BLOCK_SIZE)
        rand_file = self.create_temp_file(
            'power_DeferForFlashrom.rand', '/dev/urandom', BLOCK_SIZE)

        # Start flashrom in the background and wait for it to create its lock
        # file.
        self.run_in_background(
            ('flashrom -w %s --diff %s --noverify '
             '-p dummy:freq=%d,emulate=VARIABLE_SIZE,size=%d,'
             'erase_to_zero=yes') %
            (rand_file, zero_file, frequency_hz, BLOCK_SIZE))

        logging.info("Waiting for flashrom to create %s...", _LOCK_FILE)
        self.host.run(
            'while [ ! -e %s ]; do sleep 0.1; done' % (_LOCK_FILE),
            timeout=_COMMAND_TIMEOUT)


    def send_suspend_request(self, wake_sec):
        """
        Asynchronously ask powerd to suspend the system immediately.

        @param wake_sec: Integer delay in seconds to use for setting a wake
                alarm. Note that the alarm starts when the request is sent to
                powerd, not when the system actually suspends.
        """
        self.run_in_background(
            'powerd_dbus_suspend --delay=0 --wakeup_timeout=%d' % (wake_sec))


    def send_reboot_request(self):
        """Ask powerd to reboot the system immediately."""
        logging.info('Calling powerd\'s RequestRestart method')
        self.host.run(
            ('dbus-send --type=method_call --system '
             '--dest=org.chromium.PowerManager /org/chromium/PowerManager '
             'org.chromium.PowerManager.RequestRestart'),
            timeout=_COMMAND_TIMEOUT)


    def wait_for_system_to_cycle(self, down_sec, up_sec):
        """
        Wait for the system to stop and then start responding to pings.

        @param down_sec: Maximum delay for the system to go down.
        @param up_sec: Maximum delay for the system to come back up.

        @return: Floating-point time when system went down.
        """
        logging.info("Waiting for host to go down...")
        if not self.host.ping_wait_down(timeout=down_sec):
            raise error.TestError(
                'System hasn\'t gone down after %d seconds' % (down_sec))
        down_timestamp = time.time()
        logging.info("System went down at %.2f", down_timestamp)

        logging.info("Waiting for host to come back up...")
        if not self.host.ping_wait_up(timeout=up_sec) or \
            not self.host.wait_up(timeout=up_sec):
            raise error.TestError('System didn\'t come back up')

        return down_timestamp


    def run_once(self):
        # Start flashrom and then request that the system be suspended. The
        # suspend should be deferred until flashrom finishes writing but should
        # happen eventually.
        flashrom_time = time.time()
        self.start_fake_flashrom_write(_SUSPEND_FLASHROM_SEC)
        self.send_suspend_request(_SUSPEND_DOWN_SEC)
        delay_sec = self.wait_for_system_to_cycle(
            _SUSPEND_DOWN_SEC, _SUSPEND_UP_SEC) - flashrom_time

        # Check that powerd waited for flashrom to finish.
        if delay_sec < _SUSPEND_FLASHROM_SEC:
            raise error.TestError(
                ('Suspend was blocked for %.2f sec; expected it to be blocked '
                 'for at least %d sec') % (delay_sec, _SUSPEND_FLASHROM_SEC))

        # Now do the same thing, but with a reboot request.
        flashrom_time = time.time()
        self.start_fake_flashrom_write(_REBOOT_FLASHROM_SEC)
        self.send_reboot_request()
        delay_sec = self.wait_for_system_to_cycle(
            _REBOOT_DOWN_SEC, _REBOOT_UP_SEC) - flashrom_time
        if delay_sec < _REBOOT_FLASHROM_SEC:
            raise error.TestError(
                ('Reboot was blocked for %.2f sec; expected it to be blocked '
                 'for at least %d sec') % (delay_sec, _REBOOT_FLASHROM_SEC))
