1# Copyright (c) 2013 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# WARNING(crbug.com/743265): This test is currently broken because the ability 6# to run client tests in the background from a server-side test has been 7# deleted. 8 9import logging, time 10 11from autotest_lib.server import autotest, test 12from autotest_lib.client.common_lib import error 13 14_SUSPEND_TIME = 60 15_SUSPEND_TIMEOUT = 30 16 17class power_USBHotplugInSuspend(test.test): 18 19 version = 1 20 21 # Constant to wait in seconds after turning on or off the usb port power. 22 USB_POWEROFF_DELAY_S = 2 23 24 25 def _switch_usbkey_power(self, on): 26 """ 27 Turn on/off the power to the USB key. 28 29 @param on True to turn on, false otherwise. 30 """ 31 if on: 32 self._host.servo.set('image_usbkey_pwr', 'on') 33 else: 34 self._host.servo.set('image_usbkey_pwr', 'off') 35 time.sleep(self.USB_POWEROFF_DELAY_S) 36 37 def _get_usb_devices(self): 38 """ 39 Get the USB devices attached to the client. 40 41 Parses output from lsusb and returns the set of device IDs. 42 """ 43 try: 44 lines = self._host.run('lsusb').stdout.strip().split('\n') 45 except: 46 raise error.TestError('Failed to get list of USB devices.') 47 devices = set(line.split()[5] for line in lines) 48 logging.info('USB Devices: %s' % (",".join(devices))) 49 return devices 50 51 def _suspend_client(self): 52 """ 53 Start the client test power_KernelSuspend to suspend the client and 54 do not wait for it to finish. 55 """ 56 client_at = autotest.Autotest(self._host) 57 # TODO(scottz): Add server side support to sys_power: crosbug.com/38115 58 client_at.run_test('power_KernelSuspend', background=True, 59 seconds=_SUSPEND_TIME) 60 61 def _suspend_and_hotplug(self, insert): 62 """ 63 Suspend the client and add/remove the USB key. This assumes that a 64 USB key is plugged into the servo and is facing the DUT. 65 66 @param insert True to test insertion during suspend, False to test 67 removal. 68 """ 69 # Initialize the USB key and get the set of USB devices before 70 # suspending. 71 self._switch_usbkey_power(not insert) 72 before_suspend = self._get_usb_devices() 73 74 # Suspend the client and wait for it to go down before powering on/off 75 # the usb key. 76 self._suspend_client() 77 if not self._host.ping_wait_down(_SUSPEND_TIMEOUT): 78 raise error.TestError('Client failed to suspend.') 79 self._switch_usbkey_power(insert) 80 81 # Wait for the client to come back up (suspend time + some slack time). 82 # TODO(beeps): Combine the two timeouts in wait_up after 83 # crbug.com/221785 is resolved. 84 time.sleep(_SUSPEND_TIME) 85 if not self._host.wait_up(self._host.RESUME_TIMEOUT): 86 raise error.TestError('Client failed to resume.') 87 88 # Get the set of devices plugged in and make sure the change was 89 # detected. 90 after_suspend = self._get_usb_devices() 91 diff = after_suspend ^ before_suspend 92 if not diff: 93 raise error.TestFail('No USB changes detected after resuming.') 94 95 # Finally, make sure hotplug still works after resuming by switching 96 # the USB key's power once more. 97 self._switch_usbkey_power(not insert) 98 after_hotplug = self._get_usb_devices() 99 diff = after_hotplug ^ after_suspend 100 if not diff: 101 raise error.TestFail('No USB changes detected after hotplugging.') 102 103 def cleanup(self): 104 """ 105 Reset the USB key to its initial state. 106 """ 107 self._host.servo.switch_usbkey(self._init_usbkey_direction) 108 self._switch_usbkey_power(self._init_usbkey_power == 'on') 109 super(power_USBHotplugInSuspend, self).cleanup() 110 111 def run_once(self, host): 112 """ 113 Tests adding and removing a USB device while the client is suspended. 114 """ 115 self._host = host 116 self._init_usbkey_power = self._host.servo.get('image_usbkey_pwr') 117 self._init_usbkey_direction = self._host.servo.get_usbkey_state() 118 119 # Make sure the USB key is facing the DUT and is actually present. 120 self._host.servo.switch_usbkey('dut') 121 self._switch_usbkey_power(False) 122 before_insert = self._get_usb_devices() 123 self._switch_usbkey_power(True) 124 after_insert = self._get_usb_devices() 125 diff = after_insert - before_insert 126 logging.info('Inserted USB device(s): %s' % (",".join(diff))) 127 if not diff: 128 raise error.TestError('No new USB devices detected. Is a USB key ' 129 'plugged into the servo?') 130 131 logging.info('Testing insertion during suspend.') 132 self._suspend_and_hotplug(True) 133 logging.info('Testing removal during suspend.') 134 self._suspend_and_hotplug(False) 135