普通文本  |  100行  |  3.31 KB

# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import dbus
import logging

from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.cellular.pseudomodem import modem_3gpp
from autotest_lib.client.cros.cellular.pseudomodem import modem_cdma
from autotest_lib.client.cros.cellular.pseudomodem import pm_errors
from autotest_lib.client.cros.cellular.pseudomodem import utils as pm_utils
from autotest_lib.client.cros.networking import cellular_proxy
from autotest_lib.client.cros.networking import shill_proxy


def _GetModemSuperClass(family):
    """
    Obtains the correct Modem base class to use for the given family.

    @param family: The modem family. Should be one of |3GPP|/|CDMA|.
    @returns: The relevant Modem base class.
    @raises error.TestError, if |family| is not one of '3GPP' or 'CDMA'.

    """
    if family == '3GPP':
        return modem_3gpp.Modem3gpp
    elif family == 'CDMA':
        return modem_cdma.ModemCdma
    else:
        raise error.TestError('Invalid pseudomodem family: %s', family)


def GetFailConnectModem(family):
    """
    Returns the correct modem subclass based on |family|.

    @param family: A string containing either '3GPP' or 'CDMA'.

    """
    modem_class = _GetModemSuperClass(family)

    class FailConnectModem(modem_class):
        """Custom fake Modem that always fails to connect."""
        @pm_utils.log_dbus_method(return_cb_arg='return_cb',
                                  raise_cb_arg='raise_cb')
        def Connect(self, properties, return_cb, raise_cb):
            logging.info('Connect call will fail.')
            raise_cb(pm_errors.MMCoreError(pm_errors.MMCoreError.FAILED))

    return FailConnectModem()


class cellular_ConnectFailure(test.test):
    """
    Tests that 3G connect failures are handled by shill properly.

    This test will fail if a connect failure does not immediately cause the
    service to enter the Failed state.

    """
    version = 1

    def _connect_to_3g_network(self, config_timeout):
        """
        Attempts to connect to a 3G network using shill.

        @param config_timeout: Timeout (in seconds) before giving up on
                               connect.

        @raises: error.TestFail if connection fails.

        """
        service = self.test_env.shill.find_cellular_service_object()

        try:
            service.Connect()
        except dbus.DBusException as e:
            logging.info('Expected error: %s', e)

        _, state, _ = self.test_env.shill.wait_for_property_in(
                service,
                shill_proxy.ShillProxy.SERVICE_PROPERTY_STATE,
                ('ready', 'portal', 'online', 'failure'),
                config_timeout)

        if state != 'failure':
            raise error.TestFail('Service state should be failure not %s' %
                                 state)


    def run_once(self, test_env, connect_count=4):
        with test_env:
            self.test_env = test_env
            for count in xrange(connect_count):
                logging.info('Connect attempt %d', count + 1)
                self._connect_to_3g_network(config_timeout=
                        cellular_proxy.CellularProxy.SERVICE_CONNECT_TIMEOUT)