def run_once(self):
        time.sleep(self._init_delay)
        self._suspender = power_suspend.Suspender(
            self.resultsdir,
            method=self._method,
            suspend_state=self._suspend_state)
        # Find the interface which is used for most communication.
        # We assume the interface connects to the gateway and has the lowest
        # metric.
        if self._check_connection:
            iface = utils.poll_for_condition(
                self._get_default_network_interface,
                desc='Find default network interface')
            logging.info('Found default network interface: %s', iface.name)

        while not self._done():
            time.sleep(self._min_resume +
                       random.randint(0, self._max_resume_window))
            # Check the network interface to the caller is still available
            if self._check_connection:
                # Give a 10 second window for the network to come back.
                try:
                    utils.poll_for_condition(iface.is_link_operational,
                                             desc='Link is operational')
                except utils.TimeoutError:
                    logging.error('Link to the server gone, reboot')
                    utils.system('reboot')
                    # Reboot may return; raise a TestFail() to abort too, even
                    # though the server likely won't see this.
                    raise error.TestFail('Link is gone; rebooting')

            self._suspender.suspend(random.randint(0, 3) + self._min_suspend)
Beispiel #2
0
    def run_once(self):
        time.sleep(self._init_delay)
        self._suspender = power_suspend.Suspender(
            self.resultsdir,
            method=self._method,
            suspend_state=self._suspend_state)
        # Find the interface which is used for most communication.
        # We assume the interface connects to the gateway and has the lowest
        # metric.
        if self._check_connection:
            interface_choices = {}
            with open('/proc/net/route') as fh:
                for line in fh:
                    fields = line.strip().split()
                    if fields[1] != '00000000' or not int(fields[3], 16) & 2:
                        continue
                    interface_choices[fields[0]] = fields[6]
            iface = interface.Interface(min(interface_choices))

        while not self._done():
            time.sleep(self._min_resume +
                       random.randint(0, self._max_resume_window))
            # Check the network interface to the caller is still available
            if self._check_connection:
                # Give a 10 second window for the network to come back.
                try:
                    utils.poll_for_condition(iface.is_link_operational,
                                             desc='Link is operational')
                except utils.TimeoutError:
                    logging.error('Link to the server gone, reboot')
                    utils.system('reboot')

            self._suspender.suspend(random.randint(0, 3) + self._min_suspend)
Beispiel #3
0
    def initialize(self, suspend_state=''):
        """
        Entry point.

        @param suspend_state: Force to suspend to a specific
                state ("mem" or "freeze"). If the string is empty, suspend
                state is left to the default pref on the system.
        """
        self._suspender = power_suspend.Suspender(self.resultsdir,
                                                  throw=True,
                                                  device_times=True,
                                                  suspend_state=suspend_state)
Beispiel #4
0
    def suspend_resume(self, duration=10):
        suspender = power_suspend.Suspender(self.resultsdir, throw=True)
        suspender.suspend(duration)
        logging.info('Machine resumed')

        # Race condition hack alert: Before we added this sleep, this
        # test was very sensitive to the relative timing of the test
        # and modem resumption.  There is a window where flimflam has
        # not yet learned that the old modem has gone away (it doesn't
        # find this out until seconds after we resume) and the test is
        # running.  If the test finds and attempts to use the old
        # modem, those operations will fail.  There's no good
        # hardware-independent way to see the modem go away and come
        # back, so instead we sleep
        time.sleep(4)
    def run_once(self,
                 test_hours=None,
                 sample_hours=None,
                 max_milliwatts_standby=500,
                 ac_ok=False,
                 force_discharge=False,
                 suspend_state='',
                 bypass_check=False):
        """Put DUT to suspend state for |sample_hours| and measure power."""
        if not power_utils.has_battery():
            raise error.TestNAError(
                'Skipping test because DUT has no battery.')

        if test_hours < sample_hours:
            raise error.TestFail('Test hours must be greater than sample '
                                 'hours.')

        # If we're measuring < 6min of standby then the S0 time is not
        # negligible. Note, reasonable rule of thumb is S0 idle is ~10-20 times
        # standby power.
        if sample_hours < self._min_sample_hours and not bypass_check:
            raise error.TestFail('Must standby more than %.2f hours.' % \
                                 sample_hours)

        power_stats = power_status.get_status()

        if not ac_ok and power_stats.on_ac():
            raise error.TestError('On AC, please unplug power supply.')

        if force_discharge:
            if not power_stats.on_ac():
                raise error.TestError('Not on AC, please plug in power supply '
                                      'to attempt force discharge.')
            if not power_utils.charge_control_by_ectool(False):
                raise error.TestError('Unable to force discharge.')

            self._force_discharge_enabled = True

        charge_start = power_stats.battery[0].charge_now
        voltage_start = power_stats.battery[0].voltage_now

        max_hours = ((charge_start * voltage_start) /
                     (max_milliwatts_standby / 1000.))
        if max_hours < test_hours:
            raise error.TestFail('Battery not charged adequately for test.')

        suspender = power_suspend.Suspender(self.resultsdir,
                                            suspend_state=suspend_state)

        elapsed_hours = 0

        results = {}
        loop = 0
        start_ts = time.time()

        while elapsed_hours < test_hours:
            charge_before = power_stats.battery[0].charge_now
            before_suspend_secs = rtc.get_seconds()
            suspender.suspend(duration=sample_hours * 3600)
            after_suspend_secs = rtc.get_seconds()

            power_stats.refresh()
            if power_stats.percent_current_charge() < self._percent_min_charge:
                logging.warning('Battery = %.2f%%.  Too low to continue.')
                break

            # check that the RTC slept the correct amount of time as there could
            # potentially be another wake source that would spoil the test.
            actual_hours = (after_suspend_secs - before_suspend_secs) / 3600.0
            percent_diff = math.fabs((actual_hours - sample_hours) /
                                     ((actual_hours + sample_hours) / 2) * 100)
            if percent_diff > 2 and not bypass_check:
                err = 'Requested standby time and actual varied by %.2f%%.' \
                    % percent_diff
                raise error.TestFail(err)

            # Check resulting charge consumption
            charge_used = charge_before - power_stats.battery[0].charge_now
            elapsed_hours += actual_hours
            logging.debug(
                'loop%d done: loop hours %.3f, elapsed hours %.3f '
                'charge used: %.3f', loop, actual_hours, elapsed_hours,
                charge_used)
            loop += 1

        end_ts = time.time()
        offset = (end_ts - start_ts - elapsed_hours * 3600) / 2.
        offset += suspender.get_suspend_delay()
        start_ts += offset
        end_ts -= offset
        power_telemetry_utils.start_measurement(start_ts)
        power_telemetry_utils.end_measurement(end_ts)
        self._checkpoint_logger.checkpoint(self.tagged_testname, start_ts,
                                           end_ts)
        charge_end = power_stats.battery[0].charge_now
        total_charge_used = charge_start - charge_end
        if total_charge_used <= 0 and not bypass_check:
            raise error.TestError('Charge used is suspect.')

        voltage_end = power_stats.battery[0].voltage_now
        standby_hours = power_stats.battery[0].charge_full_design / \
                        total_charge_used * elapsed_hours
        energy_used = (voltage_start + voltage_end) / 2 * \
                      total_charge_used

        results['ah_charge_start'] = charge_start
        results['ah_charge_now'] = charge_end
        results['ah_charge_used'] = total_charge_used
        results['force_discharge'] = self._force_discharge_enabled
        results['hours_standby_time'] = standby_hours
        results['hours_standby_time_tested'] = elapsed_hours
        results['v_voltage_start'] = voltage_start
        results['v_voltage_now'] = voltage_end
        results['w_energy_rate'] = energy_used / elapsed_hours
        results['wh_energy_used'] = energy_used

        self.write_perf_keyval(results)
        pdash = power_dashboard.SimplePowerLoggerDashboard(
            end_ts - start_ts,
            results['w_energy_rate'],
            self.tagged_testname,
            start_ts,
            self.resultsdir,
            note=self._pdash_note)
        pdash.upload()
        self._checkpoint_logger.save_checkpoint_data(self.resultsdir)

        self.output_perf_value(description='hours_standby_time',
                               value=results['hours_standby_time'],
                               units='hours',
                               higher_is_better=True)
        self.output_perf_value(description='w_energy_rate',
                               value=results['w_energy_rate'],
                               units='watts',
                               higher_is_better=False)

        # need to sleep for some time to allow network connection to return
        time.sleep(10)
    def run_once(self, force_suspend_to_idle=False):
        """Main test method.
        """
        if utils.get_cpu_arch() != 'x86_64':
            raise error.TestNAError('This test only supports x86_64 CPU.')

        if power_utils.get_sleep_state() != 'freeze':
            if not force_suspend_to_idle:
                raise error.TestNAError(
                    'System default config is not suspend to idle.')
            else:
                logging.info('System default config is suspend to ram. '
                             'Force suspend to idle')

        self._error_count = 0
        self._error_message = []
        dmc_firmware_stats = None
        s0ix_residency_stats = None
        cpu_packages_stats = None
        rc6_residency_stats = None

        with self._log_error_message():
            dmc_firmware_stats = power_status.DMCFirmwareStats()
            if not dmc_firmware_stats.check_fw_loaded():
                raise error.TestFail('DMC firmware not loaded.')

        with self._log_error_message():
            pch_powergating_stats = power_status.PCHPowergatingStats()
            pch_powergating_stats.read_pch_powergating_info()
            if not pch_powergating_stats.check_s0ix_requirement():
                raise error.TestFail('PCH powergating check failed.')

        with self._log_error_message():
            s0ix_residency_stats = power_status.S0ixResidencyStats()

        with self._log_error_message():
            cpu_packages_stats = power_status.CPUPackageStats()

        with self._log_error_message():
            rc6_residency_stats = power_status.RC6ResidencyStats()

        with self._log_error_message():
            suspender = power_suspend.Suspender(self.resultsdir,
                                                suspend_state='freeze')
            suspender.suspend()

        with self._log_error_message():
            if (dmc_firmware_stats and dmc_firmware_stats.is_dc6_supported()
                    and dmc_firmware_stats.get_accumulated_dc6_entry() <= 0):
                raise error.TestFail('DC6 entry check failed.')

        with self._log_error_message():
            if (s0ix_residency_stats
                    and s0ix_residency_stats.get_accumulated_residency_secs()
                    <= 0):
                raise error.TestFail('S0ix residency check failed.')

        with self._log_error_message():
            if (cpu_packages_stats
                    and cpu_packages_stats.refresh().get('C10', 0) <= 0):
                raise error.TestFail('C10 state check failed.')

        with self._log_error_message():
            if (rc6_residency_stats and
                    rc6_residency_stats.get_accumulated_residency_secs() <= 0):
                raise error.TestFail('RC6 residency check failed.')

        if self._error_count > 0:
            raise error.TestFail('Found %d errors: ' % self._error_count,
                                 ', '.join(self._error_message))