def check_usb_peripherals_details(self, connected_device_dict):
        """Checks USB peripheral details against the values in dictionary.

        @param connected_device_dict: Dictionary of device attributes.

        """
        result = True
        usbPort = connected_device_dict['usb_port']
        PORT_BEING_TESTED.append(usbPort)
        self.usb_mux.enable_port(usbPort)

        vendorId = connected_device_dict['deviceInfo']['vendorId']
        productId = connected_device_dict['deviceInfo']['productId']
        manufacturer = connected_device_dict['deviceInfo']['manufacturer']
        productName = connected_device_dict['deviceInfo']['productName']
        lsusbOutput = connected_device_dict['deviceInfo']['lsusb']
        devicePath = connected_device_dict['deviceInfo']['devicePath']

        try:
            utils.poll_for_condition(lambda: self.host.path_exists(devicePath),
                                     exception=utils.TimeoutError(
                                         'Trouble finding USB device '
                                         'on port %d' % usbPort),
                                     timeout=15,
                                     sleep_interval=1)
        except utils.TimeoutError:
            logging.debug('Trouble finding USB device on port %d', usbPort)
            result = False
            pass

        if not ((vendorId + ':' + productId in lsusbOutput)
                and self.check_manufacturer_and_product_info(
                    vendorId, productId, manufacturer, productName) and
                self.check_driver_symlink_and_dir(devicePath, productName)):
            result = False

        self.usb_mux.disable_all_ports()
        try:
            utils.poll_for_condition(
                lambda: not self.host.path_exists(devicePath),
                exception=utils.TimeoutError(
                    'Device driver path does not '
                    'disappear after device is disconnected.'),
                timeout=15,
                sleep_interval=1)
        except utils.TimeoutError:
            logging.debug(
                'Device driver path is still present after device is '
                'disconnected from the DUT.')
            result = False
            pass

        if result is False:
            logging.debug('Test failed on port %s.', usbPort)
            TMP_FAILED_TEST_LIST.append(usbPort)
Example #2
0
    def stop(self):
        """Restore the backed-up DNS settings and stop the mock DNS server."""
        try:
            # Follow resolv.conf symlink.
            resolv = os.path.realpath(constants.RESOLV_CONF_FILE)
            # Grab path to the real file, do following work in that directory.
            resolv_dir = os.path.dirname(resolv)
            resolv_bak = os.path.join(resolv_dir, self._resolv_bak_file)
            os.chmod(resolv_dir, self._resolv_dir_mode)
            if os.path.exists(resolv_bak):
                os.rename(resolv_bak, resolv)
            else:
                # This probably means shill restarted during the execution
                # of our test, and has cleaned up the .bak file we created.
                raise error.TestError('Backup file %s no longer exists!  '
                                      'Connection manager probably crashed '
                                      'during the test run.' %
                                      resolv_bak)

            utils.poll_for_condition(
                lambda: self.__attempt_resolve('www.google.com.',
                                               '127.0.0.1',
                                               expected=False),
                utils.TimeoutError('Timed out waiting to revert DNS.  '
                                   'resolv.conf contents are: ' +
                                   utils.read_one_line(resolv)),
                timeout=10)
        finally:
            # Stop the DNS server.
            self._stopper.set()
            self._thread.join()
Example #3
0
def wait_for_chrome_ready(old_session, host=None, timeout=RESTART_UI_TIMEOUT):
    """Wait until a new Chrome login prompt is on screen and ready.

    The standard formula to check whether the prompt has appeared yet
    is with a pattern like the following:

       session = get_chrome_session_ident()
       logout()
       wait_for_chrome_ready(session)

    Args:
        old_session:  identifier for the login prompt prior to
            restarting Chrome.
        host:  If not None, a host object on which to test Chrome
            state, rather than running commands on the local host.
        timeout: float number of seconds to wait

    Raises:
        TimeoutError: Login prompt didn't get up before timeout

    """
    utils.poll_for_condition(
        condition=lambda: old_session != get_chrome_session_ident(host),
        exception=utils.TimeoutError('Timed out waiting for login prompt'),
        timeout=timeout,
        sleep_interval=1.0)
Example #4
0
def wait_for_condition(condition, timeout_msg, timeout, process, crash_msg):
    """Wait for callable |condition| to return true, while checking for crashes.

    Poll for |condition| to become true, for |timeout| seconds. If the timeout
    is reached, check to see if |process| crashed while we were polling.
    If so, raise CrashError(crash_msg). If not, raise TimeoutError(timeout_msg).

    @param condition: a callable to poll on.
    @param timeout_msg: message to put in TimeoutError before raising.
    @param timeout: float number of seconds to poll on |condition|.
    @param process: process name to watch for crashes while polling.
    @param crash_msg: message to put in CrashError if polling failed and
                      |process| crashed.

    @raise: TimeoutError if timeout is reached.
    @raise: CrashError if process crashed and the condition never fired.
    """
    # Mark /var/log/messages now; we'll run through all subsequent log
    # messages if we couldn't start chrome to see if the browser crashed.
    log_reader = cros_logging.LogReader()
    log_reader.set_start_by_current()
    try:
        utils.poll_for_condition(condition,
                                 utils.TimeoutError(timeout_msg),
                                 timeout=timeout)
    except utils.TimeoutError, e:
        # We could fail faster if necessary, but it'd be more complicated.
        if process_crashed(process, log_reader):
            logging.error(crash_msg)
            raise CrashError(crash_msg)
        else:
            raise e
    def run_once(self):
        # Create magic file to enable browser liveness checking and
        # bounce the session manager to pick up the flag file.
        cros_ui.stop()
        os.mknod(constants.ENABLE_BROWSER_HANG_DETECTION_FILE)
        cros_ui.start()

        browser_pid = self._get_oldest_pid_by_name(constants.BROWSER)
        sm_pid = self._get_oldest_pid_by_name(constants.SESSION_MANAGER)

        # Reading the log is the best way to watch for the hang detector.
        reader = cros_logging.LogReader()
        reader.set_start_by_current()

        # To simulate a hang, STOP the browser and wait for it to get
        # hit by the session manager.  It won't actually exit until it gets
        # a SIGCONT, though.
        try:
            os.kill(browser_pid, signal.SIGSTOP)  # Simulate hang.
        except OSError as e:
            raise error.TestError('Cannot STOP browser: %r' % e)

        # Watch for hang detection.
        utils.poll_for_condition(
            condition=lambda: reader.can_find('Aborting browser process.'),
            exception=utils.TimeoutError('Waiting for hang detector.'),
            sleep_interval=5,
            timeout=60)

        try:
            os.kill(browser_pid, signal.SIGCONT)  # Allow browser to die.
        except OSError as e:
            raise error.TestError('Cannot CONT browser: %r' % e)

        # Wait for old browser process to be gone.
        utils.poll_for_condition(
            condition= lambda: utils.pid_is_alive(browser_pid),
            exception=utils.TimeoutError(
                'Browser does not seem to have restarted!'),
            timeout=60)

        # Wait for new browser to come up.
        login.wait_for_browser()
        if sm_pid != self._get_oldest_pid_by_name(constants.SESSION_MANAGER):
            raise error.TestFail('session_manager seems to have restarted')
    def _wait_for_rlz_lock(self):
        """Waits for the DUT to get into locked state after login."""
        def get_install_lockbox_finalized_status():
            status = cryptohome.get_tpm_more_status()
            return status.get('install_lockbox_finalized')

        try:
            utils.poll_for_condition(
                lambda: get_install_lockbox_finalized_status(),
                exception=utils.TimeoutError(),
                timeout=120)
        except utils.TimeoutError:
            raise error.TestFail('Timed out trying to lock the device')
    def poll_pd_state(self, state):
        """Polls until Plankton pd goes to the specific state.

        @param state: Specified pd state name.
        """
        if state not in self.USBC_PD_STATES:
            raise PlanktonError('Invalid state name: %s' % state)
        utils.poll_for_condition(
            lambda: self.get('pd_state') == self.USBC_PD_STATES[state],
            exception=utils.TimeoutError('Plankton not in %s state '
                                         'after %s seconds.' %
                                         (self.USBC_PD_STATES[state],
                                          self.POLL_STATE_SECS)),
            timeout=self.POLL_STATE_SECS)
Example #8
0
    def wait_test_completed(self, timeout_secs):
        """
        Waits until the test is done.

        @param timeout_secs Max time to wait in seconds.

        @raises TestError on timeout, or javascript eval fails, or
                error status from the getStatus() JS method.
        """
        start_secs = time.time()
        while not self._test_done():
            spent_time = time.time() - start_secs
            if spent_time > timeout_secs:
                raise utils.TimeoutError(
                        'Test timed out after {} seconds'.format(spent_time))
            self.do_in_wait_loop()
Example #9
0
    def _wait_for_stable_modem_state(self):
        """
        Wait for a maximum of _MODEM_WAIT_DELAY seconds for the modem to get
        into stable state. Also, because we do not want the test to terminate
        in case there is an exception, we are catching and logging the exception
        so the test can continue with rebooting the device again as needed.

        """
        try:
            utils.poll_for_condition(
                lambda: self._get_modem_state() in self.STABLE_MODEM_STATES,
                exception=utils.TimeoutError('Modem not in stable state '
                                             'after %s seconds.' %
                                             _MODEM_WAIT_DELAY),
                timeout=_MODEM_WAIT_DELAY,
                sleep_interval=5)
        except utils.TimeoutError as e:
            logging.debug("Stable modem state TimeoutError is: %s", e)
Example #10
0
    def run(self):
        """Start the mock DNS server and redirect all queries to it."""
        self._thread.start()
        # Redirect all DNS queries to the mock DNS server.
        try:
            # Follow resolv.conf symlink.
            resolv = os.path.realpath(constants.RESOLV_CONF_FILE)
            # Grab path to the real file, do following work in that directory.
            resolv_dir = os.path.dirname(resolv)
            resolv_bak = os.path.join(resolv_dir, self._resolv_bak_file)
            resolv_contents = 'nameserver 127.0.0.1'
            # Test to make sure the current resolv.conf isn't already our
            # specially modified version.  If this is the case, we have
            # probably been interrupted while in the middle of this test
            # in a previous run.  The last thing we want to do at this point
            # is to overwrite a legitimate backup.
            if (utils.read_one_line(resolv) == resolv_contents and
                os.path.exists(resolv_bak)):
                logging.error('Current resolv.conf is setup for our local '
                              'server, and a backup already exists!  '
                              'Skipping the backup step.')
            else:
                # Back up the current resolv.conf.
                os.rename(resolv, resolv_bak)
            # To stop flimflam from editing resolv.conf while we're working
            # with it, we want to make the directory -r-xr-xr-x.  Open an
            # fd to the file first, so that we'll retain the ability to
            # alter it.
            resolv_fd = open(resolv, 'w')
            self._resolv_dir_mode = os.stat(resolv_dir).st_mode
            os.chmod(resolv_dir, (stat.S_IRUSR | stat.S_IXUSR |
                                  stat.S_IRGRP | stat.S_IXGRP |
                                  stat.S_IROTH | stat.S_IXOTH))
            resolv_fd.write(resolv_contents)
            resolv_fd.close()
            assert utils.read_one_line(resolv) == resolv_contents
        except Exception as e:
            logging.error(str(e))
            raise e

        utils.poll_for_condition(
            lambda: self.__attempt_resolve('www.google.com.', '127.0.0.1'),
            utils.TimeoutError('Timed out waiting for DNS changes.'),
            timeout=10)
    def teardown(self):
        """Tears down the backchannel."""
        if self.interface:
            self._run('%s teardown %s' % (BACKCHANNEL_SCRIPT, self.interface))

        # Hack around broken Asix network adaptors that may flake out when we
        # bring them up and down (crbug.com/349264).
        # TODO(thieule): Remove this when the adaptor/driver is fixed
        # (crbug.com/350172).
        try:
            if self.gateway:
                logging.info('Waiting for route restore to gateway %s',
                             self.gateway)
                utils.poll_for_condition(lambda: self._is_route_ready(),
                                         exception=utils.TimeoutError(
                                             'Timed out waiting for route'),
                                         timeout=30)
        except utils.TimeoutError:
            if self.host is None:
                self._reset_usb_ethernet_device()
    except dbus.exceptions.DBusException, e:
        # The service object may disappear, we can safely ignore it.
        if e._dbus_error_name != 'org.freedesktop.DBus.Error.UnknownMethod':
            raise

    for manager, path in mm.EnumerateDevices():
        modem = manager.GetModem(path)
        version = modem.GetVersion()
        # Icera modems behave weirdly if we cancel the operation while the
        # modem is connecting or disconnecting. Work around the issue by waiting
        # until the connect/disconnect operation completes.
        # TODO(benchan): Remove this workaround once the issue is addressed
        # on the modem side.
        utils.poll_for_condition(
            lambda: not modem.IsConnectingOrDisconnecting(),
            exception=utils.TimeoutError('Timed out waiting for modem to ' +
                                         'finish connecting/disconnecting'),
            sleep_interval=1,
            timeout=30)
        modem.Enable(False)
        # Although we disable at the ModemManager level, we need to wait for
        # shill to process the disable to ensure the modem is in a stable state
        # before continuing else we may end up trying to enable a modem that
        # is still in the process of disabling.
        cm_device = conn_mgr.FindElementByPropertySubstring('Device',
                                                            'DBus.Object',
                                                            path)
        utils.poll_for_condition(
            lambda: not cm_device.GetProperties()['Powered'],
            exception=utils.TimeoutError(
                'Timed out waiting for shill device disable'),
            sleep_interval=1,
Example #13
0
    def __init__(self,
                 exe_path,
                 port=None,
                 skip_cleanup=False,
                 url_base=None,
                 extra_args=None):
        """Starts the ChromeDriver server and waits for it to be ready.

        Args:
            exe_path: path to the ChromeDriver executable
            port: server port. If None, an available port is chosen at random.
            skip_cleanup: If True, leave the server running so that remote
                          tests can run after this script ends. Default is
                          False.
            url_base: Optional base url for chromedriver.
            extra_args: List of extra arguments to forward to the chromedriver
                        binary, if any.
        Raises:
            RuntimeError if ChromeDriver fails to start
        """
        if not os.path.exists(exe_path):
            raise RuntimeError('ChromeDriver exe not found at: ' + exe_path)

        chromedriver_args = [exe_path]
        if port:
            # Allow remote connections if a port was specified
            chromedriver_args.append('--whitelisted-ips')
        else:
            port = utils.get_unused_port()
        chromedriver_args.append('--port=%d' % port)

        self.url = 'http://localhost:%d' % port
        if url_base:
            chromedriver_args.append('--url-base=%s' % url_base)
            self.url = urlparse.urljoin(self.url, url_base)

        if extra_args:
            chromedriver_args.extend(extra_args)

        # TODO(ihf): Remove references to X after M45.
        # Chromedriver will look for an X server running on the display
        # specified through the DISPLAY environment variable.
        os.environ['DISPLAY'] = X_SERVER_DISPLAY
        os.environ['XAUTHORITY'] = X_AUTHORITY

        self.bg_job = utils.BgJob(chromedriver_args,
                                  stderr_level=logging.DEBUG)
        if self.bg_job is None:
            raise RuntimeError('ChromeDriver server cannot be started')

        try:
            timeout_msg = 'Timeout on waiting for ChromeDriver to start.'
            utils.poll_for_condition(self.is_running,
                                     exception=utils.TimeoutError(timeout_msg),
                                     timeout=10,
                                     sleep_interval=.1)
        except utils.TimeoutError:
            self.close_bgjob()
            raise RuntimeError('ChromeDriver server did not start')

        logging.debug('Chrome Driver server is up and listening at port %d.',
                      port)
        if not skip_cleanup:
            atexit.register(self.close)
    def run_once(self, host, loop_count):
        """Main function to run the autotest.

        @param host: Host object representing the DUT.
        @param loop_count: Number of iteration cycles.
        @raise error.TestFail if one or more USB devices are not detected

        """
        self.host = host
        self.usb_mux = USBMuxController(self.host)

        # Make sure all USB ports are disabled prior to starting the test.
        self.usb_mux.disable_all_ports()

        self.host.servo.switch_usbkey('dut')
        self.host.servo.set('usb_mux_sel3', 'dut_sees_usbkey')

        self.set_hub_power(False)
        # Collect the USB devices directories before switching on hub
        usb_list_dir_off = self.get_usb_device_dirs()

        self.set_hub_power(True)
        # Collect the USB devices directories after switching on hub
        usb_list_dir_on = self.get_usb_device_dirs()

        lsusb_original_out = (self.host.run(
            'lsusb', ignore_status=True).stdout.strip().split('\n'))
        list_of_usb_device_dictionaries = list()
        usb_port = 0

        # Extract connected USB device information and store it in a dict.
        while usb_port < MAX_PORTS:
            usb_device_dict = {
                'usb_port': None,
                'deviceInfo': {
                    'devicePath': None,
                    'vendorId': None,
                    'productId': None,
                    'productName': None,
                    'manufacturer': None,
                    'lsusb': None
                }
            }
            usb_device_dir_list = list()
            self.usb_mux.enable_port(usb_port)
            try:
                utils.poll_for_condition(
                    lambda: self.check_lsusb_diff(lsusb_original_out),
                    exception=utils.TimeoutError('No USB device on port '
                                                 '%d' % usb_port),
                    timeout=_WAIT_DELAY,
                    sleep_interval=1)
            except utils.TimeoutError:
                logging.debug('No USB device found on port %d', usb_port)
                pass

            # Maintain list of associated dirs for each connected USB device
            for device in self.get_usb_device_dirs():
                if device not in usb_list_dir_on:
                    usb_device_dir_list.append(device)

            usb_device_dict = self.parse_device_dir_for_info(
                usb_device_dir_list, usb_device_dict)

            lsusb_diff = self.check_lsusb_diff(lsusb_original_out)
            if lsusb_diff:
                usb_device_dict['usb_port'] = usb_port
                usb_device_dict['deviceInfo']['lsusb'] = lsusb_diff[0]
                list_of_usb_device_dictionaries.append(usb_device_dict)

            self.usb_mux.disable_all_ports()
            try:
                utils.poll_for_condition(
                    lambda: not self.check_lsusb_diff(lsusb_original_out),
                    exception=utils.TimeoutError('Timed out waiting for '
                                                 'USB device to disappear.'),
                    timeout=_WAIT_DELAY,
                    sleep_interval=1)
            except utils.TimeoutError:
                logging.debug('Timed out waiting for USB device to disappear.')
                pass
            logging.info('%s', usb_device_dict)
            usb_port += 1

        if len(list_of_usb_device_dictionaries) == 0:
            # Fails if no devices detected
            raise error.TestError('No connected devices were detected. Make '
                                  'sure the devices are connected to USB_KEY '
                                  'and DUT_HUB1_USB on the servo board.')
        logging.info('Connected devices list: %s',
                     list_of_usb_device_dictionaries)

        # loop_count defines the number of times the USB peripheral details
        # should be checked and random.choice is used to randomly select one of
        # the elements from the usb device list specifying the device whose
        # details should be checked.
        for i in xrange(loop_count):
            self.check_usb_peripherals_details(
                random.choice(list_of_usb_device_dictionaries))

        logging.info('Sequence of ports tested with random picker: %s',
                     ', '.join(map(str, PORT_BEING_TESTED)))

        if TMP_FAILED_TEST_LIST:
            logging.info('Failed to verify devices on following ports: %s',
                         ', '.join(map(str, TMP_FAILED_TEST_LIST)))
            raise error.TestFail('Failed to do full device verification on '
                                 'some ports.')
    def setup(self, create_ssh_routes=True):
        """
        Enables the backchannel interface.

        @param create_ssh_routes: If True set up routes so that all existing
                SSH sessions will remain open.

        @returns True if the backchannel is already set up, or was set up by
                this call, otherwise False.

        """

        # If the backchannel interface is already up there's nothing
        # for us to do.
        if self._is_test_iface_running():
            return True

        # Retrieve the gateway for the default route.
        try:
            # Poll here until we have route information.
            # If shill was recently started, it will take some time before
            # DHCP gives us an address.
            line = utils.poll_for_condition(
                lambda: self._get_default_route(),
                exception=utils.TimeoutError(
                    'Timed out waiting for route information'),
                timeout=30)
            self.gateway, self.interface = line.strip().split(' ')

            # Retrieve list of open ssh sessions so we can reopen
            # routes afterward.
            if create_ssh_routes:
                out = self._run("netstat -tanp | grep :22 | "
                                "grep ESTABLISHED | awk '{print $5}'").stdout
                # Extract IP from IP:PORT listing. Uses set to remove
                # duplicates.
                open_ssh = list(
                    set(item.strip().split(':')[0] for item in out.split('\n')
                        if item.strip()))

            # Build a command that will set up the test interface and add
            # ssh routes in one shot. This is necessary since we'll lose
            # connectivity to a remote host between these steps.
            cmd = '%s setup %s' % (BACKCHANNEL_SCRIPT, self.interface)
            if create_ssh_routes:
                for ip in open_ssh:
                    # Add route using the pre-backchannel gateway.
                    cmd += '&& %s reach %s %s' % (BACKCHANNEL_SCRIPT, ip,
                                                  self.gateway)

            self._run(cmd)

            # Make sure we have a route to the gateway before continuing.
            logging.info('Waiting for route to gateway %s', self.gateway)
            utils.poll_for_condition(
                lambda: self._is_route_ready(),
                exception=utils.TimeoutError('Timed out waiting for route'),
                timeout=30)
        except Exception, e:
            logging.error(e)
            return False