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