#!/usr/bin/env python3 # # Copyright 2019 - The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import itertools import re from acts import asserts from acts import utils from acts.controllers.access_point import setup_ap from acts.controllers.ap_lib import hostapd_constants from acts.controllers.ap_lib import hostapd_config from acts.controllers.ap_lib.hostapd_security import Security from acts.controllers.ap_lib.hostapd_utils import generate_random_password from acts_contrib.test_utils.abstract_devices.wlan_device import create_wlan_device from acts_contrib.test_utils.abstract_devices.wlan_device_lib.AbstractDeviceWlanDeviceBaseTest import AbstractDeviceWlanDeviceBaseTest from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest FREQUENCY_24 = ['2.4GHz'] FREQUENCY_5 = ['5GHz'] CHANNEL_BANDWIDTH_20 = ['HT20'] CHANNEL_BANDWIDTH_40_LOWER = ['HT40-'] CHANNEL_BANDWIDTH_40_UPPER = ['HT40+'] SECURITY_OPEN = 'open' SECURITY_WPA2 = 'wpa2' LDPC = [hostapd_constants.N_CAPABILITY_LDPC, ''] TX_STBC = [hostapd_constants.N_CAPABILITY_TX_STBC, ''] RX_STBC = [hostapd_constants.N_CAPABILITY_RX_STBC1, ''] SGI_20 = [hostapd_constants.N_CAPABILITY_SGI20, ''] SGI_40 = [hostapd_constants.N_CAPABILITY_SGI40, ''] DSSS_CCK = [hostapd_constants.N_CAPABILITY_DSSS_CCK_40, ''] INTOLERANT_40 = [hostapd_constants.N_CAPABILITY_40_INTOLERANT, ''] MAX_AMPDU_7935 = [hostapd_constants.N_CAPABILITY_MAX_AMSDU_7935, ''] SMPS = [hostapd_constants.N_CAPABILITY_SMPS_STATIC, ''] def generate_test_name(settings): """Generates a string based on the n_capabilities for a test case Args: settings: A dictionary of hostapd constant n_capabilities. Returns: A string that represents a test case name. """ ret = [] for cap in hostapd_constants.N_CAPABILITIES_MAPPING.keys(): if cap in settings['n_capabilities']: ret.append(hostapd_constants.N_CAPABILITIES_MAPPING[cap]) return '%s_%s_%s_%s' % (settings['frequency'], settings['chbw'], settings['security'], ''.join(ret)) class WlanPhyCompliance11NTest(AbstractDeviceWlanDeviceBaseTest): """Tests for validating 11n PHYS. Test Bed Requirement: * One Android device or Fuchsia device * One Access Point """ def __init__(self, controllers): WifiBaseTest.__init__(self, controllers) self.tests = [ 'test_11n_capabilities_24_HT20', 'test_11n_capabilities_24_HT40_lower', 'test_11n_capabilities_24_HT40_upper', 'test_11n_capabilities_5_HT20', 'test_11n_capabilities_5_HT40_lower', 'test_11n_capabilities_5_HT40_upper', 'test_11n_capabilities_24_HT20_wpa2', 'test_11n_capabilities_24_HT40_lower_wpa2', 'test_11n_capabilities_24_HT40_upper_wpa2', 'test_11n_capabilities_5_HT20_wpa2', 'test_11n_capabilities_5_HT40_lower_wpa2', 'test_11n_capabilities_5_HT40_upper_wpa2' ] if 'debug_11n_tests' in self.user_params: self.tests.append('test_11n_capabilities_debug') def setup_class(self): super().setup_class() if 'dut' in self.user_params: if self.user_params['dut'] == 'fuchsia_devices': self.dut = create_wlan_device(self.fuchsia_devices[0]) elif self.user_params['dut'] == 'android_devices': self.dut = create_wlan_device(self.android_devices[0]) else: raise ValueError('Invalid DUT specified in config. (%s)' % self.user_params['dut']) else: # Default is an android device, just like the other tests self.dut = create_wlan_device(self.android_devices[0]) self.access_point = self.access_points[0] self.access_point.stop_all_aps() def setup_test(self): if hasattr(self, "android_devices"): for ad in self.android_devices: ad.droid.wakeLockAcquireBright() ad.droid.wakeUpNow() self.dut.wifi_toggle_state(True) def teardown_test(self): if hasattr(self, "android_devices"): for ad in self.android_devices: ad.droid.wakeLockRelease() ad.droid.goToSleepNow() self.dut.turn_location_off_and_scan_toggle_off() self.dut.disconnect() self.dut.reset_wifi() self.download_ap_logs() self.access_point.stop_all_aps() def on_fail(self, test_name, begin_time): super().on_fail(test_name, begin_time) self.access_point.stop_all_aps() def setup_and_connect(self, ap_settings): """Generates a hostapd config, setups up the AP with that config, then attempts to associate a DUT Args: ap_settings: A dictionary of hostapd constant n_capabilities. """ ssid = utils.rand_ascii_str(20) security_profile = None password = None temp_n_capabilities = list(ap_settings['n_capabilities']) n_capabilities = [] for n_capability in temp_n_capabilities: if n_capability in hostapd_constants.N_CAPABILITIES_MAPPING.keys(): n_capabilities.append(n_capability) if ap_settings['chbw'] == 'HT20' or ap_settings['chbw'] == 'HT40+': if ap_settings['frequency'] == '2.4GHz': channel = 1 elif ap_settings['frequency'] == '5GHz': channel = 36 else: raise ValueError('Invalid frequence: %s' % ap_settings['frequency']) elif ap_settings['chbw'] == 'HT40-': if ap_settings['frequency'] == '2.4GHz': channel = 11 elif ap_settings['frequency'] == '5GHz': channel = 60 else: raise ValueError('Invalid frequency: %s' % ap_settings['frequency']) else: raise ValueError('Invalid channel bandwidth: %s' % ap_settings['chbw']) if ap_settings['chbw'] == 'HT40-' or ap_settings['chbw'] == 'HT40+': if hostapd_config.ht40_plus_allowed(channel): extended_channel = hostapd_constants.N_CAPABILITY_HT40_PLUS elif hostapd_config.ht40_minus_allowed(channel): extended_channel = hostapd_constants.N_CAPABILITY_HT40_MINUS else: raise ValueError('Invalid channel: %s' % channel) n_capabilities.append(extended_channel) if ap_settings['security'] == 'wpa2': security_profile = Security( security_mode=SECURITY_WPA2, password=generate_random_password(length=20), wpa_cipher='CCMP', wpa2_cipher='CCMP') password = security_profile.password target_security = hostapd_constants.SECURITY_STRING_TO_DEFAULT_TARGET_SECURITY.get( ap_settings['security'], None) setup_ap(access_point=self.access_point, profile_name='whirlwind', mode=hostapd_constants.MODE_11N_MIXED, channel=channel, n_capabilities=n_capabilities, ac_capabilities=[], force_wmm=True, ssid=ssid, security=security_profile, password=password) asserts.assert_true( self.dut.associate(ssid, target_pwd=password, target_security=target_security), 'Failed to connect.') def test_11n_capabilities_24_HT20(self): test_list = [] for combination in itertools.product(FREQUENCY_24, CHANNEL_BANDWIDTH_20, LDPC, TX_STBC, RX_STBC, SGI_20, INTOLERANT_40, MAX_AMPDU_7935, SMPS): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_OPEN, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_24_HT40_lower(self): test_list = [] for combination in itertools.product(FREQUENCY_24, CHANNEL_BANDWIDTH_40_LOWER, LDPC, TX_STBC, RX_STBC, SGI_20, SGI_40, MAX_AMPDU_7935, SMPS, DSSS_CCK): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_OPEN, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_24_HT40_upper(self): test_list = [] for combination in itertools.product(FREQUENCY_24, CHANNEL_BANDWIDTH_40_UPPER, LDPC, TX_STBC, RX_STBC, SGI_20, SGI_40, MAX_AMPDU_7935, SMPS, DSSS_CCK): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_OPEN, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_5_HT20(self): test_list = [] for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_20, LDPC, TX_STBC, RX_STBC, SGI_20, INTOLERANT_40, MAX_AMPDU_7935, SMPS): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_OPEN, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_5_HT40_lower(self): test_list = [] for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_40_LOWER, LDPC, TX_STBC, RX_STBC, SGI_20, SGI_40, MAX_AMPDU_7935, SMPS, DSSS_CCK): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_OPEN, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_5_HT40_upper(self): test_list = [] for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_40_UPPER, LDPC, TX_STBC, RX_STBC, SGI_20, SGI_40, MAX_AMPDU_7935, SMPS, DSSS_CCK): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_OPEN, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_24_HT20_wpa2(self): test_list = [] for combination in itertools.product(FREQUENCY_24, CHANNEL_BANDWIDTH_20, LDPC, TX_STBC, RX_STBC, SGI_20, INTOLERANT_40, MAX_AMPDU_7935, SMPS): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_WPA2, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_24_HT40_lower_wpa2(self): test_list = [] for combination in itertools.product(FREQUENCY_24, CHANNEL_BANDWIDTH_40_LOWER, LDPC, TX_STBC, RX_STBC, SGI_20, SGI_40, MAX_AMPDU_7935, SMPS, DSSS_CCK): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_WPA2, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_24_HT40_upper_wpa2(self): test_list = [] for combination in itertools.product(FREQUENCY_24, CHANNEL_BANDWIDTH_40_UPPER, LDPC, TX_STBC, RX_STBC, SGI_20, SGI_40, MAX_AMPDU_7935, SMPS, DSSS_CCK): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_WPA2, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_5_HT20_wpa2(self): test_list = [] for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_20, LDPC, TX_STBC, RX_STBC, SGI_20, INTOLERANT_40, MAX_AMPDU_7935, SMPS): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_WPA2, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_5_HT40_lower_wpa2(self): test_list = [] for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_40_LOWER, LDPC, TX_STBC, RX_STBC, SGI_20, SGI_40, MAX_AMPDU_7935, SMPS, DSSS_CCK): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_WPA2, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_5_HT40_upper_wpa2(self): test_list = [] for combination in itertools.product(FREQUENCY_5, CHANNEL_BANDWIDTH_40_UPPER, LDPC, TX_STBC, RX_STBC, SGI_20, SGI_40, MAX_AMPDU_7935, SMPS, DSSS_CCK): test_frequency = combination[0] test_chbw = combination[1] n_capabilities = combination[2:] test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': SECURITY_WPA2, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) def test_11n_capabilities_debug(self): allowed_frequencies = FREQUENCY_5 + FREQUENCY_24 allowed_chbw = (CHANNEL_BANDWIDTH_20 + CHANNEL_BANDWIDTH_40_LOWER + CHANNEL_BANDWIDTH_40_UPPER) allowed_security = [SECURITY_WPA2, SECURITY_OPEN] freq_chbw_sec = re.compile(r'(.*)_(.*)_(.*)_(\[.*\])?$') for test_title in self.user_params['debug_11n_tests']: test_list = [] test_to_run = re.match(freq_chbw_sec, test_title) if test_to_run: test_frequency = test_to_run.group(1) test_chbw = test_to_run.group(2) security = test_to_run.group(3) if (test_frequency in allowed_frequencies and test_chbw in allowed_chbw and security in allowed_security): if test_to_run.group(4): n_capabilities_str = test_to_run.group(4) else: n_capabilities_str = '' n_capabilities_list = [] if '[LDPC]' in n_capabilities_str: n_capabilities_list.append( hostapd_constants.N_CAPABILITY_LDPC) if '[TX-STBC]' in n_capabilities_str: n_capabilities_list.append( hostapd_constants.N_CAPABILITY_TX_STBC) if '[RX-STBC1]' in n_capabilities_str: n_capabilities_list.append( hostapd_constants.N_CAPABILITY_RX_STBC1) if '[SHORT-GI-20]' in n_capabilities_str: n_capabilities_list.append( hostapd_constants.N_CAPABILITY_SGI20) if '[SHORT-GI-40]' in n_capabilities_str: n_capabilities_list.append( hostapd_constants.N_CAPABILITY_SGI40) if '[DSSS_CCK-40]' in n_capabilities_str: n_capabilities_list.append( hostapd_constants.N_CAPABILITY_DSSS_CCK_40) if '[40-INTOLERANT]' in n_capabilities_str: n_capabilities_list.append( hostapd_constants.N_CAPABILITY_40_INTOLERANT) if '[MAX-AMSDU-7935]' in n_capabilities_str: n_capabilities_list.append( hostapd_constants.N_CAPABILITY_MAX_AMSDU_7935) if '[SMPS-STATIC]' in n_capabilities_str: n_capabilities_list.append( hostapd_constants.N_CAPABILITY_SMPS_STATIC) n_capabilities = tuple(n_capabilities_list) test_list.append({ 'frequency': test_frequency, 'chbw': test_chbw, 'security': security, 'n_capabilities': n_capabilities }) self.run_generated_testcases(self.setup_and_connect, settings=test_list, name_func=generate_test_name) else: self.log.error('Invalid test (%s). Trying the next one.' % test_title) else: self.log.error('Invalid test (%s). Trying the next one.' % test_title)