1#!/usr/bin/env python3.4 2# 3# Copyright (C) 2018 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); you may not 6# use this file except in compliance with the License. You may obtain a copy of 7# the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14# License for the specific language governing permissions and limitations under 15# the License. 16# 17""" 18This test exercises basic scanning functionality to confirm expected behavior 19related to wlan scanning 20""" 21 22from datetime import datetime 23 24from acts import signals 25from acts.controllers.ap_lib import hostapd_ap_preset 26from acts.controllers.ap_lib import hostapd_bss_settings 27from acts.controllers.ap_lib import hostapd_constants 28from acts.controllers.ap_lib import hostapd_security 29from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 30 31 32class WlanScanTest(WifiBaseTest): 33 """WLAN scan test class. 34 35 Test Bed Requirement: 36 * One or more Fuchsia devices 37 * Several Wi-Fi networks visible to the device, including an open Wi-Fi 38 network or a onHub/GoogleWifi 39 """ 40 41 def setup_class(self): 42 super().setup_class() 43 44 self.access_point = self.access_points[0] 45 self.start_access_point = False 46 for fd in self.fuchsia_devices: 47 fd.configure_wlan(association_mechanism='drivers') 48 if "AccessPoint" in self.user_params: 49 # This section sets up the config that could be sent to the AP if 50 # the AP is needed. The reasoning is since ACTS already connects 51 # to the AP if it is in the config, generating the config in memory 52 # has no over head is used if need by the test if one of the ssids 53 # needed for the test is not included in the config. The logic 54 # here creates 2 ssids on each radio, 5ghz and 2.4ghz, with an 55 # open, no security network and one that is wpa2, for a total of 4 56 # networks. However, if all of the ssids are specified in the 57 # the config will never be written to the AP and the AP will not be 58 # brought up. For more information about how to configure the 59 # hostapd config info, see the hostapd libraries, which have more 60 # documentation. 61 bss_settings_2g = [] 62 bss_settings_5g = [] 63 open_network = self.get_open_network(False, []) 64 self.open_network_2g = open_network['2g'] 65 self.open_network_5g = open_network['5g'] 66 wpa2_settings = self.get_psk_network(False, []) 67 self.wpa2_network_2g = wpa2_settings['2g'] 68 self.wpa2_network_5g = wpa2_settings['5g'] 69 bss_settings_2g.append( 70 hostapd_bss_settings.BssSettings( 71 name=self.wpa2_network_2g['SSID'], 72 ssid=self.wpa2_network_2g['SSID'], 73 security=hostapd_security.Security( 74 security_mode=self.wpa2_network_2g["security"], 75 password=self.wpa2_network_2g["password"]))) 76 bss_settings_5g.append( 77 hostapd_bss_settings.BssSettings( 78 name=self.wpa2_network_5g['SSID'], 79 ssid=self.wpa2_network_5g['SSID'], 80 security=hostapd_security.Security( 81 security_mode=self.wpa2_network_5g["security"], 82 password=self.wpa2_network_5g["password"]))) 83 self.ap_2g = hostapd_ap_preset.create_ap_preset( 84 iface_wlan_2g=self.access_point.wlan_2g, 85 iface_wlan_5g=self.access_point.wlan_5g, 86 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G, 87 ssid=self.open_network_2g['SSID'], 88 bss_settings=bss_settings_2g) 89 self.ap_5g = hostapd_ap_preset.create_ap_preset( 90 iface_wlan_2g=self.access_point.wlan_2g, 91 iface_wlan_5g=self.access_point.wlan_5g, 92 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G, 93 ssid=self.open_network_5g['SSID'], 94 bss_settings=bss_settings_5g) 95 96 if "wlan_open_network_2g" in self.user_params: 97 self.open_network_2g = self.user_params.get("wlan_open_network_2g") 98 elif "AccessPoint" in self.user_params: 99 self.start_access_point_2g = True 100 else: 101 raise Exception('Missing parameter in config ' 102 '(wlan_open_network_2g)') 103 104 if "wlan_open_network_5g" in self.user_params: 105 self.open_network_5g = self.user_params.get("wlan_open_network_5g") 106 elif "AccessPoint" in self.user_params: 107 self.start_access_point_5g = True 108 else: 109 raise Exception('Missing parameter in config ' 110 '(wlan_open_network_5g)') 111 112 if "wlan_wpa2_network_2g" in self.user_params: 113 self.wpa2_network_2g = self.user_params.get("wlan_wpa2_network_2g") 114 elif "AccessPoint" in self.user_params: 115 self.start_access_point_2g = True 116 else: 117 raise Exception('Missing parameter in config ' 118 '(wlan_wpa2_network_2g)') 119 120 if "wlan_wpa2_network_5g" in self.user_params: 121 self.wpa2_network_5g = self.user_params.get("wlan_wpa2_network_5g") 122 elif "AccessPoint" in self.user_params: 123 self.start_access_point_5g = True 124 else: 125 raise Exception('Missing parameter in config ' 126 '(wlan_wpa2_network_5g)') 127 128 # Only bring up the APs that are needed for the test. Each ssid is 129 # randomly generated so there is no chance of re associating to a 130 # previously saved ssid on the device. 131 if self.start_access_point_2g: 132 self.start_access_point = True 133 self.access_point.start_ap(hostapd_config=self.ap_2g) 134 if self.start_access_point_5g: 135 self.start_access_point = True 136 self.access_point.start_ap(hostapd_config=self.ap_5g) 137 138 def setup_test(self): 139 for fd in self.fuchsia_devices: 140 # stub for setting up all the fuchsia devices in the testbed. 141 pass 142 143 def teardown_test(self): 144 for fd in self.fuchsia_devices: 145 fd.sl4f.wlan_lib.wlanDisconnect() 146 147 def teardown_class(self): 148 if self.start_access_point: 149 self.download_ap_logs() 150 self.access_point.stop_all_aps() 151 152 def on_fail(self, test_name, begin_time): 153 for fd in self.fuchsia_devices: 154 super().on_device_fail(fd, test_name, begin_time) 155 fd.configure_wlan(association_mechanism='drivers') 156 157 """Helper Functions""" 158 159 def check_connect_response(self, connection_response): 160 """ Checks the result of connecting to a wlan. 161 Args: 162 connection_response: The response from SL4F after attempting 163 to connect to a wlan. 164 """ 165 if connection_response.get("error") is None: 166 # the command did not get an error response - go ahead and 167 # check the result 168 connection_result = connection_response.get("result") 169 if connection_result: 170 self.log.info("connection to network successful") 171 else: 172 # ideally, we would have the actual error... but logging 173 # here to cover that error case 174 raise signals.TestFailure("Connect call failed, aborting test") 175 else: 176 # the response indicates an error - log and raise failure 177 raise signals.TestFailure("Aborting test - Connect call failed " 178 "with error: %s" % 179 connection_response.get("error")) 180 181 def scan_while_connected(self, wlan_network_params, fd): 182 """ Connects to as specified network and initiates a scan 183 Args: 184 wlan_network_params: A dictionary containing wlan 185 infomation. 186 fd: The fuchsia device to connect to the wlan. 187 """ 188 target_ssid = wlan_network_params['SSID'] 189 self.log.info("got the ssid! %s", target_ssid) 190 target_pwd = None 191 if 'password' in wlan_network_params: 192 target_pwd = wlan_network_params['password'] 193 194 bss_scan_response = fd.sl4f.wlan_lib.wlanScanForBSSInfo().get('result') 195 connection_response = fd.sl4f.wlan_lib.wlanConnectToNetwork( 196 target_ssid, 197 bss_scan_response[target_ssid][0], 198 target_pwd=target_pwd) 199 self.check_connect_response(connection_response) 200 self.basic_scan_request(fd) 201 202 def basic_scan_request(self, fd): 203 """ Initiates a basic scan on a Fuchsia device 204 Args: 205 fd: A fuchsia device 206 """ 207 start_time = datetime.now() 208 209 scan_response = fd.sl4f.wlan_lib.wlanStartScan() 210 211 # first check if we received an error 212 if scan_response.get("error") is None: 213 # the scan command did not get an error response - go ahead 214 # and check for scan results 215 scan_results = scan_response["result"] 216 else: 217 # the response indicates an error - log and raise failure 218 raise signals.TestFailure("Aborting test - scan failed with " 219 "error: %s" % scan_response.get("error")) 220 221 self.log.info("scan contained %d results", len(scan_results)) 222 223 total_time_ms = (datetime.now() - start_time).total_seconds() * 1000 224 self.log.info("scan time: %d ms", total_time_ms) 225 226 if len(scan_results) > 0: 227 raise signals.TestPass(details="", 228 extras={"Scan time": "%d" % total_time_ms}) 229 else: 230 raise signals.TestFailure("Scan failed or did not " 231 "find any networks") 232 233 """Tests""" 234 235 def test_basic_scan_request(self): 236 """Verify a general scan trigger returns at least one result""" 237 for fd in self.fuchsia_devices: 238 self.basic_scan_request(fd) 239 240 def test_scan_while_connected_open_network_2g(self): 241 for fd in self.fuchsia_devices: 242 self.scan_while_connected(self.open_network_2g, fd) 243 244 def test_scan_while_connected_wpa2_network_2g(self): 245 for fd in self.fuchsia_devices: 246 self.scan_while_connected(self.wpa2_network_2g, fd) 247 248 def test_scan_while_connected_open_network_5g(self): 249 for fd in self.fuchsia_devices: 250 self.scan_while_connected(self.open_network_5g, fd) 251 252 def test_scan_while_connected_wpa2_network_5g(self): 253 for fd in self.fuchsia_devices: 254 self.scan_while_connected(self.wpa2_network_5g, fd) 255