# 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/power_override/flashrom.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 --flash-contents %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))
