Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python3.4 |
| 2 | # |
| 3 | # Copyright 2018 - The Android Open Source Project |
| 4 | # |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 5 | # Licensed under the Apache License, Version 2.0 (the 'License'); |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 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 |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 12 | # distributed under the License is distributed on an 'AS IS' BASIS, |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 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 | |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 17 | import collections |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 18 | import itertools |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 19 | import json |
| 20 | import logging |
| 21 | import math |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 22 | import numpy |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 23 | import os |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 24 | import statistics |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 25 | from acts import asserts |
| 26 | from acts import base_test |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 27 | from acts import context |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 28 | from acts import utils |
Omar El Ayach | 2819be6 | 2019-04-11 12:00:00 -0700 | [diff] [blame] | 29 | from acts.controllers.utils_lib import ssh |
Omar El Ayach | 14416ac | 2019-01-30 14:58:19 -0800 | [diff] [blame] | 30 | from acts.controllers import iperf_server as ipf |
Xianyuan Jia | 976d404 | 2019-09-30 17:19:47 -0700 | [diff] [blame] | 31 | from acts.metrics.loggers.blackbox import BlackboxMappedMetricLogger |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 32 | from acts.test_utils.wifi import ota_chamber |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 33 | from acts.test_utils.wifi import wifi_performance_test_utils as wputils |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 34 | from acts.test_utils.wifi import wifi_retail_ap as retail_ap |
| 35 | from acts.test_utils.wifi import wifi_test_utils as wutils |
Omar El Ayach | 14416ac | 2019-01-30 14:58:19 -0800 | [diff] [blame] | 36 | from concurrent.futures import ThreadPoolExecutor |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 37 | from functools import partial |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 38 | |
| 39 | SHORT_SLEEP = 1 |
| 40 | MED_SLEEP = 6 |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 41 | CONST_3dB = 3.01029995664 |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 42 | RSSI_ERROR_VAL = float('nan') |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 43 | |
| 44 | |
| 45 | class WifiRssiTest(base_test.BaseTestClass): |
Omar El Ayach | bb82898 | 2018-08-27 15:47:41 -0700 | [diff] [blame] | 46 | """Class to test WiFi RSSI reporting. |
| 47 | |
| 48 | This class tests RSSI reporting on android devices. The class tests RSSI |
| 49 | accuracy by checking RSSI over a large attenuation range, checks for RSSI |
| 50 | stability over time when attenuation is fixed, and checks that RSSI quickly |
| 51 | and reacts to changes attenuation by checking RSSI trajectories over |
| 52 | configurable attenuation waveforms.For an example config file to run this |
| 53 | test class see example_connectivity_performance_ap_sta.json. |
| 54 | """ |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 55 | def __init__(self, controllers): |
| 56 | base_test.BaseTestClass.__init__(self, controllers) |
Omar El Ayach | a7c3afe | 2019-09-16 15:58:29 -0700 | [diff] [blame] | 57 | self.testcase_metric_logger = ( |
Xianyuan Jia | 976d404 | 2019-09-30 17:19:47 -0700 | [diff] [blame] | 58 | BlackboxMappedMetricLogger.for_test_case()) |
Omar El Ayach | a7c3afe | 2019-09-16 15:58:29 -0700 | [diff] [blame] | 59 | self.testclass_metric_logger = ( |
Xianyuan Jia | 976d404 | 2019-09-30 17:19:47 -0700 | [diff] [blame] | 60 | BlackboxMappedMetricLogger.for_test_class()) |
Omar El Ayach | 02a1cce | 2019-09-19 17:51:39 -0700 | [diff] [blame] | 61 | self.publish_test_metrics = True |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 62 | |
| 63 | def setup_class(self): |
| 64 | self.dut = self.android_devices[0] |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 65 | req_params = [ |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 66 | 'RemoteServer', 'RetailAccessPoints', 'rssi_test_params', |
| 67 | 'main_network', 'testbed_params' |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 68 | ] |
| 69 | self.unpack_userparams(req_params) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 70 | self.testclass_params = self.rssi_test_params |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 71 | self.num_atten = self.attenuators[0].instrument.num_atten |
| 72 | self.iperf_server = self.iperf_servers[0] |
Omar El Ayach | 14416ac | 2019-01-30 14:58:19 -0800 | [diff] [blame] | 73 | self.iperf_client = self.iperf_clients[0] |
Omar El Ayach | 2819be6 | 2019-04-11 12:00:00 -0700 | [diff] [blame] | 74 | self.remote_server = ssh.connection.SshConnection( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 75 | ssh.settings.from_config(self.RemoteServer[0]['ssh_config'])) |
Omar El Ayach | 14416ac | 2019-01-30 14:58:19 -0800 | [diff] [blame] | 76 | self.access_point = retail_ap.create(self.RetailAccessPoints)[0] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 77 | self.log_path = os.path.join(logging.log_path, 'results') |
Mark De Ruyter | 72f8df9 | 2020-02-12 13:44:49 -0800 | [diff] [blame] | 78 | os.makedirs(self.log_path, exist_ok=True) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 79 | self.log.info('Access Point Configuration: {}'.format( |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 80 | self.access_point.ap_settings)) |
Omar El Ayach | 9c56cf3 | 2019-09-19 13:07:51 -0700 | [diff] [blame] | 81 | if hasattr(self, 'bdf'): |
| 82 | self.log.info('Pushing WiFi BDF to DUT.') |
| 83 | wputils.push_bdf(self.dut, self.bdf) |
| 84 | if hasattr(self, 'firmware'): |
| 85 | self.log.info('Pushing WiFi firmware to DUT.') |
| 86 | wlanmdsp = [ |
| 87 | file for file in self.firmware if "wlanmdsp.mbn" in file |
| 88 | ][0] |
| 89 | data_msc = [file for file in self.firmware |
| 90 | if "Data.msc" in file][0] |
| 91 | wputils.push_firmware(self.dut, wlanmdsp, data_msc) |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 92 | self.testclass_results = [] |
| 93 | |
Omar El Ayach | 9c56cf3 | 2019-09-19 13:07:51 -0700 | [diff] [blame] | 94 | # Turn WiFi ON |
Omar El Ayach | d710909 | 2019-09-29 18:31:33 -0700 | [diff] [blame] | 95 | if self.testclass_params.get('airplane_mode', 1): |
| 96 | self.log.info('Turning on airplane mode.') |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 97 | asserts.assert_true(utils.force_airplane_mode(self.dut, True), |
| 98 | "Can not turn on airplane mode.") |
Omar El Ayach | 9c56cf3 | 2019-09-19 13:07:51 -0700 | [diff] [blame] | 99 | wutils.wifi_toggle_state(self.dut, True) |
| 100 | |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 101 | def teardown_test(self): |
| 102 | self.iperf_server.stop() |
| 103 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 104 | def pass_fail_check_rssi_stability(self, testcase_params, |
| 105 | postprocessed_results): |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 106 | """Check the test result and decide if it passed or failed. |
| 107 | |
| 108 | Checks the RSSI test result and fails the test if the standard |
| 109 | deviation of signal_poll_rssi is beyond the threshold defined in the |
| 110 | config file. |
| 111 | |
| 112 | Args: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 113 | testcase_params: dict containing test-specific parameters |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 114 | postprocessed_results: compiled arrays of RSSI measurements |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 115 | """ |
Omar El Ayach | 059c5cf | 2018-10-26 18:45:25 -0700 | [diff] [blame] | 116 | # Set Blackbox metric values |
Omar El Ayach | 02a1cce | 2019-09-19 17:51:39 -0700 | [diff] [blame] | 117 | if self.publish_test_metrics: |
| 118 | self.testcase_metric_logger.add_metric( |
| 119 | 'signal_poll_rssi_stdev', |
| 120 | max(postprocessed_results['signal_poll_rssi']['stdev'])) |
| 121 | self.testcase_metric_logger.add_metric( |
| 122 | 'chain_0_rssi_stdev', |
| 123 | max(postprocessed_results['chain_0_rssi']['stdev'])) |
| 124 | self.testcase_metric_logger.add_metric( |
| 125 | 'chain_1_rssi_stdev', |
| 126 | max(postprocessed_results['chain_1_rssi']['stdev'])) |
Omar El Ayach | a7c3afe | 2019-09-16 15:58:29 -0700 | [diff] [blame] | 127 | |
Omar El Ayach | 059c5cf | 2018-10-26 18:45:25 -0700 | [diff] [blame] | 128 | # Evaluate test pass/fail |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 129 | test_failed = any([ |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 130 | stdev > self.testclass_params['stdev_tolerance'] |
| 131 | for stdev in postprocessed_results['signal_poll_rssi']['stdev'] |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 132 | ]) |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 133 | test_message = ( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 134 | 'RSSI stability {0}. Standard deviation was {1} dB ' |
| 135 | '(limit {2}), per chain standard deviation [{3}, {4}] dB'.format( |
| 136 | 'failed' * test_failed + 'passed' * (not test_failed), [ |
| 137 | float('{:.2f}'.format(x)) |
| 138 | for x in postprocessed_results['signal_poll_rssi']['stdev'] |
| 139 | ], self.testclass_params['stdev_tolerance'], [ |
| 140 | float('{:.2f}'.format(x)) |
| 141 | for x in postprocessed_results['chain_0_rssi']['stdev'] |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 142 | ], [ |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 143 | float('{:.2f}'.format(x)) |
| 144 | for x in postprocessed_results['chain_1_rssi']['stdev'] |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 145 | ])) |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 146 | if test_failed: |
| 147 | asserts.fail(test_message) |
| 148 | asserts.explicit_pass(test_message) |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 149 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 150 | def pass_fail_check_rssi_accuracy(self, testcase_params, |
| 151 | postprocessed_results): |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 152 | """Check the test result and decide if it passed or failed. |
| 153 | |
| 154 | Checks the RSSI test result and compares and compute its deviation from |
| 155 | the predicted RSSI. This computation is done for all reported RSSI |
| 156 | values. The test fails if any of the RSSI values specified in |
| 157 | rssi_under_test have an average error beyond what is specified in the |
| 158 | configuration file. |
| 159 | |
| 160 | Args: |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 161 | postprocessed_results: compiled arrays of RSSI measurements |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 162 | testcase_params: dict containing params such as list of RSSIs under |
| 163 | test, i.e., can cause test to fail and boolean indicating whether |
| 164 | to look at absolute RSSI accuracy, or centered RSSI accuracy. |
| 165 | Centered accuracy is computed after systematic RSSI shifts are |
| 166 | removed. |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 167 | """ |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 168 | test_failed = False |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 169 | test_message = '' |
| 170 | if testcase_params['absolute_accuracy']: |
| 171 | error_type = 'absolute' |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 172 | else: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 173 | error_type = 'centered' |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 174 | |
| 175 | for key, val in postprocessed_results.items(): |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 176 | # Compute the error metrics ignoring invalid RSSI readings |
| 177 | # If all readings invalid, set error to RSSI_ERROR_VAL |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 178 | if 'rssi' in key and 'predicted' not in key: |
| 179 | filtered_error = [x for x in val['error'] if not math.isnan(x)] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 180 | if filtered_error: |
| 181 | avg_shift = statistics.mean(filtered_error) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 182 | if testcase_params['absolute_accuracy']: |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 183 | avg_error = statistics.mean( |
| 184 | [abs(x) for x in filtered_error]) |
| 185 | else: |
| 186 | avg_error = statistics.mean( |
| 187 | [abs(x - avg_shift) for x in filtered_error]) |
| 188 | else: |
| 189 | avg_error = RSSI_ERROR_VAL |
| 190 | avg_shift = RSSI_ERROR_VAL |
Omar El Ayach | 059c5cf | 2018-10-26 18:45:25 -0700 | [diff] [blame] | 191 | # Set Blackbox metric values |
Omar El Ayach | 02a1cce | 2019-09-19 17:51:39 -0700 | [diff] [blame] | 192 | if self.publish_test_metrics: |
| 193 | self.testcase_metric_logger.add_metric( |
| 194 | '{}_error'.format(key), avg_error) |
| 195 | self.testcase_metric_logger.add_metric( |
| 196 | '{}_shift'.format(key), avg_shift) |
Omar El Ayach | 059c5cf | 2018-10-26 18:45:25 -0700 | [diff] [blame] | 197 | # Evaluate test pass/fail |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 198 | rssi_failure = (avg_error > |
| 199 | self.testclass_params['abs_tolerance'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 200 | ) or math.isnan(avg_error) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 201 | if rssi_failure and key in testcase_params['rssi_under_test']: |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 202 | test_message = test_message + ( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 203 | '{} failed ({} error = {:.2f} dB, ' |
| 204 | 'shift = {:.2f} dB)\n').format(key, error_type, |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 205 | avg_error, avg_shift) |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 206 | test_failed = True |
| 207 | elif rssi_failure: |
| 208 | test_message = test_message + ( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 209 | '{} failed (ignored) ({} error = {:.2f} dB, ' |
| 210 | 'shift = {:.2f} dB)\n').format(key, error_type, |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 211 | avg_error, avg_shift) |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 212 | else: |
| 213 | test_message = test_message + ( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 214 | '{} passed ({} error = {:.2f} dB, ' |
| 215 | 'shift = {:.2f} dB)\n').format(key, error_type, |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 216 | avg_error, avg_shift) |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 217 | if test_failed: |
| 218 | asserts.fail(test_message) |
| 219 | asserts.explicit_pass(test_message) |
| 220 | |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 221 | def post_process_rssi_sweep(self, rssi_result): |
| 222 | """Postprocesses and saves JSON formatted results. |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 223 | |
| 224 | Args: |
| 225 | rssi_result: dict containing attenuation, rssi and other meta |
| 226 | data |
| 227 | Returns: |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 228 | postprocessed_results: compiled arrays of RSSI data used in |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 229 | pass/fail check |
| 230 | """ |
| 231 | # Save output as text file |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 232 | results_file_path = os.path.join(self.log_path, self.current_test_name) |
| 233 | with open(results_file_path, 'w') as results_file: |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 234 | json.dump(rssi_result, results_file, indent=4) |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 235 | # Compile results into arrays of RSSIs suitable for plotting |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 236 | # yapf: disable |
| 237 | postprocessed_results = collections.OrderedDict( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 238 | [('signal_poll_rssi', {}), |
| 239 | ('signal_poll_avg_rssi', {}), |
| 240 | ('scan_rssi', {}), |
| 241 | ('chain_0_rssi', {}), |
| 242 | ('chain_1_rssi', {}), |
| 243 | ('total_attenuation', []), |
| 244 | ('predicted_rssi', [])]) |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 245 | # yapf: enable |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 246 | for key, val in postprocessed_results.items(): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 247 | if 'scan_rssi' in key: |
| 248 | postprocessed_results[key]['data'] = [ |
| 249 | x for data_point in rssi_result['rssi_result'] for x in |
| 250 | data_point[key][rssi_result['connected_bssid']]['data'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 251 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 252 | postprocessed_results[key]['mean'] = [ |
| 253 | x[key][rssi_result['connected_bssid']]['mean'] |
| 254 | for x in rssi_result['rssi_result'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 255 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 256 | postprocessed_results[key]['stdev'] = [ |
| 257 | x[key][rssi_result['connected_bssid']]['stdev'] |
| 258 | for x in rssi_result['rssi_result'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 259 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 260 | elif 'predicted_rssi' in key: |
| 261 | postprocessed_results['total_attenuation'] = [ |
| 262 | att + rssi_result['fixed_attenuation'] + |
| 263 | rssi_result['dut_front_end_loss'] |
| 264 | for att in rssi_result['attenuation'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 265 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 266 | postprocessed_results['predicted_rssi'] = [ |
| 267 | rssi_result['ap_tx_power'] - att |
| 268 | for att in postprocessed_results['total_attenuation'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 269 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 270 | elif 'rssi' in key: |
| 271 | postprocessed_results[key]['data'] = [ |
| 272 | x for data_point in rssi_result['rssi_result'] |
| 273 | for x in data_point[key]['data'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 274 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 275 | postprocessed_results[key]['mean'] = [ |
| 276 | x[key]['mean'] for x in rssi_result['rssi_result'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 277 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 278 | postprocessed_results[key]['stdev'] = [ |
| 279 | x[key]['stdev'] for x in rssi_result['rssi_result'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 280 | ] |
| 281 | # Compute RSSI errors |
| 282 | for key, val in postprocessed_results.items(): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 283 | if 'chain' in key: |
| 284 | postprocessed_results[key]['error'] = [ |
| 285 | postprocessed_results[key]['mean'][idx] + CONST_3dB - |
| 286 | postprocessed_results['predicted_rssi'][idx] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 287 | for idx in range( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 288 | len(postprocessed_results['predicted_rssi'])) |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 289 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 290 | elif 'rssi' in key and 'predicted' not in key: |
| 291 | postprocessed_results[key]['error'] = [ |
| 292 | postprocessed_results[key]['mean'][idx] - |
| 293 | postprocessed_results['predicted_rssi'][idx] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 294 | for idx in range( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 295 | len(postprocessed_results['predicted_rssi'])) |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 296 | ] |
| 297 | return postprocessed_results |
| 298 | |
| 299 | def plot_rssi_vs_attenuation(self, postprocessed_results): |
| 300 | """Function to plot RSSI vs attenuation sweeps |
| 301 | |
| 302 | Args: |
| 303 | postprocessed_results: compiled arrays of RSSI data. |
| 304 | """ |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 305 | figure = wputils.BokehFigure(self.current_test_name, |
| 306 | x_label='Attenuation (dB)', |
| 307 | primary_y_label='RSSI (dBm)') |
| 308 | figure.add_line(postprocessed_results['total_attenuation'], |
| 309 | postprocessed_results['signal_poll_rssi']['mean'], |
| 310 | 'Signal Poll RSSI', |
| 311 | marker='circle') |
| 312 | figure.add_line(postprocessed_results['total_attenuation'], |
| 313 | postprocessed_results['scan_rssi']['mean'], |
| 314 | 'Scan RSSI', |
| 315 | marker='circle') |
| 316 | figure.add_line(postprocessed_results['total_attenuation'], |
| 317 | postprocessed_results['chain_0_rssi']['mean'], |
| 318 | 'Chain 0 RSSI', |
| 319 | marker='circle') |
| 320 | figure.add_line(postprocessed_results['total_attenuation'], |
| 321 | postprocessed_results['chain_1_rssi']['mean'], |
| 322 | 'Chain 1 RSSI', |
| 323 | marker='circle') |
| 324 | figure.add_line(postprocessed_results['total_attenuation'], |
| 325 | postprocessed_results['predicted_rssi'], |
| 326 | 'Predicted RSSI', |
| 327 | marker='circle') |
Omar El Ayach | 37be28a | 2019-04-10 16:29:26 -0700 | [diff] [blame] | 328 | |
| 329 | output_file_path = os.path.join(self.log_path, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 330 | self.current_test_name + '.html') |
Omar El Ayach | 37be28a | 2019-04-10 16:29:26 -0700 | [diff] [blame] | 331 | figure.generate_figure(output_file_path) |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 332 | |
| 333 | def plot_rssi_vs_time(self, rssi_result, postprocessed_results, |
| 334 | center_curves): |
| 335 | """Function to plot RSSI vs time. |
| 336 | |
| 337 | Args: |
| 338 | rssi_result: dict containing raw RSSI data |
| 339 | postprocessed_results: compiled arrays of RSSI data |
| 340 | center_curvers: boolean indicating whether to shift curves to align |
| 341 | them with predicted RSSIs |
| 342 | """ |
Omar El Ayach | 37be28a | 2019-04-10 16:29:26 -0700 | [diff] [blame] | 343 | figure = wputils.BokehFigure( |
| 344 | self.current_test_name, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 345 | x_label='Time (s)', |
Omar El Ayach | 954eb28 | 2019-09-30 15:33:32 -0700 | [diff] [blame] | 346 | primary_y_label=center_curves * 'Centered' + 'RSSI (dBm)', |
Omar El Ayach | 37be28a | 2019-04-10 16:29:26 -0700 | [diff] [blame] | 347 | ) |
| 348 | |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 349 | # yapf: disable |
| 350 | rssi_time_series = collections.OrderedDict( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 351 | [('signal_poll_rssi', []), |
| 352 | ('signal_poll_avg_rssi', []), |
| 353 | ('scan_rssi', []), |
| 354 | ('chain_0_rssi', []), |
| 355 | ('chain_1_rssi', []), |
| 356 | ('predicted_rssi', [])]) |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 357 | # yapf: enable |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 358 | for key, val in rssi_time_series.items(): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 359 | if 'predicted_rssi' in key: |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 360 | rssi_time_series[key] = [ |
| 361 | x for x in postprocessed_results[key] for copies in range( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 362 | len(rssi_result['rssi_result'][0]['signal_poll_rssi'] |
| 363 | ['data'])) |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 364 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 365 | elif 'rssi' in key: |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 366 | if center_curves: |
| 367 | filtered_error = [ |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 368 | x for x in postprocessed_results[key]['error'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 369 | if not math.isnan(x) |
| 370 | ] |
| 371 | if filtered_error: |
| 372 | avg_shift = statistics.mean(filtered_error) |
| 373 | else: |
| 374 | avg_shift = 0 |
| 375 | rssi_time_series[key] = [ |
| 376 | x - avg_shift |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 377 | for x in postprocessed_results[key]['data'] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 378 | ] |
| 379 | else: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 380 | rssi_time_series[key] = postprocessed_results[key]['data'] |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 381 | time_vec = [ |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 382 | self.testclass_params['polling_frequency'] * x |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 383 | for x in range(len(rssi_time_series[key])) |
| 384 | ] |
| 385 | if len(rssi_time_series[key]) > 0: |
Omar El Ayach | 37be28a | 2019-04-10 16:29:26 -0700 | [diff] [blame] | 386 | figure.add_line(time_vec, rssi_time_series[key], key) |
| 387 | |
| 388 | output_file_path = os.path.join(self.log_path, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 389 | self.current_test_name + '.html') |
Omar El Ayach | 37be28a | 2019-04-10 16:29:26 -0700 | [diff] [blame] | 390 | figure.generate_figure(output_file_path) |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 391 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 392 | def plot_rssi_distribution(self, postprocessed_results): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 393 | """Function to plot RSSI distributions. |
| 394 | |
| 395 | Args: |
| 396 | postprocessed_results: compiled arrays of RSSI data |
| 397 | """ |
| 398 | monitored_rssis = ['signal_poll_rssi', 'chain_0_rssi', 'chain_1_rssi'] |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 399 | |
| 400 | rssi_dist = collections.OrderedDict() |
| 401 | for rssi_key in monitored_rssis: |
| 402 | rssi_data = postprocessed_results[rssi_key] |
| 403 | rssi_dist[rssi_key] = collections.OrderedDict() |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 404 | unique_rssi = sorted(set(rssi_data['data'])) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 405 | rssi_counts = [] |
| 406 | for value in unique_rssi: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 407 | rssi_counts.append(rssi_data['data'].count(value)) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 408 | total_count = sum(rssi_counts) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 409 | rssi_dist[rssi_key]['rssi_values'] = unique_rssi |
| 410 | rssi_dist[rssi_key]['rssi_pdf'] = [ |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 411 | x / total_count for x in rssi_counts |
| 412 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 413 | rssi_dist[rssi_key]['rssi_cdf'] = [] |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 414 | cum_prob = 0 |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 415 | for prob in rssi_dist[rssi_key]['rssi_pdf']: |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 416 | cum_prob += prob |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 417 | rssi_dist[rssi_key]['rssi_cdf'].append(cum_prob) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 418 | |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 419 | figure = wputils.BokehFigure(self.current_test_name, |
| 420 | x_label='RSSI (dBm)', |
| 421 | primary_y_label='p(RSSI = x)', |
| 422 | secondary_y_label='p(RSSI <= x)') |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 423 | for rssi_key, rssi_data in rssi_dist.items(): |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 424 | figure.add_line(x_data=rssi_data['rssi_values'], |
| 425 | y_data=rssi_data['rssi_pdf'], |
| 426 | legend='{} PDF'.format(rssi_key), |
| 427 | y_axis='default') |
| 428 | figure.add_line(x_data=rssi_data['rssi_values'], |
| 429 | y_data=rssi_data['rssi_cdf'], |
| 430 | legend='{} CDF'.format(rssi_key), |
| 431 | y_axis='secondary') |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 432 | output_file_path = os.path.join(self.log_path, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 433 | self.current_test_name + '_dist.html') |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 434 | figure.generate_figure(output_file_path) |
| 435 | |
| 436 | def run_rssi_test(self, testcase_params): |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 437 | """Test function to run RSSI tests. |
| 438 | |
| 439 | The function runs an RSSI test in the current device/AP configuration. |
| 440 | Function is called from another wrapper function that sets up the |
| 441 | testbed for the RvR test |
| 442 | |
| 443 | Args: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 444 | testcase_params: dict containing test-specific parameters |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 445 | Returns: |
| 446 | rssi_result: dict containing rssi_result and meta data |
| 447 | """ |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 448 | # Run test and log result |
Omar El Ayach | 74f78dc | 2019-07-30 15:15:34 -0700 | [diff] [blame] | 449 | rssi_result = collections.OrderedDict() |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 450 | rssi_result['test_name'] = self.current_test_name |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 451 | rssi_result['testcase_params'] = testcase_params |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 452 | rssi_result['ap_settings'] = self.access_point.ap_settings.copy() |
| 453 | rssi_result['attenuation'] = list(testcase_params['rssi_atten_range']) |
| 454 | rssi_result['connected_bssid'] = self.main_network[ |
| 455 | testcase_params['band']].get('BSSID', '00:00:00:00') |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 456 | channel_mode_combo = '{}_{}'.format(str(testcase_params['channel']), |
| 457 | testcase_params['mode']) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 458 | channel_str = str(testcase_params['channel']) |
| 459 | if channel_mode_combo in self.testbed_params['ap_tx_power']: |
| 460 | rssi_result['ap_tx_power'] = self.testbed_params['ap_tx_power'][ |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 461 | channel_mode_combo] |
| 462 | else: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 463 | rssi_result['ap_tx_power'] = self.testbed_params['ap_tx_power'][ |
| 464 | str(testcase_params['channel'])] |
| 465 | rssi_result['fixed_attenuation'] = self.testbed_params[ |
| 466 | 'fixed_attenuation'][channel_str] |
| 467 | rssi_result['dut_front_end_loss'] = self.testbed_params[ |
| 468 | 'dut_front_end_loss'][channel_str] |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 469 | |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 470 | self.log.info('Start running RSSI test.') |
| 471 | rssi_result['rssi_result'] = [] |
| 472 | rssi_result['llstats'] = [] |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 473 | llstats_obj = wputils.LinkLayerStats(self.dut) |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 474 | # Start iperf traffic if required by test |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 475 | if testcase_params['active_traffic'] and testcase_params[ |
| 476 | 'traffic_type'] == 'iperf': |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 477 | self.iperf_server.start(tag=0) |
Omar El Ayach | 14416ac | 2019-01-30 14:58:19 -0800 | [diff] [blame] | 478 | if isinstance(self.iperf_server, ipf.IPerfServerOverAdb): |
| 479 | iperf_server_address = self.dut_ip |
| 480 | else: |
Omar El Ayach | 2819be6 | 2019-04-11 12:00:00 -0700 | [diff] [blame] | 481 | iperf_server_address = wputils.get_server_address( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 482 | self.remote_server, self.dut_ip, '255.255.255.0') |
Omar El Ayach | 14416ac | 2019-01-30 14:58:19 -0800 | [diff] [blame] | 483 | executor = ThreadPoolExecutor(max_workers=1) |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 484 | thread_future = executor.submit( |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 485 | self.iperf_client.start, iperf_server_address, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 486 | testcase_params['iperf_args'], 0, |
| 487 | testcase_params['traffic_timeout'] + SHORT_SLEEP) |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 488 | executor.shutdown(wait=False) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 489 | elif testcase_params['active_traffic'] and testcase_params[ |
| 490 | 'traffic_type'] == 'ping': |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 491 | thread_future = wputils.get_ping_stats_nb( |
| 492 | self.remote_server, self.dut_ip, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 493 | testcase_params['traffic_timeout'], 0.02, 64) |
| 494 | for atten in testcase_params['rssi_atten_range']: |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 495 | # Set Attenuation |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 496 | self.log.info('Setting attenuation to {} dB'.format(atten)) |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 497 | for attenuator in self.attenuators: |
| 498 | attenuator.set_atten(atten) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 499 | llstats_obj.update_stats() |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 500 | current_rssi = collections.OrderedDict() |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 501 | current_rssi = wputils.get_connected_rssi( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 502 | self.dut, testcase_params['connected_measurements'], |
| 503 | self.testclass_params['polling_frequency'], |
| 504 | testcase_params['first_measurement_delay']) |
| 505 | current_rssi['scan_rssi'] = wputils.get_scan_rssi( |
| 506 | self.dut, testcase_params['tracked_bssid'], |
| 507 | testcase_params['scan_measurements']) |
| 508 | rssi_result['rssi_result'].append(current_rssi) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 509 | llstats_obj.update_stats() |
| 510 | curr_llstats = llstats_obj.llstats_incremental.copy() |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 511 | rssi_result['llstats'].append(curr_llstats) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 512 | self.log.info( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 513 | 'Connected RSSI at {0:.2f} dB is {1:.2f} [{2:.2f}, {3:.2f}] dB' |
| 514 | .format(atten, current_rssi['signal_poll_rssi']['mean'], |
| 515 | current_rssi['chain_0_rssi']['mean'], |
| 516 | current_rssi['chain_1_rssi']['mean'])) |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 517 | # Stop iperf traffic if needed |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 518 | for attenuator in self.attenuators: |
| 519 | attenuator.set_atten(0) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 520 | if testcase_params['active_traffic']: |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 521 | thread_future.result() |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 522 | if testcase_params['traffic_type'] == 'iperf': |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 523 | self.iperf_server.stop() |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 524 | return rssi_result |
| 525 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 526 | def setup_ap(self, testcase_params): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 527 | """Function that gets devices ready for the test. |
| 528 | |
| 529 | Args: |
| 530 | testcase_params: dict containing test-specific parameters |
| 531 | """ |
| 532 | if '2G' in testcase_params['band']: |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 533 | frequency = wutils.WifiEnums.channel_2G_to_freq[ |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 534 | testcase_params['channel']] |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 535 | else: |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 536 | frequency = wutils.WifiEnums.channel_5G_to_freq[ |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 537 | testcase_params['channel']] |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 538 | if frequency in wutils.WifiEnums.DFS_5G_FREQUENCIES: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 539 | self.access_point.set_region(self.testbed_params['DFS_region']) |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 540 | else: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 541 | self.access_point.set_region(self.testbed_params['default_region']) |
| 542 | self.access_point.set_channel(testcase_params['band'], |
| 543 | testcase_params['channel']) |
| 544 | self.access_point.set_bandwidth(testcase_params['band'], |
| 545 | testcase_params['mode']) |
| 546 | self.log.info('Access Point Configuration: {}'.format( |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 547 | self.access_point.ap_settings)) |
| 548 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 549 | def setup_dut(self, testcase_params): |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 550 | """Sets up the DUT in the configuration required by the test.""" |
Omar El Ayach | 656bf3d | 2019-07-31 15:04:53 -0700 | [diff] [blame] | 551 | # Check battery level before test |
| 552 | if not wputils.health_check(self.dut, 10): |
| 553 | asserts.skip('Battery level too low. Skipping test.') |
| 554 | # Turn screen off to preserve battery |
| 555 | self.dut.go_to_sleep() |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 556 | if wputils.validate_network(self.dut, |
| 557 | testcase_params['test_network']['SSID']): |
Omar El Ayach | 39acf80 | 2019-08-02 17:52:39 -0700 | [diff] [blame] | 558 | self.log.info('Already connected to desired network') |
| 559 | else: |
| 560 | wutils.wifi_toggle_state(self.dut, True) |
| 561 | wutils.reset_wifi(self.dut) |
| 562 | self.main_network[testcase_params['band']][ |
| 563 | 'channel'] = testcase_params['channel'] |
Roshan Pius | 5b19a12 | 2019-09-13 08:07:30 -0700 | [diff] [blame] | 564 | wutils.set_wifi_country_code(self.dut, |
Omar El Ayach | 39acf80 | 2019-08-02 17:52:39 -0700 | [diff] [blame] | 565 | self.testclass_params['country_code']) |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 566 | wutils.wifi_connect(self.dut, |
| 567 | self.main_network[testcase_params['band']], |
| 568 | num_of_tries=5) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 569 | self.dut_ip = self.dut.droid.connectivityGetIPv4Addresses('wlan0')[0] |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 570 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 571 | def setup_rssi_test(self, testcase_params): |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 572 | """Main function to test RSSI. |
| 573 | |
| 574 | The function sets up the AP in the correct channel and mode |
| 575 | configuration and called rssi_test to sweep attenuation and measure |
| 576 | RSSI |
| 577 | |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 578 | Args: |
| 579 | testcase_params: dict containing test-specific parameters |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 580 | Returns: |
| 581 | rssi_result: dict containing rssi_results and meta data |
| 582 | """ |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 583 | # Configure AP |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 584 | self.setup_ap(testcase_params) |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 585 | # Initialize attenuators |
Omar El Ayach | 5c9d3d5 | 2018-10-17 17:59:09 -0700 | [diff] [blame] | 586 | for attenuator in self.attenuators: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 587 | attenuator.set_atten(testcase_params['rssi_atten_range'][0]) |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 588 | # Connect DUT to Network |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 589 | self.setup_dut(testcase_params) |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 590 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 591 | def get_traffic_timeout(self, testcase_params): |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 592 | """Function to comput iperf session length required in RSSI test. |
| 593 | |
| 594 | Args: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 595 | testcase_params: dict containing test-specific parameters |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 596 | Returns: |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 597 | traffic_timeout: length of iperf session required in rssi test |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 598 | """ |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 599 | atten_step_duration = testcase_params['first_measurement_delay'] + ( |
| 600 | testcase_params['connected_measurements'] * |
| 601 | self.testclass_params['polling_frequency'] |
| 602 | ) + testcase_params['scan_measurements'] * MED_SLEEP |
| 603 | timeout = len(testcase_params['rssi_atten_range'] |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 604 | ) * atten_step_duration + MED_SLEEP |
| 605 | return timeout |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 606 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 607 | def compile_rssi_vs_atten_test_params(self, testcase_params): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 608 | """Function to complete compiling test-specific parameters |
| 609 | |
| 610 | Args: |
| 611 | testcase_params: dict containing test-specific parameters |
| 612 | """ |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 613 | testcase_params.update( |
| 614 | connected_measurements=self. |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 615 | testclass_params['rssi_vs_atten_connected_measurements'], |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 616 | scan_measurements=self. |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 617 | testclass_params['rssi_vs_atten_scan_measurements'], |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 618 | first_measurement_delay=MED_SLEEP, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 619 | rssi_under_test=self.testclass_params['rssi_vs_atten_metrics'], |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 620 | absolute_accuracy=1) |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 621 | |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 622 | testcase_params['band'] = self.access_point.band_lookup_by_channel( |
| 623 | testcase_params['channel']) |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 624 | testcase_params['test_network'] = self.main_network[ |
| 625 | testcase_params['band']] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 626 | testcase_params['tracked_bssid'] = [ |
| 627 | self.main_network[testcase_params['band']].get( |
| 628 | 'BSSID', '00:00:00:00') |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 629 | ] |
| 630 | |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 631 | num_atten_steps = int((self.testclass_params['rssi_vs_atten_stop'] - |
| 632 | self.testclass_params['rssi_vs_atten_start']) / |
| 633 | self.testclass_params['rssi_vs_atten_step']) |
| 634 | testcase_params['rssi_atten_range'] = [ |
| 635 | self.testclass_params['rssi_vs_atten_start'] + |
| 636 | x * self.testclass_params['rssi_vs_atten_step'] |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 637 | for x in range(0, num_atten_steps) |
| 638 | ] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 639 | testcase_params['traffic_timeout'] = self.get_traffic_timeout( |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 640 | testcase_params) |
| 641 | |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 642 | if isinstance(self.iperf_server, ipf.IPerfServerOverAdb): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 643 | testcase_params['iperf_args'] = '-i 1 -t {} -J'.format( |
| 644 | testcase_params['traffic_timeout']) |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 645 | else: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 646 | testcase_params['iperf_args'] = '-i 1 -t {} -J -R'.format( |
| 647 | testcase_params['traffic_timeout']) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 648 | return testcase_params |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 649 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 650 | def compile_rssi_stability_test_params(self, testcase_params): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 651 | """Function to complete compiling test-specific parameters |
| 652 | |
| 653 | Args: |
| 654 | testcase_params: dict containing test-specific parameters |
| 655 | """ |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 656 | testcase_params.update( |
| 657 | connected_measurements=int( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 658 | self.testclass_params['rssi_stability_duration'] / |
| 659 | self.testclass_params['polling_frequency']), |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 660 | scan_measurements=0, |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 661 | first_measurement_delay=MED_SLEEP, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 662 | rssi_atten_range=self.testclass_params['rssi_stability_atten']) |
| 663 | testcase_params['band'] = self.access_point.band_lookup_by_channel( |
| 664 | testcase_params['channel']) |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 665 | testcase_params['test_network'] = self.main_network[ |
| 666 | testcase_params['band']] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 667 | testcase_params['tracked_bssid'] = [ |
| 668 | self.main_network[testcase_params['band']].get( |
| 669 | 'BSSID', '00:00:00:00') |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 670 | ] |
Omar El Ayach | e95eecc | 2018-02-27 16:12:08 -0800 | [diff] [blame] | 671 | |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 672 | testcase_params['traffic_timeout'] = self.get_traffic_timeout( |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 673 | testcase_params) |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 674 | if isinstance(self.iperf_server, ipf.IPerfServerOverAdb): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 675 | testcase_params['iperf_args'] = '-i 1 -t {} -J'.format( |
| 676 | testcase_params['traffic_timeout']) |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 677 | else: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 678 | testcase_params['iperf_args'] = '-i 1 -t {} -J -R'.format( |
| 679 | testcase_params['traffic_timeout']) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 680 | return testcase_params |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 681 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 682 | def compile_rssi_tracking_test_params(self, testcase_params): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 683 | """Function to complete compiling test-specific parameters |
| 684 | |
| 685 | Args: |
| 686 | testcase_params: dict containing test-specific parameters |
| 687 | """ |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 688 | testcase_params.update(connected_measurements=int( |
| 689 | 1 / self.testclass_params['polling_frequency']), |
| 690 | scan_measurements=0, |
| 691 | first_measurement_delay=0, |
| 692 | rssi_under_test=['signal_poll_rssi'], |
| 693 | absolute_accuracy=0) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 694 | testcase_params['band'] = self.access_point.band_lookup_by_channel( |
| 695 | testcase_params['channel']) |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 696 | testcase_params['test_network'] = self.main_network[ |
| 697 | testcase_params['band']] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 698 | testcase_params['tracked_bssid'] = [ |
| 699 | self.main_network[testcase_params['band']].get( |
| 700 | 'BSSID', '00:00:00:00') |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 701 | ] |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 702 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 703 | rssi_atten_range = [] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 704 | for waveform in self.testclass_params['rssi_tracking_waveforms']: |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 705 | waveform_vector = [] |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 706 | for section in range(len(waveform['atten_levels']) - 1): |
| 707 | section_limits = waveform['atten_levels'][section:section + 2] |
Omar El Ayach | 319fb89 | 2019-02-21 16:10:08 -0800 | [diff] [blame] | 708 | up_down = (1 - 2 * (section_limits[1] < section_limits[0])) |
| 709 | temp_section = list( |
| 710 | range(section_limits[0], section_limits[1] + up_down, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 711 | up_down * waveform['step_size'])) |
Omar El Ayach | 319fb89 | 2019-02-21 16:10:08 -0800 | [diff] [blame] | 712 | temp_section = [ |
| 713 | temp_section[idx] for idx in range(len(temp_section)) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 714 | for n in range(waveform['step_duration']) |
Omar El Ayach | 319fb89 | 2019-02-21 16:10:08 -0800 | [diff] [blame] | 715 | ] |
| 716 | waveform_vector += temp_section |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 717 | waveform_vector = waveform_vector * waveform['repetitions'] |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 718 | rssi_atten_range = rssi_atten_range + waveform_vector |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 719 | testcase_params['rssi_atten_range'] = rssi_atten_range |
| 720 | testcase_params['traffic_timeout'] = self.get_traffic_timeout( |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 721 | testcase_params) |
| 722 | |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 723 | if isinstance(self.iperf_server, ipf.IPerfServerOverAdb): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 724 | testcase_params['iperf_args'] = '-i 1 -t {} -J'.format( |
| 725 | testcase_params['traffic_timeout']) |
Omar El Ayach | 4853314 | 2019-02-20 15:56:34 -0800 | [diff] [blame] | 726 | else: |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 727 | testcase_params['iperf_args'] = '-i 1 -t {} -J -R'.format( |
| 728 | testcase_params['traffic_timeout']) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 729 | return testcase_params |
| 730 | |
| 731 | def _test_rssi_vs_atten(self, testcase_params): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 732 | """Function that gets called for each test case of rssi_vs_atten |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 733 | |
| 734 | The function gets called in each rssi test case. The function |
| 735 | customizes the test based on the test name of the test that called it |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 736 | |
| 737 | Args: |
| 738 | testcase_params: dict containing test-specific parameters |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 739 | """ |
| 740 | testcase_params = self.compile_rssi_vs_atten_test_params( |
| 741 | testcase_params) |
| 742 | |
| 743 | self.setup_rssi_test(testcase_params) |
| 744 | rssi_result = self.run_rssi_test(testcase_params) |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 745 | rssi_result['postprocessed_results'] = self.post_process_rssi_sweep( |
| 746 | rssi_result) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 747 | self.testclass_results.append(rssi_result) |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 748 | self.plot_rssi_vs_attenuation(rssi_result['postprocessed_results']) |
| 749 | self.pass_fail_check_rssi_accuracy( |
| 750 | testcase_params, rssi_result['postprocessed_results']) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 751 | |
| 752 | def _test_rssi_stability(self, testcase_params): |
| 753 | """ Function that gets called for each test case of rssi_stability |
| 754 | |
| 755 | The function gets called in each stability test case. The function |
| 756 | customizes test based on the test name of the test that called it |
| 757 | """ |
| 758 | testcase_params = self.compile_rssi_stability_test_params( |
| 759 | testcase_params) |
| 760 | |
| 761 | self.setup_rssi_test(testcase_params) |
| 762 | rssi_result = self.run_rssi_test(testcase_params) |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 763 | rssi_result['postprocessed_results'] = self.post_process_rssi_sweep( |
| 764 | rssi_result) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 765 | self.testclass_results.append(rssi_result) |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 766 | self.plot_rssi_vs_time(rssi_result, |
| 767 | rssi_result['postprocessed_results'], 1) |
| 768 | self.plot_rssi_distribution(rssi_result['postprocessed_results']) |
| 769 | self.pass_fail_check_rssi_stability( |
| 770 | testcase_params, rssi_result['postprocessed_results']) |
Omar El Ayach | ea96339 | 2018-03-07 09:31:55 -0800 | [diff] [blame] | 771 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 772 | def _test_rssi_tracking(self, testcase_params): |
| 773 | """ Function that gets called for each test case of rssi_tracking |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 774 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 775 | The function gets called in each rssi test case. The function |
| 776 | customizes the test based on the test name of the test that called it |
| 777 | """ |
| 778 | testcase_params = self.compile_rssi_tracking_test_params( |
| 779 | testcase_params) |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 780 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 781 | self.setup_rssi_test(testcase_params) |
| 782 | rssi_result = self.run_rssi_test(testcase_params) |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 783 | rssi_result['postprocessed_results'] = self.post_process_rssi_sweep( |
| 784 | rssi_result) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 785 | self.testclass_results.append(rssi_result) |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 786 | self.plot_rssi_vs_time(rssi_result, |
| 787 | rssi_result['postprocessed_results'], 1) |
| 788 | self.pass_fail_check_rssi_accuracy( |
| 789 | testcase_params, rssi_result['postprocessed_results']) |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 790 | |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 791 | def generate_test_cases(self, test_types, channels, modes, traffic_modes): |
| 792 | """Function that auto-generates test cases for a test class.""" |
| 793 | test_cases = [] |
| 794 | allowed_configs = { |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 795 | 'VHT20': [ |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 796 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 149, 153, |
| 797 | 157, 161 |
| 798 | ], |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 799 | 'VHT40': [36, 44, 149, 157], |
| 800 | 'VHT80': [36, 149] |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 801 | } |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 802 | |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 803 | for channel, mode, traffic_mode, test_type in itertools.product( |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 804 | channels, modes, traffic_modes, test_types): |
| 805 | if channel not in allowed_configs[mode]: |
| 806 | continue |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 807 | test_name = test_type + '_ch{}_{}_{}'.format( |
| 808 | channel, mode, traffic_mode) |
| 809 | testcase_params = collections.OrderedDict( |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 810 | channel=channel, |
| 811 | mode=mode, |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 812 | active_traffic=(traffic_mode == 'ActiveTraffic'), |
| 813 | traffic_type=self.user_params['rssi_test_params'] |
| 814 | ['traffic_type'], |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 815 | ) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 816 | test_function = getattr(self, '_{}'.format(test_type)) |
| 817 | setattr(self, test_name, partial(test_function, testcase_params)) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 818 | test_cases.append(test_name) |
| 819 | return test_cases |
Omar El Ayach | 8f7f0b2 | 2018-06-01 21:20:19 -0700 | [diff] [blame] | 820 | |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 821 | |
| 822 | class WifiRssi_2GHz_ActiveTraffic_Test(WifiRssiTest): |
| 823 | def __init__(self, controllers): |
Omar El Ayach | 059c5cf | 2018-10-26 18:45:25 -0700 | [diff] [blame] | 824 | super().__init__(controllers) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 825 | self.tests = self.generate_test_cases( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 826 | ['test_rssi_stability', 'test_rssi_vs_atten'], [1, 2, 6, 10, 11], |
| 827 | ['VHT20'], ['ActiveTraffic']) |
Omar El Ayach | e84e874 | 2018-03-19 16:42:44 -0700 | [diff] [blame] | 828 | |
| 829 | |
| 830 | class WifiRssi_5GHz_ActiveTraffic_Test(WifiRssiTest): |
| 831 | def __init__(self, controllers): |
Omar El Ayach | 059c5cf | 2018-10-26 18:45:25 -0700 | [diff] [blame] | 832 | super().__init__(controllers) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 833 | self.tests = self.generate_test_cases( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 834 | ['test_rssi_stability', 'test_rssi_vs_atten'], |
| 835 | [36, 40, 44, 48, 149, 153, 157, 161], ['VHT20', 'VHT40', 'VHT80'], |
| 836 | ['ActiveTraffic']) |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 837 | |
| 838 | |
| 839 | class WifiRssi_AllChannels_ActiveTraffic_Test(WifiRssiTest): |
| 840 | def __init__(self, controllers): |
| 841 | super().__init__(controllers) |
| 842 | self.tests = self.generate_test_cases( |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 843 | ['test_rssi_stability', 'test_rssi_vs_atten'], |
Omar El Ayach | d05bf02 | 2019-07-10 14:09:54 -0700 | [diff] [blame] | 844 | [1, 6, 11, 36, 40, 44, 48, 149, 153, 157, 161], |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 845 | ['VHT20', 'VHT40', 'VHT80'], ['ActiveTraffic']) |
Omar El Ayach | 35bc9cb | 2019-01-23 15:20:13 -0800 | [diff] [blame] | 846 | |
| 847 | |
Omar El Ayach | 92bc8fb | 2019-08-27 17:21:00 -0700 | [diff] [blame] | 848 | class WifiRssi_SampleChannels_NoTraffic_Test(WifiRssiTest): |
| 849 | def __init__(self, controllers): |
| 850 | super().__init__(controllers) |
| 851 | self.tests = self.generate_test_cases( |
| 852 | ['test_rssi_stability', 'test_rssi_vs_atten'], [6, 36, 149], |
| 853 | ['VHT20', 'VHT40', 'VHT80'], ['NoTraffic']) |
| 854 | |
| 855 | |
Omar El Ayach | 35bc9cb | 2019-01-23 15:20:13 -0800 | [diff] [blame] | 856 | class WifiRssiTrackingTest(WifiRssiTest): |
| 857 | def __init__(self, controllers): |
Omar El Ayach | 235a49f | 2019-01-23 15:35:24 -0800 | [diff] [blame] | 858 | super().__init__(controllers) |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 859 | self.tests = self.generate_test_cases(['test_rssi_tracking'], |
| 860 | [6, 36, 149], |
| 861 | ['VHT20', 'VHT40', 'VHT80'], |
| 862 | ['ActiveTraffic', 'NoTraffic']) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 863 | |
| 864 | |
| 865 | # Over-the air version of RSSI tests |
| 866 | class WifiOtaRssiTest(WifiRssiTest): |
| 867 | """Class to test over-the-air rssi tests. |
| 868 | |
| 869 | This class implements measures WiFi RSSI tests in an OTA chamber. |
| 870 | It allows setting orientation and other chamber parameters to study |
| 871 | performance in varying channel conditions |
| 872 | """ |
Omar El Ayach | 02a1cce | 2019-09-19 17:51:39 -0700 | [diff] [blame] | 873 | def __init__(self, controllers): |
| 874 | base_test.BaseTestClass.__init__(self, controllers) |
| 875 | self.testcase_metric_logger = ( |
Xianyuan Jia | 976d404 | 2019-09-30 17:19:47 -0700 | [diff] [blame] | 876 | BlackboxMappedMetricLogger.for_test_case()) |
Omar El Ayach | 02a1cce | 2019-09-19 17:51:39 -0700 | [diff] [blame] | 877 | self.testclass_metric_logger = ( |
Xianyuan Jia | 976d404 | 2019-09-30 17:19:47 -0700 | [diff] [blame] | 878 | BlackboxMappedMetricLogger.for_test_class()) |
Omar El Ayach | 02a1cce | 2019-09-19 17:51:39 -0700 | [diff] [blame] | 879 | self.publish_test_metrics = False |
| 880 | |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 881 | def setup_class(self): |
| 882 | WifiRssiTest.setup_class(self) |
| 883 | self.ota_chamber = ota_chamber.create( |
| 884 | self.user_params['OTAChamber'])[0] |
| 885 | |
| 886 | def teardown_class(self): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 887 | self.ota_chamber.reset_chamber() |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 888 | self.process_testclass_results() |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 889 | |
| 890 | def teardown_test(self): |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 891 | if self.ota_chamber.current_mode == 'continuous': |
| 892 | self.ota_chamber.reset_chamber() |
| 893 | |
| 894 | def extract_test_id(self, testcase_params, id_fields): |
| 895 | test_id = collections.OrderedDict( |
| 896 | (param, testcase_params[param]) for param in id_fields) |
| 897 | return test_id |
| 898 | |
| 899 | def process_testclass_results(self): |
| 900 | """Saves all test results to enable comparison.""" |
| 901 | testclass_data = collections.OrderedDict() |
| 902 | for test_result in self.testclass_results: |
| 903 | current_params = test_result['testcase_params'] |
| 904 | |
| 905 | channel = current_params['channel'] |
| 906 | channel_data = testclass_data.setdefault( |
| 907 | channel, |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 908 | collections.OrderedDict(orientation=[], |
| 909 | rssi=collections.OrderedDict( |
| 910 | signal_poll_rssi=[], |
| 911 | chain_0_rssi=[], |
| 912 | chain_1_rssi=[]))) |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 913 | |
| 914 | channel_data['orientation'].append(current_params['orientation']) |
| 915 | channel_data['rssi']['signal_poll_rssi'].append( |
| 916 | test_result['postprocessed_results']['signal_poll_rssi'] |
| 917 | ['mean'][0]) |
| 918 | channel_data['rssi']['chain_0_rssi'].append( |
| 919 | test_result['postprocessed_results']['chain_0_rssi']['mean'] |
| 920 | [0]) |
| 921 | channel_data['rssi']['chain_1_rssi'].append( |
| 922 | test_result['postprocessed_results']['chain_1_rssi']['mean'] |
| 923 | [0]) |
| 924 | |
| 925 | chamber_mode = self.testclass_results[0]['testcase_params'][ |
| 926 | 'chamber_mode'] |
| 927 | if chamber_mode == 'orientation': |
| 928 | x_label = 'Angle (deg)' |
| 929 | elif chamber_mode == 'stepped stirrers': |
| 930 | x_label = 'Position Index' |
| 931 | |
| 932 | # Publish test class metrics |
| 933 | for channel, channel_data in testclass_data.items(): |
| 934 | for rssi_metric, rssi_metric_value in channel_data['rssi'].items(): |
| 935 | metric_name = 'ota_summary_ch{}.avg_{}'.format( |
| 936 | channel, rssi_metric) |
| 937 | metric_value = numpy.mean(rssi_metric_value) |
| 938 | self.testclass_metric_logger.add_metric( |
| 939 | metric_name, metric_value) |
| 940 | |
| 941 | # Plot test class results |
| 942 | plots = [] |
| 943 | for channel, channel_data in testclass_data.items(): |
| 944 | current_plot = wputils.BokehFigure( |
| 945 | title='Channel {} - Rssi vs. Position'.format(channel), |
| 946 | x_label=x_label, |
Omar El Ayach | 954eb28 | 2019-09-30 15:33:32 -0700 | [diff] [blame] | 947 | primary_y_label='RSSI (dBm)', |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 948 | ) |
| 949 | for rssi_metric, rssi_metric_value in channel_data['rssi'].items(): |
| 950 | legend = rssi_metric |
| 951 | current_plot.add_line(channel_data['orientation'], |
| 952 | rssi_metric_value, legend) |
| 953 | current_plot.generate_figure() |
| 954 | plots.append(current_plot) |
| 955 | current_context = context.get_current_context().get_full_output_path() |
| 956 | plot_file_path = os.path.join(current_context, 'results.html') |
| 957 | wputils.BokehFigure.save_figures(plots, plot_file_path) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 958 | |
| 959 | def setup_rssi_test(self, testcase_params): |
| 960 | # Test setup |
| 961 | WifiRssiTest.setup_rssi_test(self, testcase_params) |
| 962 | if testcase_params['chamber_mode'] == 'StirrersOn': |
| 963 | self.ota_chamber.start_continuous_stirrers() |
| 964 | else: |
| 965 | self.ota_chamber.set_orientation(testcase_params['orientation']) |
| 966 | |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 967 | def compile_ota_rssi_test_params(self, testcase_params): |
| 968 | """Function to complete compiling test-specific parameters |
| 969 | |
| 970 | Args: |
| 971 | testcase_params: dict containing test-specific parameters |
| 972 | """ |
| 973 | if "rssi_over_orientation" in self.test_name: |
| 974 | rssi_test_duration = self.testclass_params[ |
| 975 | 'rssi_over_orientation_duration'] |
| 976 | elif "rssi_variation" in self.test_name: |
| 977 | rssi_test_duration = self.testclass_params[ |
| 978 | 'rssi_variation_duration'] |
| 979 | |
| 980 | testcase_params.update( |
| 981 | connected_measurements=int( |
| 982 | rssi_test_duration / |
| 983 | self.testclass_params['polling_frequency']), |
| 984 | scan_measurements=0, |
| 985 | first_measurement_delay=MED_SLEEP, |
| 986 | rssi_atten_range=[ |
| 987 | self.testclass_params['rssi_ota_test_attenuation'] |
| 988 | ]) |
| 989 | testcase_params['band'] = self.access_point.band_lookup_by_channel( |
| 990 | testcase_params['channel']) |
Omar El Ayach | cbf6ba9 | 2019-12-07 11:54:06 -0800 | [diff] [blame] | 991 | testcase_params['test_network'] = self.main_network[ |
| 992 | testcase_params['band']] |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 993 | testcase_params['tracked_bssid'] = [ |
| 994 | self.main_network[testcase_params['band']].get( |
| 995 | 'BSSID', '00:00:00:00') |
| 996 | ] |
| 997 | |
| 998 | testcase_params['traffic_timeout'] = self.get_traffic_timeout( |
| 999 | testcase_params) |
| 1000 | if isinstance(self.iperf_server, ipf.IPerfServerOverAdb): |
| 1001 | testcase_params['iperf_args'] = '-i 1 -t {} -J'.format( |
| 1002 | testcase_params['traffic_timeout']) |
| 1003 | else: |
| 1004 | testcase_params['iperf_args'] = '-i 1 -t {} -J -R'.format( |
| 1005 | testcase_params['traffic_timeout']) |
| 1006 | return testcase_params |
| 1007 | |
| 1008 | def _test_ota_rssi(self, testcase_params): |
| 1009 | testcase_params = self.compile_ota_rssi_test_params(testcase_params) |
| 1010 | |
| 1011 | self.setup_rssi_test(testcase_params) |
| 1012 | rssi_result = self.run_rssi_test(testcase_params) |
| 1013 | rssi_result['postprocessed_results'] = self.post_process_rssi_sweep( |
| 1014 | rssi_result) |
| 1015 | self.testclass_results.append(rssi_result) |
| 1016 | self.plot_rssi_vs_time(rssi_result, |
| 1017 | rssi_result['postprocessed_results'], 1) |
| 1018 | self.plot_rssi_distribution(rssi_result['postprocessed_results']) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 1019 | |
| 1020 | def generate_test_cases(self, test_types, channels, modes, traffic_modes, |
| 1021 | chamber_modes, orientations): |
| 1022 | test_cases = [] |
| 1023 | allowed_configs = { |
| 1024 | 'VHT20': [ |
| 1025 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 149, 153, |
| 1026 | 157, 161 |
| 1027 | ], |
| 1028 | 'VHT40': [36, 44, 149, 157], |
| 1029 | 'VHT80': [36, 149] |
| 1030 | } |
| 1031 | |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 1032 | for (channel, mode, traffic, chamber_mode, orientation, |
| 1033 | test_type) in itertools.product(channels, modes, traffic_modes, |
| 1034 | chamber_modes, orientations, |
| 1035 | test_types): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 1036 | if channel not in allowed_configs[mode]: |
| 1037 | continue |
Omar El Ayach | b755792 | 2019-08-07 17:04:02 -0700 | [diff] [blame] | 1038 | test_name = test_type + '_ch{}_{}_{}_{}deg'.format( |
| 1039 | channel, mode, traffic, orientation) |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 1040 | testcase_params = collections.OrderedDict( |
| 1041 | channel=channel, |
| 1042 | mode=mode, |
| 1043 | active_traffic=(traffic == 'ActiveTraffic'), |
| 1044 | traffic_type=self.user_params['rssi_test_params'] |
| 1045 | ['traffic_type'], |
| 1046 | chamber_mode=chamber_mode, |
| 1047 | orientation=orientation) |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 1048 | test_function = self._test_ota_rssi |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 1049 | setattr(self, test_name, partial(test_function, testcase_params)) |
| 1050 | test_cases.append(test_name) |
| 1051 | return test_cases |
| 1052 | |
| 1053 | |
Omar El Ayach | b755792 | 2019-08-07 17:04:02 -0700 | [diff] [blame] | 1054 | class WifiOtaRssi_Accuracy_Test(WifiOtaRssiTest): |
| 1055 | def __init__(self, controllers): |
| 1056 | super().__init__(controllers) |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 1057 | self.tests = self.generate_test_cases(['test_rssi_vs_atten'], |
| 1058 | [6, 36, 149], ['VHT20'], |
| 1059 | ['ActiveTraffic'], |
| 1060 | ['orientation'], |
| 1061 | list(range(0, 360, 45))) |
Omar El Ayach | b755792 | 2019-08-07 17:04:02 -0700 | [diff] [blame] | 1062 | |
| 1063 | |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 1064 | class WifiOtaRssi_StirrerVariation_Test(WifiOtaRssiTest): |
Omar El Ayach | bbc6a0a | 2019-07-22 10:26:11 -0700 | [diff] [blame] | 1065 | def __init__(self, controllers): |
| 1066 | WifiRssiTest.__init__(self, controllers) |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 1067 | self.tests = self.generate_test_cases(['test_rssi_variation'], |
| 1068 | [6, 36, 149], ['VHT20'], |
| 1069 | ['ActiveTraffic'], |
| 1070 | ['StirrersOn'], [0]) |
Omar El Ayach | a7c3afe | 2019-09-16 15:58:29 -0700 | [diff] [blame] | 1071 | |
Omar El Ayach | 3903e34 | 2019-09-17 19:17:03 -0700 | [diff] [blame] | 1072 | |
Omar El Ayach | a7c3afe | 2019-09-16 15:58:29 -0700 | [diff] [blame] | 1073 | class WifiOtaRssi_TenDegree_Test(WifiOtaRssiTest): |
| 1074 | def __init__(self, controllers): |
| 1075 | WifiRssiTest.__init__(self, controllers) |
Omar El Ayach | 35bf3b8 | 2019-12-06 19:29:19 -0800 | [diff] [blame] | 1076 | self.tests = self.generate_test_cases(['test_rssi_over_orientation'], |
| 1077 | [6, 36, 149], ['VHT20'], |
| 1078 | ['ActiveTraffic'], |
| 1079 | ['orientation'], |
| 1080 | list(range(0, 360, 10))) |