blob: 6bb328672262d5b6f21b4783b9ace17ee2eaecff [file] [log] [blame]
# Copyright (c) 2013 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 logging
import os
import time
from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.cellular import cell_tools
from autotest_lib.client.cros.cellular import mm
from autotest_lib.client.cros.cellular import mm1_constants
from autotest_lib.client.cros.cellular.pseudomodem import pseudomodem_context
# Disable warning about flimflam_test_path not being used. It is used to set up
# the path to the flimflam module
# pylint: disable=W0611
from autotest_lib.client.cros import backchannel, network, flimflam_test_path
# pylint: enable=W0611
import flimflam
CONNECT_CONFIG_TIMEOUT = 120
CONNECT_SERVICE_TIMEOUT = 30
DISCONNECT_TIMEOUT = 60
TEST_MODEMS_MODULE_PATH = os.path.join(os.path.dirname(__file__), 'files',
'modems.py')
class DisconnectFailTest(object):
"""
DisconnectFailTest implements common functionality in all test cases.
"""
def __init__(self, test, pseudomodem_family):
self.test = test
self._pseudomodem_family = pseudomodem_family
def Run(self):
"""
Runs the test.
@raises test.TestFail, if |test_modem| hasn't been initialized.
"""
with pseudomodem_context.PseudoModemManagerContext(
True,
{'test-module' : TEST_MODEMS_MODULE_PATH,
'test-modem-class' : self._GetTestModemFunctorName(),
'test-modem-arg' : [self._pseudomodem_family]}):
self._RunTest()
def _GetTestModemFunctorName(self):
""" Returns the modem to be used by the pseudomodem for this test. """
raise NotImplementedError()
def _RunTest(self):
raise NotImplementedError()
class DisconnectWhileStateIsDisconnectingTest(DisconnectFailTest):
"""
Simulates a disconnect failure while the modem is still disconnecting.
Fails if the service doesn't remain connected.
"""
def _GetTestModemFunctorName(self):
return 'GetModemDisconnectWhileStateIsDisconnecting'
def _RunTest(self):
network.ResetAllModems(self.test.flim)
time.sleep(5)
# Connect to the service if not already connected.
if not self.test.IsServiceConnected():
cell_tools.ConnectToCellular(self.test.flim)
# Disconnect attempt should fail.
service = self.test.FindCellularService()
self.test.flim.DisconnectService(service=service,
wait_timeout=DISCONNECT_TIMEOUT)
# Service should remain connected.
if not self.test.IsServiceConnected():
raise error.TestError('Service should remain connected after '
'disconnect failure.')
class DisconnectWhileDisconnectInProgressTest(DisconnectFailTest):
"""
Simulates a disconnect failure on successive disconnects. Fails if the
service doesn't remain connected.
"""
def _GetTestModemFunctorName(self):
return 'GetModemDisconnectWhileDisconnectInProgress'
def _RunTest(self):
network.ResetAllModems(self.test.flim)
time.sleep(5)
# Connect to the service if not already connected.
if not self.test.IsServiceConnected():
cell_tools.ConnectToCellular(self.test.flim)
# Issue first disconnect. Service should remain connected.
service = self.test.FindCellularService()
self.test.flim.DisconnectService(service=service,
wait_timeout=DISCONNECT_TIMEOUT)
if not self.test.IsServiceConnected():
raise error.TestError('Service should remain connected after '
'first disconnect.')
# Modem state should be disconnecting.
manager, modem_path = mm.PickOneModem('')
modem = manager.GetModem(modem_path)
props = modem.GetAll(mm1_constants.I_MODEM)
if not props['State'] == mm1_constants.MM_MODEM_STATE_DISCONNECTING:
raise error.TestError('Modem should be in the DISCONNECTING state.')
# Issue second disconnect. Service should remain connected.
self.test.flim.DisconnectService(service=service,
wait_timeout=DISCONNECT_TIMEOUT)
if not self.test.IsServiceConnected():
raise error.TestError('Service should remain connected after '
'disconnect failure.')
class DisconnectFailOtherTest(DisconnectFailTest):
"""
Simulates a disconnect failure. Fails if the service doesn't disconnect.
"""
def _GetTestModemFunctorName(self):
return 'GetModemDisconnectFailOther'
def _RunTest(self):
network.ResetAllModems(self.test.flim)
time.sleep(5)
# Connect to the service if not already connected.
if not self.test.IsServiceConnected():
cell_tools.ConnectToCellular(self.test.flim)
# Disconnect attempt should fail.
service = self.test.FindCellularService()
self.test.flim.DisconnectService(service=service,
wait_timeout=DISCONNECT_TIMEOUT)
# Service should be cleaned up as if disconnect succeeded.
if not self.test.IsServiceDisconnected():
raise error.TestError('Service should be disconnected.')
class network_3GDisconnectFailure(test.test):
"""
The test uses the pseudo modem manager to simulate two failure scenarios of
a Disconnect call: failure while the modem state is DISCONNECTING and
failure while it is CONNECTED. The expected behavior of shill is to do
nothing if the modem state is DISCONNECTING and to clean up the service
otherwise.
"""
version = 1
def IsServiceConnected(self):
"""
@return True, if service is connected.
"""
service = self.FindCellularService()
properties = service.GetProperties(utf8_strings=True)
state = properties.get('State', None)
return state in ['portal', 'online']
def IsServiceDisconnected(self):
"""
@return True, if service is disconnected.
"""
service = self.FindCellularService()
properties = service.GetProperties(utf8_strings=True)
state = properties.get('State', None)
return state == 'idle'
def FindCellularService(self):
"""
Looks for a cellular service.
@return A Service DBus proxy object.
@raises error.TestError, if no cellular service can be found.
"""
service = self.flim.FindCellularService()
if not service:
raise error.TestError('Could not find cellular service.')
return service
def run_once(self, pseudomodem_family='3GPP'):
with backchannel.Backchannel():
self.flim = flimflam.FlimFlam()
self.device_manager = flimflam.DeviceManager(self.flim)
self.flim.SetDebugTags(
'dbus+service+device+modem+cellular+portal+network+'
'manager+dhcp')
tests = [
DisconnectWhileStateIsDisconnectingTest(self,
pseudomodem_family),
DisconnectWhileDisconnectInProgressTest(self,
pseudomodem_family),
DisconnectFailOtherTest(self, pseudomodem_family),
]
try:
self.device_manager.ShutdownAllExcept('cellular')
for test in tests:
test.Run()
finally:
self.device_manager.RestoreDevices()