blob: cf0c3ddff2bb7a93e16c51ca966f2032d9160bf7 [file] [log] [blame]
# Copyright (c) 2011 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 time
import urlparse
from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import network
from autotest_lib.client.cros.cellular import cell_tools, mm
# Default timeouts in seconds
CONNECT_TIMEOUT = 120
DISCONNECT_TIMEOUT = 60
SHILL_LOG_SCOPES = 'cellular+dbus+device+dhcp+manager+modem+portal+service'
class network_3GSmokeTest(test.test):
"""
Tests that 3G modem can connect to the network
The test attempts to connect using the 3G network. The test then
disconnects from the network, and verifies that the modem still
responds to modem manager DBUS API calls. It repeats the
connect/disconnect sequence several times.
"""
version = 1
# TODO(benchan): Migrate to use ShillProxy when ShillProxy provides a
# similar method.
def DisconnectFrom3GNetwork(self, disconnect_timeout):
"""Attempts to disconnect from a 3G network.
@param disconnect_timeout: Timeout in seconds for disconnecting from
the network.
@raises error.TestFail if it fails to disconnect from the network before
timeout.
@raises error.TestError If no cellular service is available.
"""
logging.info('DisconnectFrom3GNetwork')
service = self.test_env.flim.FindCellularService()
if not service:
raise error.TestError('Could not find cellular service.')
success, status = self.test_env.flim.DisconnectService(
service=service,
wait_timeout=disconnect_timeout)
if not success:
raise error.TestFail('Could not disconnect: %s.' % status)
def GetModemInfo(self):
"""Find all modems attached and return an dictionary of information.
This returns a bunch of information for each modem attached to
the system. In practice collecting all this information
sometimes fails if a modem is left in an odd state, so we
collect as many things as we can to ensure that the modem is
responding correctly.
@return A dictionary of information for each modem path.
"""
results = {}
devices = mm.EnumerateDevices()
print 'Devices: %s' % ', '.join([p for _, p in devices])
for manager, path in devices:
modem = manager.GetModem(path)
results[path] = modem.GetModemProperties()
return results
def run_once_internal(self):
"""
Executes the test.
"""
# Get information about all the modems
old_modem_info = self.GetModemInfo()
for _ in xrange(self.connect_count):
service, state = cell_tools.ConnectToCellular(self.test_env.flim,
CONNECT_TIMEOUT)
if state == 'portal':
url_pattern = ('https://quickaccess.verizonwireless.com/'
'images_b2c/shared/nav/'
'vz_logo_quickaccess.jpg?foo=%d')
bytes_to_fetch = 4476
else:
url_pattern = network.FETCH_URL_PATTERN_FOR_TEST
bytes_to_fetch = 64 * 1024
device = self.test_env.flim.GetObjectInterface(
'Device', service.GetProperties()['Device'])
interface = device.GetProperties()['Interface']
logging.info('Expected interface for %s: %s',
service.object_path, interface)
network.CheckInterfaceForDestination(
urlparse.urlparse(url_pattern).hostname,
interface)
fetch_time = network.FetchUrl(url_pattern, bytes_to_fetch,
self.fetch_timeout)
self.write_perf_keyval({
'seconds_3G_fetch_time': fetch_time,
'bytes_3G_bytes_received': bytes_to_fetch,
'bits_second_3G_speed': 8 * bytes_to_fetch / fetch_time
})
self.DisconnectFrom3GNetwork(disconnect_timeout=DISCONNECT_TIMEOUT)
# Verify that we can still get information for all the modems
logging.info('Old modem info: %s', ', '.join(old_modem_info))
new_modem_info = self.GetModemInfo()
if len(new_modem_info) != len(old_modem_info):
logging.info('New modem info: %s', ', '.join(new_modem_info))
raise error.TestFail('Test shutdown: '
'failed to leave modem in working state.')
if self.sleep_kludge:
logging.info('Sleeping for %.1f seconds', self.sleep_kludge)
time.sleep(self.sleep_kludge)
def run_once(self, test_env, connect_count=5, sleep_kludge=5,
fetch_timeout=120):
with test_env:
self.test_env = test_env
self.connect_count = connect_count
self.sleep_kludge = sleep_kludge
self.fetch_timeout = fetch_timeout
self.run_once_internal()