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