• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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