1#!/usr/bin/env python3 2# 3# Copyright 2020 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of 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, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import itertools 18import re 19 20from acts import utils 21from acts.controllers.ap_lib.hostapd_security import Security 22from acts.controllers.ap_lib import hostapd_constants 23from acts.controllers.ap_lib import hostapd_config 24from acts.test_utils.abstract_devices.wlan_device import create_wlan_device 25from acts.test_utils.abstract_devices.wlan_device_lib.AbstractDeviceWlanDeviceBaseTest import AbstractDeviceWlanDeviceBaseTest 26from acts.test_utils.abstract_devices.utils_lib.wlan_utils import validate_setup_ap_and_associate 27from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest 28from acts.utils import rand_ascii_str 29 30# AC Capabilities 31""" 32Capabilities Not Supported on Whirlwind: 33 - Supported Channel Width ([VHT160], [VHT160-80PLUS80]): 160mhz and 80+80 34 unsupported 35 - SU Beamformer [SU-BEAMFORMER] 36 - SU Beamformee [SU-BEAMFORMEE] 37 - MU Beamformer [MU-BEAMFORMER] 38 - MU Beamformee [MU-BEAMFORMEE] 39 - BF Antenna ([BF-ANTENNA-2], [BF-ANTENNA-3], [BF-ANTENNA-4]) 40 - Rx STBC 2, 3, & 4 ([RX-STBC-12],[RX-STBC-123],[RX-STBC-124]) 41 - VHT Link Adaptation ([VHT-LINK-ADAPT2],[VHT-LINK-ADAPT3]) 42 - VHT TXOP Power Save [VHT-TXOP-PS] 43 - HTC-VHT [HTC-VHT] 44""" 45VHT_MAX_MPDU_LEN = [ 46 hostapd_constants.AC_CAPABILITY_MAX_MPDU_7991, 47 hostapd_constants.AC_CAPABILITY_MAX_MPDU_11454, '' 48] 49RXLDPC = [hostapd_constants.AC_CAPABILITY_RXLDPC, ''] 50SHORT_GI_80 = [hostapd_constants.AC_CAPABILITY_SHORT_GI_80, ''] 51TX_STBC = [hostapd_constants.AC_CAPABILITY_TX_STBC_2BY1, ''] 52RX_STBC = [hostapd_constants.AC_CAPABILITY_RX_STBC_1, ''] 53MAX_A_MPDU = [ 54 hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP0, 55 hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP1, 56 hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP2, 57 hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP3, 58 hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP4, 59 hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP5, 60 hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP6, 61 hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP7, '' 62] 63RX_ANTENNA = [hostapd_constants.AC_CAPABILITY_RX_ANTENNA_PATTERN, ''] 64TX_ANTENNA = [hostapd_constants.AC_CAPABILITY_TX_ANTENNA_PATTERN, ''] 65 66# Default 11N Capabilities 67N_CAPABS_40MHZ = [ 68 hostapd_constants.N_CAPABILITY_LDPC, hostapd_constants.N_CAPABILITY_SGI20, 69 hostapd_constants.N_CAPABILITY_RX_STBC1, 70 hostapd_constants.N_CAPABILITY_SGI20, hostapd_constants.N_CAPABILITY_SGI40, 71 hostapd_constants.N_CAPABILITY_MAX_AMSDU_7935, 72 hostapd_constants.N_CAPABILITY_HT40_PLUS 73] 74 75N_CAPABS_20MHZ = [ 76 hostapd_constants.N_CAPABILITY_LDPC, hostapd_constants.N_CAPABILITY_SGI20, 77 hostapd_constants.N_CAPABILITY_RX_STBC1, 78 hostapd_constants.N_CAPABILITY_SGI20, 79 hostapd_constants.N_CAPABILITY_MAX_AMSDU_7935, 80 hostapd_constants.N_CAPABILITY_HT20 81] 82 83# Default wpa2 profile. 84WPA2_SECURITY = Security(security_mode=hostapd_constants.WPA2_STRING, 85 password=rand_ascii_str(20), 86 wpa_cipher=hostapd_constants.WPA2_DEFAULT_CIPER, 87 wpa2_cipher=hostapd_constants.WPA2_DEFAULT_CIPER) 88 89 90def generate_test_name(settings): 91 """Generates a test name string based on the ac_capabilities for 92 a test case. 93 94 Args: 95 settings: a dict with the test settings (bandwidth, security, ac_capabs) 96 97 Returns: 98 A string test case name 99 """ 100 chbw = settings['chbw'] 101 sec = 'wpa2' if settings['security'] else 'open' 102 ret = [] 103 for cap in hostapd_constants.AC_CAPABILITIES_MAPPING.keys(): 104 if cap in settings['ac_capabilities']: 105 ret.append(hostapd_constants.AC_CAPABILITIES_MAPPING[cap]) 106 return 'test_11ac_%smhz_%s_%s' % (chbw, sec, ''.join(ret)) 107 108 109# 6912 test cases 110class WlanPhyCompliance11ACTest(AbstractDeviceWlanDeviceBaseTest): 111 """Tests for validating 11ac PHYS. 112 113 Test Bed Requirement: 114 * One Android device or Fuchsia device 115 * One Access Point 116 """ 117 def __init__(self, controllers): 118 WifiBaseTest.__init__(self, controllers) 119 self.tests = [ 120 'test_11ac_capabilities_20mhz_open', 121 'test_11ac_capabilities_40mhz_open', 122 'test_11ac_capabilities_80mhz_open', 123 'test_11ac_capabilities_20mhz_wpa2', 124 'test_11ac_capabilities_40mhz_wpa2', 125 'test_11ac_capabilities_80mhz_wpa2' 126 ] 127 if 'debug_11ac_tests' in self.user_params: 128 self.tests.append('test_11ac_capabilities_debug') 129 130 def setup_class(self): 131 super().setup_class() 132 if 'dut' in self.user_params: 133 if self.user_params['dut'] == 'fuchsia_devices': 134 self.dut = create_wlan_device(self.fuchsia_devices[0]) 135 elif self.user_params['dut'] == 'android_devices': 136 self.dut = create_wlan_device(self.android_devices[0]) 137 else: 138 raise ValueError('Invalid DUT specified in config. (%s)' % 139 self.user_params['dut']) 140 else: 141 self.dut = create_wlan_device(self.android_devices[0]) 142 143 self.access_point = self.access_points[0] 144 self.android_devices = getattr(self, 'android_devices', []) 145 self.access_point.stop_all_aps() 146 147 def setup_test(self): 148 for ad in self.android_devices: 149 ad.droid.wakeLockAcquireBright() 150 ad.droid.wakeUpNow() 151 self.dut.wifi_toggle_state(True) 152 153 def teardown_test(self): 154 for ad in self.android_devices: 155 ad.droid.wakeLockRelease() 156 ad.droid.goToSleepNow() 157 self.dut.turn_location_off_and_scan_toggle_off() 158 self.dut.disconnect() 159 self.dut.reset_wifi() 160 self.access_point.stop_all_aps() 161 162 def on_fail(self, test_name, begin_time): 163 super().on_fail(test_name, begin_time) 164 self.access_point.stop_all_aps() 165 166 def setup_and_connect(self, ap_settings): 167 """Uses ap_settings to set up ap and then attempts to associate a DUT. 168 169 Args: 170 ap_settings: a dict containing test case settings, including 171 bandwidth, security, n_capabilities, and ac_capabilities 172 173 """ 174 security = ap_settings['security'] 175 chbw = ap_settings['chbw'] 176 password = None 177 if security: 178 password = security.password 179 n_capabilities = ap_settings['n_capabilities'] 180 ac_capabilities = ap_settings['ac_capabilities'] 181 182 validate_setup_ap_and_associate(access_point=self.access_point, 183 client=self.dut, 184 profile_name='whirlwind', 185 mode=hostapd_constants.MODE_11AC_MIXED, 186 channel=36, 187 n_capabilities=n_capabilities, 188 ac_capabilities=ac_capabilities, 189 force_wmm=True, 190 ssid=utils.rand_ascii_str(20), 191 security=security, 192 vht_bandwidth=chbw, 193 password=password) 194 195 # 864 test cases 196 def test_11ac_capabilities_20mhz_open(self): 197 test_list = [] 198 for combination in itertools.product(VHT_MAX_MPDU_LEN, RXLDPC, RX_STBC, 199 TX_STBC, MAX_A_MPDU, RX_ANTENNA, 200 TX_ANTENNA): 201 test_list.append({ 202 'chbw': 20, 203 'security': None, 204 'n_capabilities': N_CAPABS_20MHZ, 205 'ac_capabilities': combination 206 }) 207 self.run_generated_testcases(self.setup_and_connect, 208 settings=test_list, 209 name_func=generate_test_name) 210 211 # 864 test cases 212 def test_11ac_capabilities_40mhz_open(self): 213 test_list = [] 214 for combination in itertools.product(VHT_MAX_MPDU_LEN, RXLDPC, RX_STBC, 215 TX_STBC, MAX_A_MPDU, RX_ANTENNA, 216 TX_ANTENNA): 217 test_list.append({ 218 'chbw': 40, 219 'security': None, 220 'n_capabilities': N_CAPABS_40MHZ, 221 'ac_capabilities': combination 222 }) 223 self.run_generated_testcases(self.setup_and_connect, 224 settings=test_list, 225 name_func=generate_test_name) 226 227 # 1728 test cases 228 def test_11ac_capabilities_80mhz_open(self): 229 test_list = [] 230 for combination in itertools.product(VHT_MAX_MPDU_LEN, RXLDPC, 231 SHORT_GI_80, RX_STBC, TX_STBC, 232 MAX_A_MPDU, RX_ANTENNA, 233 TX_ANTENNA): 234 test_list.append({ 235 'chbw': 80, 236 'security': None, 237 'n_capabilities': N_CAPABS_40MHZ, 238 'ac_capabilities': combination 239 }) 240 self.run_generated_testcases(self.setup_and_connect, 241 settings=test_list, 242 name_func=generate_test_name) 243 244 # 864 test cases 245 def test_11ac_capabilities_20mhz_wpa2(self): 246 test_list = [] 247 for combination in itertools.product(VHT_MAX_MPDU_LEN, RXLDPC, RX_STBC, 248 TX_STBC, MAX_A_MPDU, RX_ANTENNA, 249 TX_ANTENNA): 250 test_list.append({ 251 'chbw': 20, 252 'security': WPA2_SECURITY, 253 'n_capabilities': N_CAPABS_20MHZ, 254 'ac_capabilities': combination 255 }) 256 self.run_generated_testcases(self.setup_and_connect, 257 settings=test_list, 258 name_func=generate_test_name) 259 260 # 864 test cases 261 def test_11ac_capabilities_40mhz_wpa2(self): 262 test_list = [] 263 for combination in itertools.product(VHT_MAX_MPDU_LEN, RXLDPC, RX_STBC, 264 TX_STBC, MAX_A_MPDU, RX_ANTENNA, 265 TX_ANTENNA): 266 test_list.append({ 267 'chbw': 40, 268 'security': WPA2_SECURITY, 269 'n_capabilities': N_CAPABS_40MHZ, 270 'ac_capabilities': combination 271 }) 272 self.run_generated_testcases(self.setup_and_connect, 273 settings=test_list, 274 name_func=generate_test_name) 275 276 # 1728 test cases 277 def test_11ac_capabilities_80mhz_wpa2(self): 278 test_list = [] 279 for combination in itertools.product(VHT_MAX_MPDU_LEN, RXLDPC, 280 SHORT_GI_80, RX_STBC, TX_STBC, 281 MAX_A_MPDU, RX_ANTENNA, 282 TX_ANTENNA): 283 test_list.append({ 284 'chbw': 80, 285 'security': WPA2_SECURITY, 286 'n_capabilities': N_CAPABS_40MHZ, 287 'ac_capabilities': combination 288 }) 289 self.run_generated_testcases(self.setup_and_connect, 290 settings=test_list, 291 name_func=generate_test_name) 292 293 def test_11ac_capabilities_debug(self): 294 chbw_sec_capabs = re.compile( 295 r'.*?([0-9]*)mhz.*?(open|wpa2).*?(\[.*\])', re.IGNORECASE) 296 test_list = [] 297 for test_name in self.user_params['debug_11ac_tests']: 298 test_to_run = re.match(chbw_sec_capabs, test_name) 299 chbw = int(test_to_run.group(1)) 300 security = test_to_run.group(2) 301 capabs = test_to_run.group(3) 302 if chbw >= 40: 303 n_capabs = N_CAPABS_40MHZ 304 else: 305 n_capabs = N_CAPABS_20MHZ 306 if security.lower() == 'open': 307 security = None 308 elif security.lower() == 'wpa2': 309 security = WPA2_SECURITY 310 if capabs: 311 ac_capabs_strings = re.findall(r'\[.*?\]', capabs) 312 ac_capabs = [ 313 hostapd_constants.AC_CAPABILITIES_MAPPING_INVERSE[k] 314 for k in ac_capabs_strings 315 ] 316 test_list.append({ 317 'chbw': chbw, 318 'security': security, 319 'n_capabilities': n_capabs, 320 'ac_capabilities': ac_capabs 321 }) 322 self.run_generated_testcases(self.setup_and_connect, 323 settings=test_list, 324 name_func=generate_test_name) 325