import os, logging

from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error, autotemp
from autotest_lib.client.cros import storage as storage_mod
from autotest_lib.client.cros.power import power_status


class hardware_MultiReaderPowerConsumption(storage_mod.StorageTester):
    version = 1
    _files_to_delete = []
    _ramdisk_path = None
    _storage = None


    def initialize(self):
        super(hardware_MultiReaderPowerConsumption, self).initialize()

        # Make sure we're not on AC power
        self.status = power_status.get_status()
        if self.status.on_ac():
            raise error.TestNAError(
                  'This test needs to be run with the AC power offline')


    def cleanup(self):
        # Remove intermediate files
        for path in self._files_to_delete:
            utils.system('rm -f %s' % path)

        if self._storage and os.path.ismount(self._storage['mountpoint']):
            self.scanner.umount_volume(storage_dict=self._storage)

        if self._ramdisk_path and os.path.ismount(self._ramdisk_path.name):
            umount_ramdisk(self._ramdisk_path.name)
            self._ramdisk_path.clean()

        super(hardware_MultiReaderPowerConsumption, self).cleanup()


    def readwrite_test(self, path, size, delete_file=False):
        """Heavy-duty random read/write test. Run `dd` & `tail -f` in parallel

        The random write is done by writing a file from /dev/urandom into the
        given location, while the random read is done by concurrently reading
        that file.

        @param path: The directory that will create the test file.
        @param size: Size of the test file, in MiB.
        @param delete_file: Flag the file to be deleted on test exit.
               Otherwise file deletion won't be performed.
        """
        # Calculate the parameters for dd
        size = 1024*1024*size
        blocksize = 8192

        # Calculate the filename and full path, flag to delete if needed
        filename = 'tempfile.%d.delete-me' % size
        pathfile = os.path.join(path, filename)
        if delete_file:
            self._files_to_delete.append(pathfile)

        pid = os.fork() # We need to run two processes in parallel
        if pid:
            # parent
            utils.BgJob('tail -f %s --pid=%s > /dev/null'
                        % (pathfile, pid))
            # Reap the dd child so that tail does not wait for the zombie
            os.waitpid(pid, 0)
        else:
            # child
            utils.system('dd if=/dev/urandom of=%s bs=%d count=%s'
                         % (pathfile, blocksize, (size//blocksize)))
            # A forked child is exiting here, so we really do want os._exit:
            os._exit(0)


    def run_once(self, ramdisk_size=513, file_size=512, drain_limit=1.05,
                 volume_filter={'bus': 'usb'}):
        """Test card reader CPU power consumption to be within acceptable
        range while performing random r/w

        The random r/w is performed in the readwrite_test() method, by
        concurrently running `dd if=/dev/urandom` and `tail -f`. It is run once
        on a ramdisk with the SD card mounted, then on the SD card with the
        ramdisk unmounted, and then on the SD card with the ramdisk unmounted.
        The measured values are then reported.

        @param ramdisk_size: Size of ramdisk (in MiB).
        @param file_size: Size of test file (in MiB).
        @param volume_filter: Where to find the card reader.
        @param drain_limit: maximum ratio between the card reader
                            energy consumption and each of the two
                            ramdisk read/write test energy consumption
                            values. 1.00 means the card reader test may
                            not consume more energy than either ramdisk
                            test, 0.9 means it may consume no more than
                            90% of the ramdisk value, and so forth.
        """
        # Switch to VT2 so the screen turns itself off automatically instead of
        # dimming, in order to reduce the battery consuption caused by other
        # variables.
        utils.system('chvt 2')

        logging.debug('STEP 1: ensure SD card is inserted and mounted')
        self._storage = self.wait_for_device(volume_filter, cycles=1,
                                             mount_volume=True)[0]

        logging.debug('STEP 2: mount the ramdisk')
        self._ramdisk_path = autotemp.tempdir(unique_id='ramdisk',
                                              dir=self.tmpdir)
        mount_ramdisk(self._ramdisk_path.name, ramdisk_size)

        # Read current charge, as well as maximum charge.
        self.status.refresh()
        max_charge = self.status.battery.charge_full_design
        initial_charge = self.status.battery.charge_now

        logging.debug('STEP 3: perform heavy-duty read-write test on ramdisk')
        self.readwrite_test(self._ramdisk_path.name, file_size)
        # Read current charge (reading A)
        self.status.refresh()
        charge_A = self.status.battery.charge_now

        logging.debug('STEP 4: unmount ramdisk')
        umount_ramdisk(self._ramdisk_path.name)

        logging.debug('STEP 5: perform identical read write test on SD card')
        self.readwrite_test(self._storage['mountpoint'], file_size,
                            delete_file=True)
        # Read current charge (reading B)
        self.status.refresh()
        charge_B = self.status.battery.charge_now

        logging.debug('STEP 6: unmount card')
        self.scanner.umount_volume(storage_dict=self._storage, args='-f -l')

        logging.debug('STEP 7: perform ramdisk test again')
        mount_ramdisk(self._ramdisk_path.name, ramdisk_size)
        self.readwrite_test(self._ramdisk_path.name, file_size)
        # Read current charge (reading C)
        self.status.refresh()
        charge_C = self.status.battery.charge_now

        # Compute the results
        ramdisk_plus = initial_charge - charge_A
        sd_card_solo = charge_A - charge_B
        ramdisk_solo = charge_B - charge_C

        sd_card_drain_ratio_a = (sd_card_solo / ramdisk_plus)
        sd_card_drain_ratio_b = (sd_card_solo / ramdisk_solo)

        msg = None
        if sd_card_drain_ratio_a > drain_limit:
            msg = ('Card reader drain exceeds mounted baseline by > %f (%f)'
                   % (drain_limit, sd_card_drain_ratio_a))
        elif sd_card_drain_ratio_b > drain_limit:
            msg = ('Card reader drain exceeds unmounted baseline by > %f (%f)'
                   % (drain_limit, sd_card_drain_ratio_b))

        if msg:
            raise error.TestError(msg)
        else:
            fmt = 'Card reader drain ratio Ok: mounted %f; unmounted %f'
            logging.info(fmt % (sd_card_drain_ratio_a, sd_card_drain_ratio_b))


def mount_ramdisk(path, size):
    utils.system('mount -t tmpfs none %s -o size=%sm' % (path, size))


def umount_ramdisk(path):
    """Umount ramdisk mounted at |path|

    @param path: the mountpoint for the mountd RAM disk
    """
    utils.system('rm -rf %s/*' % path)
    utils.system('umount -f -l %s' % path)
