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