| # Copyright 2017 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 os |
| import time |
| |
| from autotest_lib.server import test |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.common_lib.cros import tpm_utils |
| from autotest_lib.server.cros.multimedia import remote_facade_factory |
| |
| SHORT_TIMEOUT = 5 |
| |
| |
| class CfmBaseTest(test.test): |
| """ |
| Base class for Cfm enterprise tests. |
| |
| CfmBaseTest provides common setup and cleanup methods. This base class is |
| agnostic with respect to 'hangouts classic' vs. 'hangouts meet' - it works |
| for both flavors. |
| """ |
| |
| def initialize(self, host, run_test_only=False, skip_enrollment=False): |
| """ |
| Initializes common test properties. |
| |
| @param host: a host object representing the DUT. |
| @param run_test_only: Wheter to run only the test or to also perform |
| deprovisioning, enrollment and system reboot. If set to 'True', |
| the DUT must already be enrolled and past the OOB screen to be able |
| to execute the test. |
| @param skip_enrollment: Whether to skip the enrollment step. Cleanup |
| at the end of the test is done regardless. |
| """ |
| super(CfmBaseTest, self).initialize() |
| self._host = host |
| self._run_test_only = run_test_only |
| self._skip_enrollment = skip_enrollment |
| self._facade_factory = remote_facade_factory.RemoteFacadeFactory( |
| self._host, no_chrome = True) |
| self.cfm_facade = self._facade_factory.create_cfm_facade() |
| |
| def setup(self): |
| """ |
| Performs common test setup operations: |
| - clears the TPM |
| - sets up servo |
| - enrolls the device |
| - skips OOBE |
| """ |
| super(CfmBaseTest, self).setup() |
| if self._host.servo: |
| self._setup_servo() |
| |
| if self._run_test_only or self._skip_enrollment: |
| # We need to restart the browser to obtain the handle for it when |
| # running in test_only mode. |
| self.cfm_facade.restart_chrome_for_cfm() |
| else: |
| logging.info('Clearing TPM') |
| tpm_utils.ClearTPMOwnerRequest(self._host) |
| logging.info('Enrolling device') |
| self.cfm_facade.enroll_device() |
| logging.info('Skipping OOBE') |
| self.cfm_facade.skip_oobe_after_enrollment() |
| |
| def _setup_servo(self): |
| """ |
| Enables the USB port such that any peripheral connected to it is visible |
| to the DUT. |
| """ |
| try: |
| # Servos have a USB key connected for recovery. The following code |
| # sets up the servo so that the DUT (and not the servo) sees this |
| # USB key as a device. |
| # We do not generally need this in tests, why we ignore any |
| # errors here. This also seems to fail on Servo V4 but we |
| # don't need it in any tests with that setup. |
| self._host.servo.switch_usbkey('dut') |
| self._host.servo.set('usb_mux_sel3', 'dut_sees_usbkey') |
| time.sleep(SHORT_TIMEOUT) |
| self._host.servo.set('dut_hub1_rst1', 'off') |
| time.sleep(SHORT_TIMEOUT) |
| except error.TestFail: |
| logging.warn('Failed to configure servo. This is not fatal unless ' |
| 'your test is explicitly using the servo.', |
| exc_info=True) |
| |
| def cleanup(self, run_test_only=False): |
| """Takes a screenshot, saves log files and clears the TPM.""" |
| self.take_screenshot('%s' % self.tagged_testname) |
| self.save_callgrok_logs() |
| self.save_packaged_app_logs() |
| if not self._run_test_only: |
| tpm_utils.ClearTPMOwnerRequest(self._host) |
| super(CfmBaseTest, self).cleanup() |
| |
| def take_screenshot(self, screenshot_name): |
| """ |
| Takes a screenshot (in .png format) and saves it in the debug dir. |
| |
| @param screenshot_name: Name of the screenshot file without extension. |
| """ |
| try: |
| target_dir = self.debugdir |
| logging.info('Taking screenshot and saving under %s...', |
| target_dir) |
| remote_path = self.cfm_facade.take_screenshot() |
| if remote_path: |
| # Copy the screenshot from the DUT. |
| self._safe_copy_file( |
| remote_path, |
| os.path.join(target_dir, screenshot_name + '.png')) |
| else: |
| logging.warning('Taking screenshot failed') |
| except Exception as e: |
| logging.exception('Exception while taking a screenshot.') |
| |
| def save_callgrok_logs(self): |
| """ |
| Copies the callgrok logs from the client to test's debug directory. |
| """ |
| callgrok_log_path = self.cfm_facade.get_latest_callgrok_file_path() |
| if callgrok_log_path: |
| self._safe_copy_file( |
| callgrok_log_path, |
| os.path.join(self.debugdir, 'callgrok_logs.txt')) |
| else: |
| logging.warning('No callgrok logs found on DUT.') |
| |
| def save_packaged_app_logs(self): |
| """ |
| Copies the packaged app logs from the client to test's debug directory. |
| """ |
| pa_log_path = self.cfm_facade.get_latest_pa_logs_file_path() |
| if pa_log_path: |
| self._safe_copy_file( |
| pa_log_path, |
| os.path.join(self.debugdir, 'packaged_app_logs.txt')) |
| else: |
| logging.warning('No packaged app logs found on DUT.') |
| |
| def save_all_packaged_app_logs(self): |
| """ |
| Copies the packaged app logs from the client to test's debug directory. |
| """ |
| pa_log_paths = self.cfm_facade.get_all_pa_logs_file_path() |
| if not pa_log_paths: |
| logging.warning('No packaged app logs found on DUT.') |
| return |
| for log_file in pa_log_paths: |
| log_filename = ( |
| 'packaged_app_log_%s.txt' % os.path.basename(log_file)) |
| self._safe_copy_file( |
| log_file, os.path.join(self.debugdir, log_filename)) |
| |
| def _safe_copy_file(self, remote_path, local_path): |
| """ |
| Copies the packaged app log file from CFM to test's debug directory. |
| """ |
| try: |
| logging.info('Copying file "%s" from client to "%s"...', |
| remote_path, local_path) |
| self._host.get_file(remote_path, local_path) |
| except Exception as e: |
| logging.exception( |
| 'Exception while copying file "%s"', remote_path) |
| |