Home | History | Annotate | Download | only in cfm
      1 # Copyright 2017 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import logging
      6 import os
      7 import time
      8 
      9 from autotest_lib.server import test
     10 from autotest_lib.client.common_lib import error
     11 from autotest_lib.client.common_lib.cros import tpm_utils
     12 from autotest_lib.server.cros.multimedia import remote_facade_factory
     13 
     14 SHORT_TIMEOUT = 5
     15 
     16 
     17 class CfmBaseTest(test.test):
     18     """
     19     Base class for Cfm enterprise tests.
     20 
     21     CfmBaseTest provides common setup and cleanup methods. This base class is
     22     agnostic with respect to 'hangouts classic' vs. 'hangouts meet' - it works
     23     for both flavors.
     24     """
     25 
     26     def initialize(self, host, run_test_only=False, skip_enrollment=False):
     27         """
     28         Initializes common test properties.
     29 
     30         @param host: a host object representing the DUT.
     31         @param run_test_only: Wheter to run only the test or to also perform
     32             deprovisioning, enrollment and system reboot. If set to 'True',
     33             the DUT must already be enrolled and past the OOB screen to be able
     34             to execute the test.
     35         @param skip_enrollment: Whether to skip the enrollment step. Cleanup
     36             at the end of the test is done regardless.
     37         """
     38         super(CfmBaseTest, self).initialize()
     39         self._host = host
     40         self._run_test_only = run_test_only
     41         self._skip_enrollment = skip_enrollment
     42         self._facade_factory = remote_facade_factory.RemoteFacadeFactory(
     43             self._host, no_chrome = True)
     44         self.cfm_facade = self._facade_factory.create_cfm_facade()
     45 
     46     def setup(self):
     47         """
     48         Performs common test setup operations:
     49           - clears the TPM
     50           - sets up servo
     51           - enrolls the device
     52           - skips OOBE
     53         """
     54         super(CfmBaseTest, self).setup()
     55         if self._host.servo:
     56             self._setup_servo()
     57 
     58         if self._run_test_only or self._skip_enrollment:
     59             # We need to restart the browser to obtain the handle for it when
     60             # running in test_only mode.
     61             self.cfm_facade.restart_chrome_for_cfm()
     62         else:
     63             logging.info('Clearing TPM')
     64             tpm_utils.ClearTPMOwnerRequest(self._host)
     65             logging.info('Enrolling device')
     66             self.cfm_facade.enroll_device()
     67             logging.info('Skipping OOBE')
     68             self.cfm_facade.skip_oobe_after_enrollment()
     69 
     70     def _setup_servo(self):
     71         """
     72         Enables the USB port such that any peripheral connected to it is visible
     73         to the DUT.
     74         """
     75         try:
     76             # Servos have a USB key connected for recovery. The following code
     77             # sets up the servo so that the DUT (and not the servo) sees this
     78             # USB key as a device.
     79             # We do not generally need this in tests, why we ignore any
     80             # errors here. This also seems to fail on Servo V4 but we
     81             # don't need it in any tests with that setup.
     82             self._host.servo.switch_usbkey('dut')
     83             self._host.servo.set('usb_mux_sel3', 'dut_sees_usbkey')
     84             time.sleep(SHORT_TIMEOUT)
     85             self._host.servo.set('dut_hub1_rst1', 'off')
     86             time.sleep(SHORT_TIMEOUT)
     87         except error.TestFail:
     88             logging.warn('Failed to configure servo. This is not fatal unless '
     89                          'your test is explicitly using the servo.',
     90                          exc_info=True)
     91 
     92     def cleanup(self, run_test_only=False):
     93         """Takes a screenshot, saves log files and clears the TPM."""
     94         self.take_screenshot('%s' % self.tagged_testname)
     95         self.save_callgrok_logs()
     96         self.save_packaged_app_logs()
     97         if not self._run_test_only:
     98             tpm_utils.ClearTPMOwnerRequest(self._host)
     99         super(CfmBaseTest, self).cleanup()
    100 
    101     def take_screenshot(self, screenshot_name):
    102         """
    103         Takes a screenshot (in .png format) and saves it in the debug dir.
    104 
    105         @param screenshot_name: Name of the screenshot file without extension.
    106         """
    107         try:
    108             target_dir = self.debugdir
    109             logging.info('Taking screenshot and saving under %s...',
    110                          target_dir)
    111             remote_path = self.cfm_facade.take_screenshot()
    112             if remote_path:
    113                 # Copy the screenshot from the DUT.
    114                 self._safe_copy_file(
    115                     remote_path,
    116                     os.path.join(target_dir, screenshot_name + '.png'))
    117             else:
    118                 logging.warning('Taking screenshot failed')
    119         except Exception as e:
    120             logging.exception('Exception while taking a screenshot.')
    121 
    122     def save_callgrok_logs(self):
    123         """
    124         Copies the callgrok logs from the client to test's debug directory.
    125         """
    126         callgrok_log_path = self.cfm_facade.get_latest_callgrok_file_path()
    127         if callgrok_log_path:
    128             self._safe_copy_file(
    129                 callgrok_log_path,
    130                 os.path.join(self.debugdir, 'callgrok_logs.txt'))
    131         else:
    132             logging.warning('No callgrok logs found on DUT.')
    133 
    134     def save_packaged_app_logs(self):
    135         """
    136         Copies the packaged app logs from the client to test's debug directory.
    137         """
    138         pa_log_path = self.cfm_facade.get_latest_pa_logs_file_path()
    139         if pa_log_path:
    140             self._safe_copy_file(
    141                 pa_log_path,
    142                 os.path.join(self.debugdir, 'packaged_app_logs.txt'))
    143         else:
    144             logging.warning('No packaged app logs found on DUT.')
    145 
    146     def save_all_packaged_app_logs(self):
    147         """
    148         Copies the packaged app logs from the client to test's debug directory.
    149         """
    150         pa_log_paths = self.cfm_facade.get_all_pa_logs_file_path()
    151         if not  pa_log_paths:
    152             logging.warning('No packaged app logs found on DUT.')
    153             return
    154         for log_file in pa_log_paths:
    155             log_filename = (
    156                 'packaged_app_log_%s.txt' % os.path.basename(log_file))
    157             self._safe_copy_file(
    158                 log_file, os.path.join(self.debugdir, log_filename))
    159 
    160     def _safe_copy_file(self, remote_path, local_path):
    161         """
    162         Copies the packaged app log file from CFM to test's debug directory.
    163         """
    164         try:
    165             logging.info('Copying file "%s" from client to "%s"...',
    166                          remote_path, local_path)
    167             self._host.get_file(remote_path, local_path)
    168         except Exception as e:
    169             logging.exception(
    170                 'Exception while copying file "%s"', remote_path)
    171 
    172