1#!/usr/bin/env python3 2# 3# Copyright 2019 - 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 30FREQUENCY_24 = ['2.4GHz'] 31FREQUENCY_5 = ['5GHz'] 32CHANNEL_BANDWIDTH_20 = ['HT20'] 33CHANNEL_BANDWIDTH_40_LOWER = ['HT40-'] 34CHANNEL_BANDWIDTH_40_UPPER = ['HT40+'] 35SECURITY_OPEN = 'open' 36SECURITY_WPA2 = 'wpa2' 37LDPC = [hostapd_constants.N_CAPABILITY_LDPC, ''] 38TX_STBC = [hostapd_constants.N_CAPABILITY_TX_STBC, ''] 39RX_STBC = [hostapd_constants.N_CAPABILITY_RX_STBC1, ''] 40SGI_20 = [hostapd_constants.N_CAPABILITY_SGI20, ''] 41SGI_40 = [hostapd_constants.N_CAPABILITY_SGI40, ''] 42DSSS_CCK = [hostapd_constants.N_CAPABILITY_DSSS_CCK_40, ''] 43INTOLERANT_40 = [hostapd_constants.N_CAPABILITY_40_INTOLERANT, ''] 44MAX_AMPDU_7935 = [hostapd_constants.N_CAPABILITY_MAX_AMSDU_7935, ''] 45SMPS = [hostapd_constants.N_CAPABILITY_SMPS_STATIC, ''] 46 47 48def generate_test_name(settings): 49 """Generates a string based on the n_capabilities for a test case 50 51 Args: 52 settings: A dictionary of hostapd constant n_capabilities. 53 54 Returns: 55 A string that represents a test case name. 56 """ 57 ret = [] 58 for cap in hostapd_constants.N_CAPABILITIES_MAPPING.keys(): 59 if cap in settings['n_capabilities']: 60 ret.append(hostapd_constants.N_CAPABILITIES_MAPPING[cap]) 61 return '%s_%s_%s_%s' % (settings['frequency'], settings['chbw'], 62 settings['security'], ''.join(ret)) 63 64 65class WlanPhyCompliance11NTest(AbstractDeviceWlanDeviceBaseTest): 66 """Tests for validating 11n PHYS. 67 68 Test Bed Requirement: 69 * One Android device or Fuchsia device 70 * One Access Point 71 """ 72 def __init__(self, controllers): 73 WifiBaseTest.__init__(self, controllers) 74 self.tests = [ 75 'test_11n_capabilities_24_HT20', 76 'test_11n_capabilities_24_HT40_lower', 77 'test_11n_capabilities_24_HT40_upper', 78 'test_11n_capabilities_5_HT20', 79 'test_11n_capabilities_5_HT40_lower', 80 'test_11n_capabilities_5_HT40_upper', 81 'test_11n_capabilities_24_HT20_wpa2', 82 'test_11n_capabilities_24_HT40_lower_wpa2', 83 'test_11n_capabilities_24_HT40_upper_wpa2', 84 'test_11n_capabilities_5_HT20_wpa2', 85 'test_11n_capabilities_5_HT40_lower_wpa2', 86 'test_11n_capabilities_5_HT40_upper_wpa2' 87 ] 88 if 'debug_11n_tests' in self.user_params: 89 self.tests.append('test_11n_capabilities_debug') 90 91 def setup_class(self): 92 super().setup_class() 93 if 'dut' in self.user_params: 94 if self.user_params['dut'] == 'fuchsia_devices': 95 self.dut = create_wlan_device(self.fuchsia_devices[0]) 96 elif self.user_params['dut'] == 'android_devices': 97 self.dut = create_wlan_device(self.android_devices[0]) 98 else: 99 raise ValueError('Invalid DUT specified in config. (%s)' % 100 self.user_params['dut']) 101 else: 102 # Default is an android device, just like the other tests 103 self.dut = create_wlan_device(self.android_devices[0]) 104 105 self.access_point = self.access_points[0] 106 self.access_point.stop_all_aps() 107 108 def setup_test(self): 109 if hasattr(self, "android_devices"): 110 for ad in self.android_devices: 111 ad.droid.wakeLockAcquireBright() 112 ad.droid.wakeUpNow() 113 self.dut.wifi_toggle_state(True) 114 115 def teardown_test(self): 116 if hasattr(self, "android_devices"): 117 for ad in self.android_devices: 118 ad.droid.wakeLockRelease() 119 ad.droid.goToSleepNow() 120 self.dut.turn_location_off_and_scan_toggle_off() 121 self.dut.disconnect() 122 self.dut.reset_wifi() 123 self.access_point.stop_all_aps() 124 125 def on_fail(self, test_name, begin_time): 126 super().on_fail(test_name, begin_time) 127 self.access_point.stop_all_aps() 128 129 def setup_and_connect(self, ap_settings): 130 """Generates a hostapd config, setups up the AP with that config, then 131 attempts to associate a DUT 132 133 Args: 134 ap_settings: A dictionary of hostapd constant n_capabilities. 135 """ 136 security_profile = None 137 password = None 138 temp_n_capabilities = list(ap_settings['n_capabilities']) 139 n_capabilities = [] 140 for n_capability in temp_n_capabilities: 141 if n_capability in hostapd_constants.N_CAPABILITIES_MAPPING.keys(): 142 n_capabilities.append(n_capability) 143 144 if ap_settings['chbw'] == 'HT20' or ap_settings['chbw'] == 'HT40+': 145 if ap_settings['frequency'] == '2.4GHz': 146 channel = 1 147 elif ap_settings['frequency'] == '5GHz': 148 channel = 36 149 else: 150 raise ValueError('Invalid frequence: %s' % 151 ap_settings['frequency']) 152 153 if ap_settings['chbw'] == 'HT40-': 154 if ap_settings['frequency'] == '2.4GHz': 155 channel = 11 156 elif ap_settings['frequency'] == '5GHz': 157 channel = 60 158 else: 159 raise ValueError('Invalid frequency: %s' % 160 ap_settings['frequency']) 161 162 if ap_settings['chbw'] == 'HT40-' or ap_settings['chbw'] == 'HT40+': 163 if hostapd_config.ht40_plus_allowed(channel): 164 extended_channel = hostapd_constants.N_CAPABILITY_HT40_PLUS 165 elif hostapd_config.ht40_minus_allowed(channel): 166 extended_channel = hostapd_constants.N_CAPABILITY_HT40_MINUS 167 else: 168 raise ValueError('Invalid channel: %s' % channel) 169 n_capabilities.append(extended_channel) 170 171 if ap_settings['security'] == 'wpa2': 172 security_profile = Security(security_mode=SECURITY_WPA2, 173 password=rand_ascii_str(20), 174 wpa_cipher='CCMP', 175 wpa2_cipher='CCMP') 176 password = security_profile.password 177 178 validate_setup_ap_and_associate(access_point=self.access_point, 179 client=self.dut, 180 profile_name='whirlwind', 181 mode=hostapd_constants.MODE_11N_MIXED, 182 channel=channel, 183 n_capabilities=n_capabilities, 184 ac_capabilities=[], 185 force_wmm=True, 186 ssid=utils.rand_ascii_str(20), 187 security=security_profile, 188 password=password) 189 190 def test_11n_capabilities_24_HT20(self): 191 test_list = [] 192 for combination in itertools.product(FREQUENCY_24, 193 CHANNEL_BANDWIDTH_20, LDPC, 194 TX_STBC, RX_STBC, SGI_20, 195 INTOLERANT_40, MAX_AMPDU_7935, 196 SMPS): 197 test_frequency = combination[0] 198 test_chbw = combination[1] 199 n_capabilities = combination[2:] 200 test_list.append({ 201 'frequency': test_frequency, 202 'chbw': test_chbw, 203 'security': SECURITY_OPEN, 204 'n_capabilities': n_capabilities 205 }) 206 self.run_generated_testcases(self.setup_and_connect, 207 settings=test_list, 208 name_func=generate_test_name) 209 210 def test_11n_capabilities_24_HT40_lower(self): 211 test_list = [] 212 for combination in itertools.product(FREQUENCY_24, 213 CHANNEL_BANDWIDTH_40_LOWER, LDPC, 214 TX_STBC, RX_STBC, SGI_20, SGI_40, 215 MAX_AMPDU_7935, SMPS, DSSS_CCK): 216 test_frequency = combination[0] 217 test_chbw = combination[1] 218 n_capabilities = combination[2:] 219 test_list.append({ 220 'frequency': test_frequency, 221 'chbw': test_chbw, 222 'security': SECURITY_OPEN, 223 'n_capabilities': n_capabilities 224 }) 225 self.run_generated_testcases(self.setup_and_connect, 226 settings=test_list, 227 name_func=generate_test_name) 228 229 def test_11n_capabilities_24_HT40_upper(self): 230 test_list = [] 231 for combination in itertools.product(FREQUENCY_24, 232 CHANNEL_BANDWIDTH_40_UPPER, LDPC, 233 TX_STBC, RX_STBC, SGI_20, SGI_40, 234 MAX_AMPDU_7935, SMPS, DSSS_CCK): 235 test_frequency = combination[0] 236 test_chbw = combination[1] 237 n_capabilities = combination[2:] 238 test_list.append({ 239 'frequency': test_frequency, 240 'chbw': test_chbw, 241 'security': SECURITY_OPEN, 242 'n_capabilities': n_capabilities 243 }) 244 self.run_generated_testcases(self.setup_and_connect, 245 settings=test_list, 246 name_func=generate_test_name) 247 248 def test_11n_capabilities_5_HT20(self): 249 test_list = [] 250 for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_20, 251 LDPC, TX_STBC, RX_STBC, SGI_20, 252 INTOLERANT_40, MAX_AMPDU_7935, 253 SMPS): 254 test_frequency = combination[0] 255 test_chbw = combination[1] 256 n_capabilities = combination[2:] 257 test_list.append({ 258 'frequency': test_frequency, 259 'chbw': test_chbw, 260 'security': SECURITY_OPEN, 261 'n_capabilities': n_capabilities 262 }) 263 self.run_generated_testcases(self.setup_and_connect, 264 settings=test_list, 265 name_func=generate_test_name) 266 267 def test_11n_capabilities_5_HT40_lower(self): 268 test_list = [] 269 for combination in itertools.product(FREQUENCY_5, 270 CHANNEL_BANDWIDTH_40_LOWER, LDPC, 271 TX_STBC, RX_STBC, SGI_20, SGI_40, 272 MAX_AMPDU_7935, SMPS, DSSS_CCK): 273 test_frequency = combination[0] 274 test_chbw = combination[1] 275 n_capabilities = combination[2:] 276 test_list.append({ 277 'frequency': test_frequency, 278 'chbw': test_chbw, 279 'security': SECURITY_OPEN, 280 'n_capabilities': n_capabilities 281 }) 282 self.run_generated_testcases(self.setup_and_connect, 283 settings=test_list, 284 name_func=generate_test_name) 285 286 def test_11n_capabilities_5_HT40_upper(self): 287 test_list = [] 288 for combination in itertools.product(FREQUENCY_5, 289 CHANNEL_BANDWIDTH_40_UPPER, LDPC, 290 TX_STBC, RX_STBC, SGI_20, SGI_40, 291 MAX_AMPDU_7935, SMPS, DSSS_CCK): 292 test_frequency = combination[0] 293 test_chbw = combination[1] 294 n_capabilities = combination[2:] 295 test_list.append({ 296 'frequency': test_frequency, 297 'chbw': test_chbw, 298 'security': SECURITY_OPEN, 299 'n_capabilities': n_capabilities 300 }) 301 self.run_generated_testcases(self.setup_and_connect, 302 settings=test_list, 303 name_func=generate_test_name) 304 305 def test_11n_capabilities_24_HT20_wpa2(self): 306 test_list = [] 307 for combination in itertools.product(FREQUENCY_24, 308 CHANNEL_BANDWIDTH_20, LDPC, 309 TX_STBC, RX_STBC, SGI_20, 310 INTOLERANT_40, MAX_AMPDU_7935, 311 SMPS): 312 test_frequency = combination[0] 313 test_chbw = combination[1] 314 n_capabilities = combination[2:] 315 test_list.append({ 316 'frequency': test_frequency, 317 'chbw': test_chbw, 318 'security': SECURITY_WPA2, 319 'n_capabilities': n_capabilities 320 }) 321 self.run_generated_testcases(self.setup_and_connect, 322 settings=test_list, 323 name_func=generate_test_name) 324 325 def test_11n_capabilities_24_HT40_lower_wpa2(self): 326 test_list = [] 327 for combination in itertools.product(FREQUENCY_24, 328 CHANNEL_BANDWIDTH_40_LOWER, LDPC, 329 TX_STBC, RX_STBC, SGI_20, SGI_40, 330 MAX_AMPDU_7935, SMPS, DSSS_CCK): 331 test_frequency = combination[0] 332 test_chbw = combination[1] 333 n_capabilities = combination[2:] 334 test_list.append({ 335 'frequency': test_frequency, 336 'chbw': test_chbw, 337 'security': SECURITY_WPA2, 338 'n_capabilities': n_capabilities 339 }) 340 self.run_generated_testcases(self.setup_and_connect, 341 settings=test_list, 342 name_func=generate_test_name) 343 344 def test_11n_capabilities_24_HT40_upper_wpa2(self): 345 test_list = [] 346 for combination in itertools.product(FREQUENCY_24, 347 CHANNEL_BANDWIDTH_40_UPPER, LDPC, 348 TX_STBC, RX_STBC, SGI_20, SGI_40, 349 MAX_AMPDU_7935, SMPS, DSSS_CCK): 350 test_frequency = combination[0] 351 test_chbw = combination[1] 352 n_capabilities = combination[2:] 353 test_list.append({ 354 'frequency': test_frequency, 355 'chbw': test_chbw, 356 'security': SECURITY_WPA2, 357 'n_capabilities': n_capabilities 358 }) 359 self.run_generated_testcases(self.setup_and_connect, 360 settings=test_list, 361 name_func=generate_test_name) 362 363 def test_11n_capabilities_5_HT20_wpa2(self): 364 test_list = [] 365 for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_20, 366 LDPC, TX_STBC, RX_STBC, SGI_20, 367 INTOLERANT_40, MAX_AMPDU_7935, 368 SMPS): 369 test_frequency = combination[0] 370 test_chbw = combination[1] 371 n_capabilities = combination[2:] 372 test_list.append({ 373 'frequency': test_frequency, 374 'chbw': test_chbw, 375 'security': SECURITY_WPA2, 376 'n_capabilities': n_capabilities 377 }) 378 self.run_generated_testcases(self.setup_and_connect, 379 settings=test_list, 380 name_func=generate_test_name) 381 382 def test_11n_capabilities_5_HT40_lower_wpa2(self): 383 test_list = [] 384 for combination in itertools.product(FREQUENCY_5, 385 CHANNEL_BANDWIDTH_40_LOWER, LDPC, 386 TX_STBC, RX_STBC, SGI_20, SGI_40, 387 MAX_AMPDU_7935, SMPS, DSSS_CCK): 388 test_frequency = combination[0] 389 test_chbw = combination[1] 390 n_capabilities = combination[2:] 391 test_list.append({ 392 'frequency': test_frequency, 393 'chbw': test_chbw, 394 'security': SECURITY_WPA2, 395 'n_capabilities': n_capabilities 396 }) 397 self.run_generated_testcases(self.setup_and_connect, 398 settings=test_list, 399 name_func=generate_test_name) 400 401 def test_11n_capabilities_5_HT40_upper_wpa2(self): 402 test_list = [] 403 for combination in itertools.product(FREQUENCY_5, 404 CHANNEL_BANDWIDTH_40_UPPER, LDPC, 405 TX_STBC, RX_STBC, SGI_20, SGI_40, 406 MAX_AMPDU_7935, SMPS, DSSS_CCK): 407 test_frequency = combination[0] 408 test_chbw = combination[1] 409 n_capabilities = combination[2:] 410 test_list.append({ 411 'frequency': test_frequency, 412 'chbw': test_chbw, 413 'security': SECURITY_WPA2, 414 'n_capabilities': n_capabilities 415 }) 416 self.run_generated_testcases(self.setup_and_connect, 417 settings=test_list, 418 name_func=generate_test_name) 419 420 def test_11n_capabilities_debug(self): 421 allowed_frequencies = FREQUENCY_5 + FREQUENCY_24 422 allowed_chbw = (CHANNEL_BANDWIDTH_20 + CHANNEL_BANDWIDTH_40_LOWER + 423 CHANNEL_BANDWIDTH_40_UPPER) 424 allowed_security = [SECURITY_WPA2, SECURITY_OPEN] 425 freq_chbw_sec = re.compile(r'(.*)_(.*)_(.*)_(\[.*\])?$') 426 for test_title in self.user_params['debug_11n_tests']: 427 test_list = [] 428 test_to_run = re.match(freq_chbw_sec, test_title) 429 if test_to_run: 430 test_frequency = test_to_run.group(1) 431 test_chbw = test_to_run.group(2) 432 security = test_to_run.group(3) 433 if (test_frequency in allowed_frequencies 434 and test_chbw in allowed_chbw 435 and security in allowed_security): 436 if test_to_run.group(4): 437 n_capabilities_str = test_to_run.group(4) 438 else: 439 n_capabilities_str = '' 440 n_capabilities_list = [] 441 if '[LDPC]' in n_capabilities_str: 442 n_capabilities_list.append( 443 hostapd_constants.N_CAPABILITY_LDPC) 444 if '[TX-STBC]' in n_capabilities_str: 445 n_capabilities_list.append( 446 hostapd_constants.N_CAPABILITY_TX_STBC) 447 if '[RX-STBC1]' in n_capabilities_str: 448 n_capabilities_list.append( 449 hostapd_constants.N_CAPABILITY_RX_STBC1) 450 if '[SHORT-GI-20]' in n_capabilities_str: 451 n_capabilities_list.append( 452 hostapd_constants.N_CAPABILITY_SGI20) 453 if '[SHORT-GI-40]' in n_capabilities_str: 454 n_capabilities_list.append( 455 hostapd_constants.N_CAPABILITY_SGI40) 456 if '[DSSS_CCK-40]' in n_capabilities_str: 457 n_capabilities_list.append( 458 hostapd_constants.N_CAPABILITY_DSSS_CCK_40) 459 if '[40-INTOLERANT]' in n_capabilities_str: 460 n_capabilities_list.append( 461 hostapd_constants.N_CAPABILITY_40_INTOLERANT) 462 if '[MAX-AMSDU-7935]' in n_capabilities_str: 463 n_capabilities_list.append( 464 hostapd_constants.N_CAPABILITY_MAX_AMSDU_7935) 465 if '[SMPS-STATIC]' in n_capabilities_str: 466 n_capabilities_list.append( 467 hostapd_constants.N_CAPABILITY_SMPS_STATIC) 468 n_capabilities = tuple(n_capabilities_list) 469 test_list.append({ 470 'frequency': test_frequency, 471 'chbw': test_chbw, 472 'security': security, 473 'n_capabilities': n_capabilities 474 }) 475 self.run_generated_testcases(self.setup_and_connect, 476 settings=test_list, 477 name_func=generate_test_name) 478 else: 479 self.log.error('Invalid test (%s). Trying the next one.' % 480 test_title) 481 else: 482 self.log.error('Invalid test (%s). Trying the next one.' % 483 test_title) 484