• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2018 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6from collections import namedtuple
7
8from autotest_lib.client.bin import utils
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.cros.networking.chrome_testing \
11        import chrome_networking_test_context as cntc
12from autotest_lib.client.cros.networking.chrome_testing \
13        import chrome_networking_test_api as cnta
14
15
16NETWORK_TEST_EXTENSION_PATH = cntc.NETWORK_TEST_EXTENSION_PATH
17
18
19class ChromeEnterpriseNetworkContext(object):
20    """
21    This class contains all the Network API methods required for
22    Enterprise Network WiFi tests.
23
24    """
25    SHORT_TIMEOUT = 20
26    LONG_TIMEOUT = 120
27
28
29    def __init__(self, browser=None):
30        testing_context = cntc.ChromeNetworkingTestContext()
31        testing_context.setup(browser)
32        self.chrome_net_context = cnta.ChromeNetworkProvider(testing_context)
33        self.enable_wifi_on_dut()
34
35
36    def _extract_wifi_network_info(self, networks_found_list):
37        """
38        Extract the required Network params from list of Networks found.
39
40        Filter out the required network parameters such Network Name/SSID,
41        GUID, connection state and security type of each of the networks in
42        WiFi range of the DUT.
43
44        @param networks_found_list: Network information returned as a result
45                of the getVisibleNetworks api.
46
47        @returns: Formatted list of namedtuples containing the
48                required network parameters.
49
50        """
51        network_info_list = []
52        network_info = namedtuple(
53                'NetworkInfo', 'name guid connectionState security')
54
55        for network in networks_found_list:
56            network_data = network_info(
57                                name=network['Name'],
58                                guid=network['GUID'],
59                                connectionState=network['ConnectionState'],
60                                security=network['WiFi']['Security'])
61            network_info_list.append(network_data)
62        return network_info_list
63
64
65    def list_networks(self):
66        """@returns: List of available WiFi networks."""
67        return self._extract_wifi_network_info(
68                self.chrome_net_context.get_wifi_networks())
69
70
71    def disable_network_device(self, network):
72        """
73        Disable given network device.
74
75        This will fail if called multiple times in a test. Use the version in
76        'chrome_networking_test_api' if this is the case.
77
78        @param network: string name of the network device to be disabled.
79                Options include 'WiFi', 'Cellular', and 'Ethernet'.
80
81        """
82        logging.info('Disabling: %s', network)
83        disable_network_result = self.chrome_net_context.\
84                _chrome_testing.call_test_function_async(
85                    'disableNetworkDevice',
86                    '"' + network + '"')
87
88
89    def _get_network_info(self, ssid):
90        """
91        Returns the Network parameters for a specific network.
92
93        @param ssid: SSID of the network.
94
95        @returns: The NetworkInfo tuple containing the network parameters.
96                Returns None if network info for the SSID was not found.
97
98        """
99        networks_in_range = self._extract_wifi_network_info(
100                self.chrome_net_context.get_wifi_networks())
101        logging.debug('Network info of all the networks in WiFi'
102                'range of DUT:%r', networks_in_range)
103        for network_info in networks_in_range:
104            if network_info.name == ssid:
105                return network_info
106        return None
107
108
109    def _get_network_connection_state(self, ssid):
110        """
111        Returns the connection State of the network.
112
113        @returns: Connection State for the SSID.
114
115        """
116        network_info = self._get_network_info(ssid)
117        if network_info is None:
118            return None
119        return network_info.connectionState
120
121
122    def connect_to_network(self, ssid):
123        """
124        Triggers a manual connect to the network using networkingPrivate API.
125
126        @param ssid: The ssid that the connection request is initiated for.
127
128        @raises error.TestFail: If the WiFi network is out of range or the
129            DUT cannot manually connect to the network.
130
131        """
132        if not self.is_network_in_range(ssid):
133            raise error.TestFail(
134                    "The SSID: %r is not in WiFi range of the DUT" % ssid)
135
136        network_to_connect = self._get_network_info(ssid)
137        logging.info("Triggering a manual connect to network SSID: %r, GUID %r",
138                network_to_connect.name, network_to_connect.guid)
139
140        # TODO(krishnargv): Replace below code with the
141        # self.chrome_net_context.connect_to_network(network_to_connect) method.
142        new_network_connect = self.chrome_net_context._chrome_testing.\
143                call_test_function(
144                self.LONG_TIMEOUT,
145                'connectToNetwork',
146                '"%s"'% network_to_connect.guid)
147        logging.debug("Manual network connection status: %r",
148                new_network_connect['status'])
149        if new_network_connect['status'] == 'chrome-test-call-status-failure':
150            raise error.TestFail(
151                    'Could not connect to %s network. Error returned by '
152                    'chrome.networkingPrivate.startConnect API: %s' %
153                    (network_to_connect.name, new_network_connect['error']))
154
155
156    def disconnect_from_network(self, ssid):
157        """
158        Triggers a disconnect from the network using networkingPrivate API.
159
160        @param ssid: The ssid that the disconnection request is initiated for.
161
162        @raises error.TestFail: If the WiFi network is not in WiFi range of the
163                DUT or if the DUT cannot manually disconnect from the SSID.
164
165        """
166        if not self.is_network_in_range(ssid):
167            raise error.TestFail(
168                    "The SSID: %r is not in WiFi range of the DUT" % ssid)
169
170        network_to_disconnect = self._get_network_info(ssid)
171        logging.info("Triggering a disconnect from network SSID: %r, GUID %r",
172                network_to_disconnect.name, network_to_disconnect.guid)
173
174        new_network_disconnect = self.chrome_net_context._chrome_testing.\
175                call_test_function(
176                self.LONG_TIMEOUT,
177                'disconnectFromNetwork',
178                '"%s"'% network_to_disconnect.guid)
179        logging.debug("Manual network disconnection status: %r",
180                new_network_disconnect['status'])
181        if (new_network_disconnect['status'] ==
182                'chrome-test-call-status-failure'):
183            raise error.TestFail(
184                    'Could not disconnect from %s network. Error returned by '
185                    'chrome.networkingPrivate.startDisconnect API: %s' %
186                    (network_to_disconnect.name,
187                    new_network_disconnect['error']))
188
189
190    def enable_wifi_on_dut(self):
191        """Enable the WiFi interface on the DUT if it is disabled."""
192        enabled_devices = self.chrome_net_context.get_enabled_devices()
193        if self.chrome_net_context.WIFI_DEVICE not in enabled_devices:
194            self.chrome_net_context.enable_network_device(
195                self.chrome_net_context.WIFI_DEVICE)
196
197
198    def is_network_in_range(self, ssid, wait_time=0):
199        """
200        Returns True if the WiFi network is within WiFi range of the DUT.
201
202        @param ssid: The SSID of the network.
203        @param wait_time: Seconds to wait for SSID to appear.
204
205        @returns: True if the network/ssid is within WiFi range of the DUT,
206                else returns False
207
208        """
209        try:
210            return utils.poll_for_condition(
211                    lambda: self._get_network_info(ssid) is not None,
212                    timeout=wait_time)
213        except utils.TimeoutError:
214            return False
215
216
217    def is_network_connected(self, ssid):
218        """
219        Return True if the DUT is connected to the Network.
220
221        Returns True if the DUT is connected to the network. Waits for a
222        a short time if the DUT is in a connecting state.
223
224        @param ssid: The SSID of the network.
225
226        @returns: True if the DUT is connected to the network/ssid,
227                else returns False
228
229        @raises error.TestFail: If the DUT is stuck in the connecting state.
230
231        """
232        utils.poll_for_condition(
233                lambda: (self._get_network_connection_state(ssid)
234                         != 'Connecting'),
235                exception=error.TestFail('Device stuck in connecting state'),
236                timeout=self.SHORT_TIMEOUT)
237        try:
238            utils.poll_for_condition(
239                    lambda: (self._get_network_connection_state(ssid)
240                             == 'Connected'),
241                    timeout=self.SHORT_TIMEOUT)
242            return True
243        except utils.TimeoutError:
244            logging.debug("Connection state for SSID-%r is: %r",
245                          ssid, self._get_network_connection_state(ssid))
246            return False
247