Home | History | Annotate | Download | only in firmware_PDProtocol
      1 # Copyright 2016 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 re
      7 
      8 from collections import defaultdict
      9 
     10 from autotest_lib.client.common_lib import error
     11 from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
     12 
     13 class firmware_PDProtocol(FirmwareTest):
     14     """
     15     Servo based USB PD protocol test.
     16 
     17     A charger must be connected to the DUT for this test.
     18 
     19     This test checks that when an appropriate zinger charger is connected that
     20     the PD is properly negotiated in dev mode and when booted from a test image
     21     through recovery that the PD is not negotiated.
     22 
     23     Example:
     24     PD Successfully negotiated
     25     - ectool usbpdpower should output Charger PD
     26 
     27     PD not negotiated
     28     - ectool usbpdpower should not output Charger PD
     29 
     30     """
     31     version = 1
     32 
     33     NEGOTIATED_PATTERN = 'Charger PD'
     34     PD_NOT_SUPPORTED_PATTERN = 'INVALID_COMMAND'
     35 
     36     ECTOOL_CMD_DICT = defaultdict(lambda: 'ectool usbpdpower')
     37 
     38     def initialize(self, host, cmdline_args):
     39         super(firmware_PDProtocol, self).initialize(host, cmdline_args)
     40 
     41         self.ECTOOL_CMD_DICT['samus'] = 'ectool --dev=1 usbpdpower'
     42 
     43         self.current_board = self.servo.get_board();
     44 
     45         self.check_if_pd_supported()
     46         self.assert_test_image_in_usb_disk()
     47         self.switcher.setup_mode('dev')
     48         self.setup_usbkey(usbkey=True, host=False)
     49 
     50         self.original_dev_boot_usb = self.faft_client.system.get_dev_boot_usb()
     51         logging.info('Original dev_boot_usb value: %s',
     52                      str(self.original_dev_boot_usb))
     53 
     54     def cleanup(self):
     55         self.ensure_internal_device_boot()
     56         super(firmware_PDProtocol, self).cleanup()
     57 
     58     def check_if_pd_supported(self):
     59         """ Checks if the DUT responds to ectool usbpdpower and skips the test
     60         if it isn't supported on the device.
     61         """
     62         output = self.run_command(self.ECTOOL_CMD_DICT[self.current_board])
     63 
     64         if (not output or
     65             self.check_ec_output(output, self.PD_NOT_SUPPORTED_PATTERN)):
     66             raise error.TestNAError("PD not supported skipping test.")
     67 
     68     def ensure_internal_device_boot(self):
     69         """Ensure internal device boot; if not, reboot into it.
     70 
     71         If not, it may be a test failure during step 2 or 3, try to reboot
     72         and press Ctrl-D to internal device boot.
     73         """
     74         if self.faft_client.system.is_removable_device_boot():
     75             logging.info('Reboot into internal disk...')
     76             self.faft_client.system.set_dev_boot_usb(self.original_dev_boot_usb)
     77             self.switcher.mode_aware_reboot()
     78 
     79         self.check_state((self.checkers.dev_boot_usb_checker,
     80                           False,
     81                           'Did not boot from internal disk.'))
     82 
     83     def boot_to_recovery(self):
     84         """Boot device into recovery mode."""
     85         logging.info('Reboot into Recovery...')
     86         self.assert_test_image_in_usb_disk()
     87         self.switcher.reboot_to_mode(to_mode='rec')
     88 
     89         self.check_state((self.checkers.crossystem_checker,
     90                           {'mainfw_type': 'recovery'}))
     91 
     92     def run_command(self, command):
     93         """Runs the specified command and returns the output
     94         as a list of strings.
     95 
     96         @param command: The command to run on the DUT
     97         @return A list of strings of the command output
     98         """
     99         logging.info('Command to run: %s', command)
    100 
    101         output = self.faft_client.system.run_shell_command_get_output(command)
    102 
    103         logging.info('Command output: %s', output)
    104 
    105         return output
    106 
    107     def check_ec_output(self, output, pattern):
    108         """Checks if any line in the output matches the given pattern.
    109 
    110         @param output: A list of strings containg the output to search
    111         @param pattern: The regex to search the output for
    112 
    113         @return True upon first match found or False
    114         """
    115         logging.info('Checking %s for %s.', output, pattern)
    116 
    117         for line in output:
    118             if bool(re.search(pattern, line)):
    119                 return True
    120 
    121         return False
    122 
    123 
    124     def run_once(self):
    125         self.ensure_internal_device_boot()
    126         output = self.run_command(self.ECTOOL_CMD_DICT[self.current_board])
    127 
    128         if not self.check_ec_output(output, self.NEGOTIATED_PATTERN):
    129             raise error.TestFail(
    130                 'ectool usbpdpower output %s did not match %s',
    131                 (output, self.NEGOTIATED_PATTERN))
    132 
    133 
    134         self.boot_to_recovery()
    135         output = self.run_command(self.ECTOOL_CMD_DICT[self.current_board])
    136 
    137         if self.check_ec_output(output, self.NEGOTIATED_PATTERN):
    138             raise error.TestFail(
    139                 'ectool usbpdpower output %s matched %s',
    140                 (output, self.NEGOTIATED_PATTERN))
    141 
    142