• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import logging
6import os
7import time
8
9from autotest_lib.server import test
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.common_lib.cros import tpm_utils
12from autotest_lib.server.cros.multimedia import remote_facade_factory
13
14SHORT_TIMEOUT = 5
15
16
17class 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 & rebooting afterwards...')
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            logging.info('[CLEAN UP] Clearing TPM (without reboot)...')
99            self._only_clear_tpm()
100        super(CfmBaseTest, self).cleanup()
101
102    def _only_clear_tpm(self):
103        if not self._host.run('crossystem clear_tpm_owner_request=1',
104                              ignore_status=True).exit_status == 0:
105            raise error.TestFail('Unable to clear TPM.')
106
107    def take_screenshot(self, screenshot_name):
108        """
109        Takes a screenshot (in .png format) and saves it in the debug dir.
110
111        @param screenshot_name: Name of the screenshot file without extension.
112        """
113        try:
114            target_dir = self.debugdir
115            logging.info('Taking screenshot and saving under %s...',
116                         target_dir)
117            remote_path = self.cfm_facade.take_screenshot()
118            if remote_path:
119                # Copy the screenshot from the DUT.
120                self._safe_copy_file(
121                    remote_path,
122                    os.path.join(target_dir, screenshot_name + '.png'))
123            else:
124                logging.warning('Taking screenshot failed')
125        except Exception as e:
126            logging.exception('Exception while taking a screenshot.')
127
128    def save_callgrok_logs(self):
129        """
130        Copies the callgrok logs from the client to test's debug directory.
131        """
132        callgrok_log_path = self.cfm_facade.get_latest_callgrok_file_path()
133        if callgrok_log_path:
134            self._safe_copy_file(
135                callgrok_log_path,
136                os.path.join(self.debugdir, 'callgrok_logs.txt'))
137        else:
138            logging.warning('No callgrok logs found on DUT.')
139
140    def save_packaged_app_logs(self):
141        """
142        Copies the packaged app logs from the client to test's debug directory.
143        """
144        pa_log_path = self.cfm_facade.get_latest_pa_logs_file_path()
145        if pa_log_path:
146            self._safe_copy_file(
147                pa_log_path,
148                os.path.join(self.debugdir, 'packaged_app_logs.txt'))
149        else:
150            logging.warning('No packaged app logs found on DUT.')
151
152    def save_all_packaged_app_logs(self):
153        """
154        Copies the packaged app logs from the client to test's debug directory.
155        """
156        pa_log_paths = self.cfm_facade.get_all_pa_logs_file_path()
157        if not  pa_log_paths:
158            logging.warning('No packaged app logs found on DUT.')
159            return
160        for log_file in pa_log_paths:
161            log_filename = (
162                'packaged_app_log_%s.txt' % os.path.basename(log_file))
163            self._safe_copy_file(
164                log_file, os.path.join(self.debugdir, log_filename))
165
166    def _safe_copy_file(self, remote_path, local_path):
167        """
168        Copies the packaged app log file from CFM to test's debug directory.
169        """
170        try:
171            logging.info('Copying file "%s" from client to "%s"...',
172                         remote_path, local_path)
173            self._host.get_file(remote_path, local_path)
174        except Exception as e:
175            logging.exception(
176                'Exception while copying file "%s"', remote_path)
177
178