12fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
22fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan# Use of this source code is governed by a BSD-style license that can be
32fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan# found in the LICENSE file.
42fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
52fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanimport logging
62fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanimport time
72fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanimport urlparse
82fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
92fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanfrom autotest_lib.client.bin import test
102fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanfrom autotest_lib.client.common_lib import error
112fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanfrom autotest_lib.client.cros import backchannel, network
122fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanfrom autotest_lib.client.cros.cellular import cell_tools
131f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wileyfrom autotest_lib.client.cros.networking import shill_context
142fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
151f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley# Import 'flimflam_test_path' first in order to import 'flimflam'.
161f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley# pylint: disable=W0611
172fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanfrom autotest_lib.client.cros import flimflam_test_path
181f89fd2f9f2010e732a87ed3c8f7f25777862c59Christopher Wiley# pylint: enable=W0611
192fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanimport flimflam
202fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
212fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
222fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan# TODO(benchan): Use the log scopes defined in ShillProxy after
232fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan# migrating from FlimFlam to ShillProxy.
242fd02a548211ecaec047ab36f21b576e3decafa8Ben ChanSHILL_LOG_SCOPES = 'dbus+device+dhcp+manager+portal+service+wimax'
252fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
262fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
272fd02a548211ecaec047ab36f21b576e3decafa8Ben Chanclass network_WiMaxSmoke(test.test):
282fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    """Verifies that a WiMAX module can connect to a WiMAX network.
292fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
302fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    The test attempts to connect to a WiMAX network. It assumes that a WiMAX
312fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    module is plugged in to the DUT and a WiMAX network is available. It repeats
322fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    the connect/disconnect sequence several times. Each time after connecting to
332fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    the WiMAX network, it fetches some data from a URL to confirm the WiMAX
342fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    connectivity.
352fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
362fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    """
372fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    version = 1
382fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
392fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    def _connect_service(self):
402fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        """Connects the WiMAX service under test.
412fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
422fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        Raises:
432fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            error.TestFail if it fails to connect the service before timeout.
442fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
452fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        """
462fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        logging.info('ConnectService: %s', self._service.object_path)
472fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
482fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        service_properties = self._service.GetProperties()
492fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        parameters = {
502fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            'Type': 'wimax',
512fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            'Name': str(service_properties['Name']),
522fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            'NetworkId': str(service_properties['NetworkId']),
532fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            'EAP.Identity': 'test',
542fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            'EAP.Password': 'test',
552fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        }
562fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        logging.info('parameters : %s', parameters)
572fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._flim.manager.ConfigureService(parameters)
582fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
592fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        success, status = self._flim.ConnectService(
602fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            service=self._service,
612fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            config_timeout=self._connect_timeout)
622fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        if not success:
632fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            raise error.TestFail('Could not connect: %s.' % status)
642fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
652fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        logging.info('Waiting for portal or online state.')
662fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        portal_or_online_states = ['portal', 'online']
672fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        state = self._flim.WaitForServiceState(
682fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            service=self._service,
692fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            expected_states=portal_or_online_states,
702fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            timeout=self._connect_timeout,
712fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            ignore_failure=True)[0]
722fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        if not state in portal_or_online_states:
732fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            raise error.TestFail('Still in state %s' % state)
742fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
752fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
762fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    def _disconnect_service(self):
772fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        """Disconnects the WiMAX service under test.
782fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
792fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        Raises:
802fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            error.TestFail if it fails to disconnect the service before
812fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                timeout.
822fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
832fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        """
842fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        logging.info('DisonnectService: %s', self._service.object_path)
852fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
862fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        success, status = self._flim.DisconnectService(
872fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            service=self._service,
882fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            wait_timeout=self._disconnect_timeout)
892fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        if not success:
902fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            raise error.TestFail('Could not disconnect: %s.' % status)
912fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
922fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
932fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    def _test_connectivity(self):
942fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        """Tests network connectivity over WiMAX.
952fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
962fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        Test network connectivity over WiMAX as follows:
972fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            - Connecting the WiMAX service
982fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            - Fetching data from a URL
992fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            - Disconnecting the WiMAX service
1002fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1012fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        Raises:
1022fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            error.TestFail if any of the steps above fails.
1032fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1042fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        """
1052fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        if self._sleep_kludge:
1062fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            logging.info('Sleeping for %.1f seconds', self._sleep_kludge)
1072fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            time.sleep(self._sleep_kludge)
1082fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1092fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._connect_service()
1102fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1112fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        device = self._flim.GetObjectInterface(
1122fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            'Device', self._service.GetProperties()['Device'])
1132fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        interface = device.GetProperties()['Interface']
1142fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        logging.info('Expected interface for %s: %s',
1152fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                     self._service.object_path, interface)
1162fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        network.CheckInterfaceForDestination(
1172fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            urlparse.urlparse(self._fetch_url_pattern).hostname,
1182fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            interface)
1192fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1202fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        fetch_time = network.FetchUrl(self._fetch_url_pattern,
1212fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                                      self._bytes_to_fetch,
1222fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                                      self._fetch_timeout)
1232fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self.write_perf_keyval({
1242fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            'seconds_WiMAX_fetch_time': fetch_time,
1252fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            'bytes_WiMAX_bytes_received': self._bytes_to_fetch,
1262fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            'bits_second_WiMAX_speed': 8 * self._bytes_to_fetch / fetch_time
1272fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        })
1282fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1292fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._disconnect_service()
1302fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1312fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1322fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan    def run_once(self, **kwargs):
1332fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        # Number of connectivity test runs.
1342fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._connect_count = kwargs.get('connect_count', 5)
1352fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1362fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        # Number of seconds to sleep between connect and disconnect operations.
1372fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._sleep_kludge = kwargs.get('sleep_kludge', 5)
1382fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1392fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        # URL pattern to fetch data from during each connectivity test run.
1402fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._fetch_url_pattern = \
1412fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            kwargs.get('fetch_url_pattern', network.FETCH_URL_PATTERN_FOR_TEST)
1422fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1432fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        # Timeout in seconds for connect and disconnect operations, and
1442fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        # fetching data from a URL.
1452fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._connect_timeout = kwargs.get('connect_timeout', 10)
1462fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._disconnect_timeout = kwargs.get('disconnect_timeout', 10)
1472fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._fetch_timeout = kwargs.get('fetch_timeout', 120)
1482fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1492fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        # Number of bytes to fetch during each connectivity test run.
1502fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        self._bytes_to_fetch = kwargs.get('bytes_to_fetch', 64 * 1024)
1512fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1522fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan        with backchannel.Backchannel():
1532fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan            with cell_tools.OtherDeviceShutdownContext('wimax'):
1542fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                # TODO(benchan): Replace FlimFlam with ShillProxy.
1552fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                self._flim = flimflam.FlimFlam()
1562fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                self._flim.SetDebugTags(SHILL_LOG_SCOPES)
1572fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                self._service = self._flim.FindWimaxService()
1582fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                if not self._service:
1592fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                    raise error.TestError('Could not find a WiMAX service.')
1602fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan
1612fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                with shill_context.ServiceAutoConnectContext(
1622fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                    self._flim.FindWimaxService, False):
1632fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                    self._disconnect_service()
1642fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                    for _ in xrange(self._connect_count):
1652fd02a548211ecaec047ab36f21b576e3decafa8Ben Chan                        self._test_connectivity()
166