1#!/usr/bin/env python3.4 2# 3# Copyright 2017 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import collections 18import json 19import logging 20import math 21import os 22import time 23from acts import asserts 24from acts import base_test 25from acts import utils 26from acts.controllers import iperf_server as ipf 27from acts.metrics.loggers.blackbox import BlackboxMetricLogger 28from acts.test_decorators import test_tracker_info 29from acts.test_utils.wifi import wifi_performance_test_utils as wputils 30from acts.test_utils.wifi import wifi_retail_ap as retail_ap 31from acts.test_utils.wifi import wifi_test_utils as wutils 32 33 34class WifiRvrTest(base_test.BaseTestClass): 35 """Class to test WiFi rate versus range. 36 37 This class implements WiFi rate versus range tests on single AP single STA 38 links. The class setups up the AP in the desired configurations, configures 39 and connects the phone to the AP, and runs iperf throughput test while 40 sweeping attenuation. For an example config file to run this test class see 41 example_connectivity_performance_ap_sta.json. 42 """ 43 44 TEST_TIMEOUT = 5 45 SHORT_SLEEP = 1 46 RSSI_POLL_INTERVAL = 1 47 MAX_CONSECUTIVE_ZEROS = 3 48 49 def __init__(self, controllers): 50 base_test.BaseTestClass.__init__(self, controllers) 51 self.failure_count_metric = BlackboxMetricLogger.for_test_case( 52 metric_name='failure_count') 53 54 def setup_class(self): 55 """Initializes common test hardware and parameters. 56 57 This function initializes hardwares and compiles parameters that are 58 common to all tests in this class. 59 """ 60 self.client_dut = self.android_devices[-1] 61 req_params = [ 62 "RetailAccessPoints", "rvr_test_params", "testbed_params" 63 ] 64 opt_params = ["main_network", "golden_files_list"] 65 self.unpack_userparams(req_params, opt_params) 66 self.testclass_params = self.rvr_test_params 67 self.num_atten = self.attenuators[0].instrument.num_atten 68 self.iperf_server = self.iperf_servers[0] 69 self.iperf_client = self.iperf_clients[0] 70 self.access_points = retail_ap.create(self.RetailAccessPoints) 71 self.access_point = self.access_points[0] 72 self.log.info("Access Point Configuration: {}".format( 73 self.access_point.ap_settings)) 74 self.log_path = os.path.join(logging.log_path, "results") 75 utils.create_dir(self.log_path) 76 if not hasattr(self, "golden_files_list"): 77 self.golden_files_list = [ 78 os.path.join(self.testbed_params["golden_results_path"], 79 file) for file in os.listdir( 80 self.testbed_params["golden_results_path"]) 81 ] 82 self.testclass_results = [] 83 84 # Turn WiFi ON 85 for dev in self.android_devices: 86 wutils.wifi_toggle_state(dev, True) 87 88 def teardown_test(self): 89 self.iperf_server.stop() 90 91 def teardown_class(self): 92 # Turn WiFi OFF 93 for dev in self.android_devices: 94 wutils.wifi_toggle_state(dev, False) 95 self.process_testclass_results() 96 97 def process_testclass_results(self): 98 """Saves plot with all test results to enable comparison.""" 99 # Plot and save all results 100 plot_data = collections.OrderedDict() 101 plots = [] 102 for result in self.testclass_results: 103 testcase_params = self.parse_test_params(result["test_name"]) 104 plot_id = (testcase_params["channel"], testcase_params["mode"]) 105 if plot_id not in plot_data: 106 plot_data[plot_id] = {"x_data": [], "y_data": [], "legend": []} 107 total_attenuation = [ 108 att + result["fixed_attenuation"] 109 for att in result["attenuation"] 110 ] 111 plot_data[plot_id]["x_data"].append(total_attenuation) 112 plot_data[plot_id]["y_data"].append(result["throughput_receive"]) 113 plot_data[plot_id]["legend"].append(result["test_name"]) 114 for plot_id, plot_data in plot_data.items(): 115 data_set = [plot_data["x_data"], plot_data["y_data"]] 116 fig_property = { 117 "title": "Channel {} - {}".format(plot_id[0], plot_id[1]), 118 "x_label": 'Attenuation (dB)', 119 "y_label": 'Throughput (Mbps)', 120 "linewidth": 3, 121 "markersize": 10 122 } 123 plots.append( 124 wputils.bokeh_plot( 125 data_set, 126 plot_data["legend"], 127 fig_property, 128 shaded_region=None)) 129 output_file_path = os.path.join(self.log_path, 'results.html') 130 wputils.save_bokeh_plots(plots, output_file_path) 131 132 def pass_fail_check(self, rvr_result): 133 """Check the test result and decide if it passed or failed. 134 135 Checks the RvR test result and compares to a throughput limites for 136 the same configuration. The pass/fail tolerances are provided in the 137 config file. 138 139 Args: 140 rvr_result: dict containing attenuation, throughput and other meta 141 data 142 """ 143 try: 144 throughput_limits = self.compute_throughput_limits(rvr_result) 145 except: 146 asserts.fail("Test failed: Golden file not found") 147 148 failure_count = 0 149 for idx, current_throughput in enumerate( 150 rvr_result["throughput_receive"]): 151 current_att = rvr_result["attenuation"][idx] + rvr_result["fixed_attenuation"] 152 if (current_throughput < throughput_limits["lower_limit"][idx] 153 or current_throughput > 154 throughput_limits["upper_limit"][idx]): 155 failure_count = failure_count + 1 156 self.log.info( 157 "Throughput at {}dB attenuation is beyond limits. " 158 "Throughput is {} Mbps. Expected within [{}, {}] Mbps.". 159 format(current_att, current_throughput, 160 throughput_limits["lower_limit"][idx], 161 throughput_limits["upper_limit"][idx])) 162 self.failure_count_metric.metric_value = failure_count 163 if failure_count >= self.testclass_params["failure_count_tolerance"]: 164 asserts.fail("Test failed. Found {} points outside limits.".format( 165 failure_count)) 166 asserts.explicit_pass( 167 "Test passed. Found {} points outside throughput limits.".format( 168 failure_count)) 169 170 def compute_throughput_limits(self, rvr_result): 171 """Compute throughput limits for current test. 172 173 Checks the RvR test result and compares to a throughput limites for 174 the same configuration. The pass/fail tolerances are provided in the 175 config file. 176 177 Args: 178 rvr_result: dict containing attenuation, throughput and other meta 179 data 180 Returns: 181 throughput_limits: dict containing attenuation and throughput limit data 182 """ 183 test_name = self.current_test_name 184 golden_path = next(file_name for file_name in self.golden_files_list 185 if test_name in file_name) 186 with open(golden_path, 'r') as golden_file: 187 golden_results = json.load(golden_file) 188 golden_attenuation = [ 189 att + golden_results["fixed_attenuation"] 190 for att in golden_results["attenuation"] 191 ] 192 attenuation = [] 193 lower_limit = [] 194 upper_limit = [] 195 for idx, current_throughput in enumerate( 196 rvr_result["throughput_receive"]): 197 current_att = rvr_result["attenuation"][idx] + rvr_result["fixed_attenuation"] 198 att_distances = [ 199 abs(current_att - golden_att) 200 for golden_att in golden_attenuation 201 ] 202 sorted_distances = sorted( 203 enumerate(att_distances), key=lambda x: x[1]) 204 closest_indeces = [dist[0] for dist in sorted_distances[0:3]] 205 closest_throughputs = [ 206 golden_results["throughput_receive"][index] 207 for index in closest_indeces 208 ] 209 closest_throughputs.sort() 210 211 attenuation.append(current_att) 212 lower_limit.append( 213 max(closest_throughputs[0] - 214 max(self.testclass_params["abs_tolerance"], 215 closest_throughputs[0] * 216 self.testclass_params["pct_tolerance"] / 100), 0)) 217 upper_limit.append(closest_throughputs[-1] + max( 218 self.testclass_params["abs_tolerance"], closest_throughputs[-1] 219 * self.testclass_params["pct_tolerance"] / 100)) 220 throughput_limits = { 221 "attenuation": attenuation, 222 "lower_limit": lower_limit, 223 "upper_limit": upper_limit 224 } 225 return throughput_limits 226 227 def process_test_results(self, rvr_result): 228 """Saves plots and JSON formatted results. 229 230 Args: 231 rvr_result: dict containing attenuation, throughput and other meta 232 data 233 """ 234 # Save output as text file 235 test_name = self.current_test_name 236 results_file_path = "{}/{}.json".format(self.log_path, 237 self.current_test_name) 238 with open(results_file_path, 'w') as results_file: 239 json.dump(rvr_result, results_file, indent=4) 240 # Plot and save 241 legends = [self.current_test_name] 242 x_label = 'Attenuation (dB)' 243 y_label = 'Throughput (Mbps)' 244 total_attenuation = [ 245 att + rvr_result["fixed_attenuation"] 246 for att in rvr_result["attenuation"] 247 ] 248 data_sets = [[total_attenuation], [rvr_result["throughput_receive"]]] 249 fig_property = { 250 "title": test_name, 251 "x_label": x_label, 252 "y_label": y_label, 253 "linewidth": 3, 254 "markersize": 10 255 } 256 try: 257 golden_path = next(file_name 258 for file_name in self.golden_files_list 259 if test_name in file_name) 260 with open(golden_path, 'r') as golden_file: 261 golden_results = json.load(golden_file) 262 legends.insert(0, "Golden Results") 263 golden_attenuation = [ 264 att + golden_results["fixed_attenuation"] 265 for att in golden_results["attenuation"] 266 ] 267 data_sets[0].insert(0, golden_attenuation) 268 data_sets[1].insert(0, golden_results["throughput_receive"]) 269 throughput_limits = self.compute_throughput_limits(rvr_result) 270 shaded_region = { 271 "x_vector": throughput_limits["attenuation"], 272 "lower_limit": throughput_limits["lower_limit"], 273 "upper_limit": throughput_limits["upper_limit"] 274 } 275 except: 276 shaded_region = None 277 self.log.warning("ValueError: Golden file not found") 278 output_file_path = "{}/{}.html".format(self.log_path, test_name) 279 wputils.bokeh_plot(data_sets, legends, fig_property, shaded_region, 280 output_file_path) 281 282 def run_rvr_test(self, testcase_params): 283 """Test function to run RvR. 284 285 The function runs an RvR test in the current device/AP configuration. 286 Function is called from another wrapper function that sets up the 287 testbed for the RvR test 288 289 Args: 290 testcase_params: dict containing test-specific parameters 291 Returns: 292 rvr_result: dict containing rvr_results and meta data 293 """ 294 self.log.info("Start running RvR") 295 zero_counter = 0 296 throughput = [] 297 rssi = [] 298 for atten in testcase_params["atten_range"]: 299 # Set Attenuation 300 for attenuator in self.attenuators: 301 attenuator.set_atten(atten, strict=False) 302 # Start iperf session 303 self.iperf_server.start(tag=str(atten)) 304 rssi_future = wputils.get_connected_rssi_nb( 305 self.client_dut, testcase_params["iperf_duration"] - 1, 1, 1) 306 client_output_path = self.iperf_client.start( 307 testcase_params["iperf_server_address"], 308 testcase_params["iperf_args"], str(atten), 309 testcase_params["iperf_duration"] + self.TEST_TIMEOUT) 310 server_output_path = self.iperf_server.stop() 311 current_rssi = rssi_future.result()["signal_poll_rssi"]["mean"] 312 rssi.append(current_rssi) 313 # Parse and log result 314 if testcase_params["use_client_output"]: 315 iperf_file = client_output_path 316 else: 317 iperf_file = server_output_path 318 try: 319 iperf_result = ipf.IPerfResult(iperf_file) 320 curr_throughput = (math.fsum(iperf_result.instantaneous_rates[ 321 self.testclass_params["iperf_ignored_interval"]:-1]) / len( 322 iperf_result.instantaneous_rates[self.testclass_params[ 323 "iperf_ignored_interval"]:-1])) * 8 * (1.024**2) 324 except: 325 self.log.warning( 326 "ValueError: Cannot get iperf result. Setting to 0") 327 curr_throughput = 0 328 throughput.append(curr_throughput) 329 self.log.info( 330 "Throughput at {0:.2f} dB is {1:.2f} Mbps. RSSI = {2:.2f}". 331 format(atten, curr_throughput, current_rssi)) 332 if curr_throughput == 0: 333 zero_counter = zero_counter + 1 334 else: 335 zero_counter = 0 336 if zero_counter == self.MAX_CONSECUTIVE_ZEROS: 337 self.log.info( 338 "Throughput stable at 0 Mbps. Stopping test now.") 339 throughput.extend( 340 [0] * 341 (len(testcase_params["atten_range"]) - len(throughput))) 342 break 343 for attenuator in self.attenuators: 344 attenuator.set_atten(0, strict=False) 345 # Compile test result and meta data 346 rvr_result = collections.OrderedDict() 347 rvr_result["test_name"] = self.current_test_name 348 rvr_result["ap_settings"] = self.access_point.ap_settings.copy() 349 rvr_result["fixed_attenuation"] = self.testbed_params[ 350 "fixed_attenuation"][str(testcase_params["channel"])] 351 rvr_result["attenuation"] = list(testcase_params["atten_range"]) 352 rvr_result["rssi"] = rssi 353 rvr_result["throughput_receive"] = throughput 354 return rvr_result 355 356 def setup_ap(self, testcase_params): 357 """Sets up the access point in the configuration required by the test. 358 359 Args: 360 testcase_params: dict containing AP and other test params 361 """ 362 band = self.access_point.band_lookup_by_channel( 363 testcase_params["channel"]) 364 if "2G" in band: 365 frequency = wutils.WifiEnums.channel_2G_to_freq[testcase_params[ 366 "channel"]] 367 else: 368 frequency = wutils.WifiEnums.channel_5G_to_freq[testcase_params[ 369 "channel"]] 370 if frequency in wutils.WifiEnums.DFS_5G_FREQUENCIES: 371 self.access_point.set_region(self.testbed_params["DFS_region"]) 372 else: 373 self.access_point.set_region(self.testbed_params["default_region"]) 374 self.access_point.set_channel(band, testcase_params["channel"]) 375 self.access_point.set_bandwidth(band, testcase_params["mode"]) 376 self.log.info("Access Point Configuration: {}".format( 377 self.access_point.ap_settings)) 378 379 def setup_dut(self, testcase_params): 380 """Sets up the DUT in the configuration required by the test. 381 382 Args: 383 testcase_params: dict containing AP and other test params 384 """ 385 band = self.access_point.band_lookup_by_channel( 386 testcase_params["channel"]) 387 wutils.reset_wifi(self.client_dut) 388 self.client_dut.droid.wifiSetCountryCode( 389 self.testclass_params["country_code"]) 390 self.main_network[band]["channel"] = testcase_params["channel"] 391 wutils.wifi_connect( 392 self.client_dut, 393 self.main_network[band], 394 num_of_tries=5, 395 check_connectivity=False) 396 self.dut_ip = self.client_dut.droid.connectivityGetIPv4Addresses( 397 'wlan0')[0] 398 399 def setup_rvr_test(self, testcase_params): 400 """Function that gets devices ready for the test. 401 402 Args: 403 testcase_params: dict containing test-specific parameters 404 """ 405 # Configure AP 406 self.setup_ap(testcase_params) 407 # Set attenuator to 0 dB 408 for attenuator in self.attenuators: 409 attenuator.set_atten(0, strict=False) 410 # Reset, configure, and connect DUT 411 self.setup_dut(testcase_params) 412 # Get iperf_server address 413 if isinstance(self.iperf_server, ipf.IPerfServerOverAdb): 414 testcase_params["iperf_server_address"] = self.dut_ip 415 else: 416 testcase_params["iperf_server_address"] = self.testbed_params[ 417 "iperf_server_address"] 418 419 def parse_test_params(self, test_name): 420 """Function that generates test params based on the test name.""" 421 test_name_params = test_name.split("_") 422 testcase_params = collections.OrderedDict() 423 testcase_params["channel"] = int(test_name_params[4][2:]) 424 testcase_params["mode"] = test_name_params[5] 425 num_atten_steps = int((self.testclass_params["atten_stop"] - 426 self.testclass_params["atten_start"]) / 427 self.testclass_params["atten_step"]) 428 testcase_params["atten_range"] = [ 429 self.testclass_params["atten_start"] + 430 x * self.testclass_params["atten_step"] 431 for x in range(0, num_atten_steps) 432 ] 433 testcase_params["iperf_args"] = '-i 1 -t {} -J '.format( 434 self.testclass_params["iperf_duration"]) 435 if test_name_params[2] == "UDP": 436 testcase_params[ 437 "iperf_args"] = testcase_params["iperf_args"] + "-u -b {}".format( 438 self.testclass_params["UDP_rates"][testcase_params["mode"]]) 439 if (test_name_params[3] == "DL" 440 and not isinstance(self.iperf_server, ipf.IPerfServerOverAdb) 441 ) or (test_name_params[3] == "UL" 442 and isinstance(self.iperf_server, ipf.IPerfServerOverAdb)): 443 testcase_params[ 444 "iperf_args"] = testcase_params["iperf_args"] + ' -R' 445 testcase_params["use_client_output"] = True 446 else: 447 testcase_params["use_client_output"] = False 448 return testcase_params 449 450 def _test_rvr(self): 451 """ Function that gets called for each test case 452 453 The function gets called in each rvr test case. The function customizes 454 the rvr test based on the test name of the test that called it 455 """ 456 # Compile test parameters from config and test name 457 testcase_params = self.parse_test_params(self.current_test_name) 458 testcase_params.update(self.testclass_params) 459 460 # Prepare devices and run test 461 self.setup_rvr_test(testcase_params) 462 rvr_result = self.run_rvr_test(testcase_params) 463 464 # Post-process results 465 self.testclass_results.append(rvr_result) 466 self.process_test_results(rvr_result) 467 self.pass_fail_check(rvr_result) 468 469 #Test cases 470 @test_tracker_info(uuid='e7586217-3739-44a4-a87b-d790208b04b9') 471 def test_rvr_TCP_DL_ch1_VHT20(self): 472 self._test_rvr() 473 474 @test_tracker_info(uuid='06b3e979-255c-482f-b570-d347fba048b6') 475 def test_rvr_TCP_UL_ch1_VHT20(self): 476 self._test_rvr() 477 478 @test_tracker_info(uuid='e912db87-dbfb-4e86-b91c-827e6c53e840') 479 def test_rvr_TCP_DL_ch6_VHT20(self): 480 self._test_rvr() 481 482 @test_tracker_info(uuid='ddafbe78-bd19-48fc-b653-69b23b1ab8dd') 483 def test_rvr_TCP_UL_ch6_VHT20(self): 484 self._test_rvr() 485 486 @test_tracker_info(uuid='6fcb7fd8-4438-4913-a1c8-ea35050c79dd') 487 def test_rvr_TCP_DL_ch11_VHT20(self): 488 self._test_rvr() 489 490 @test_tracker_info(uuid='a165884e-c928-46d9-b459-f550ceb0074f') 491 def test_rvr_TCP_UL_ch11_VHT20(self): 492 self._test_rvr() 493 494 @test_tracker_info(uuid='a48ee2b4-3fb9-41fd-b292-0051bfc3b0cc') 495 def test_rvr_TCP_DL_ch36_VHT20(self): 496 self._test_rvr() 497 498 @test_tracker_info(uuid='68f94e6b-b4ff-4839-904b-ec45cc661b89') 499 def test_rvr_TCP_UL_ch36_VHT20(self): 500 self._test_rvr() 501 502 @test_tracker_info(uuid='a8b00098-5c07-44bb-ae17-5d0489786c62') 503 def test_rvr_TCP_DL_ch36_VHT40(self): 504 self._test_rvr() 505 506 @test_tracker_info(uuid='ecfb4284-1794-4508-b35e-be56fa4c9035') 507 def test_rvr_TCP_UL_ch36_VHT40(self): 508 self._test_rvr() 509 510 @test_tracker_info(uuid='6190c1a6-08f2-4a27-a65f-7321801f2cd6') 511 def test_rvr_TCP_DL_ch36_VHT80(self): 512 self._test_rvr() 513 514 @test_tracker_info(uuid='ae12712d-0ac3-4317-827d-544acfa4910c') 515 def test_rvr_TCP_UL_ch36_VHT80(self): 516 self._test_rvr() 517 518 @test_tracker_info(uuid='c8f8d107-5176-484b-a0d9-7a63aef8677e') 519 def test_rvr_TCP_DL_ch40_VHT20(self): 520 self._test_rvr() 521 522 @test_tracker_info(uuid='6fa823c9-54bf-450d-b2c3-31a46fc73386') 523 def test_rvr_TCP_UL_ch40_VHT20(self): 524 self._test_rvr() 525 526 @test_tracker_info(uuid='aa6cd955-eaef-4552-87a4-c4a0df59e184') 527 def test_rvr_TCP_DL_ch44_VHT20(self): 528 self._test_rvr() 529 530 @test_tracker_info(uuid='14ad4b1c-7c8f-4650-be74-daf813021ad3') 531 def test_rvr_TCP_UL_ch44_VHT20(self): 532 self._test_rvr() 533 534 @test_tracker_info(uuid='a5fdb54c-60e2-4cc6-a9ec-1a17e7827823') 535 def test_rvr_TCP_DL_ch44_VHT40(self): 536 self._test_rvr() 537 538 @test_tracker_info(uuid='112113f1-7f50-4112-81b5-d9a4fdf153e7') 539 def test_rvr_TCP_UL_ch44_VHT40(self): 540 self._test_rvr() 541 542 @test_tracker_info(uuid='cda3886c-8776-4077-acfd-cfe128772e2f') 543 def test_rvr_TCP_DL_ch48_VHT20(self): 544 self._test_rvr() 545 546 @test_tracker_info(uuid='2e5ad031-6404-4e71-b3b3-8a3bb2c85d4f') 547 def test_rvr_TCP_UL_ch48_VHT20(self): 548 self._test_rvr() 549 550 @test_tracker_info(uuid='c2e199ce-d23f-4a24-b146-74e762085620') 551 def test_rvr_TCP_DL_ch52_VHT20(self): 552 self._test_rvr() 553 554 @test_tracker_info(uuid='5c5943e8-9d91-4270-a5ab-e7018807c64e') 555 def test_rvr_TCP_UL_ch52_VHT20(self): 556 self._test_rvr() 557 558 @test_tracker_info(uuid='b52afe89-182f-4bad-8879-cbf7001d28ef') 559 def test_rvr_TCP_DL_ch56_VHT20(self): 560 self._test_rvr() 561 562 @test_tracker_info(uuid='f8526241-3b96-463a-9082-a749a8650d5f') 563 def test_rvr_TCP_UL_ch56_VHT20(self): 564 self._test_rvr() 565 566 @test_tracker_info(uuid='c3042d7e-7468-4ab8-aec3-9b3088ba3e4c') 567 def test_rvr_TCP_DL_ch60_VHT20(self): 568 self._test_rvr() 569 570 @test_tracker_info(uuid='80426542-b035-4fb3-9010-e997f95d4964') 571 def test_rvr_TCP_UL_ch60_VHT20(self): 572 self._test_rvr() 573 574 @test_tracker_info(uuid='aa0e7117-390c-4265-adf2-0990f65f8b0b') 575 def test_rvr_TCP_DL_ch64_VHT20(self): 576 self._test_rvr() 577 578 @test_tracker_info(uuid='b2fdda85-256b-4368-8e8b-39274062264e') 579 def test_rvr_TCP_UL_ch64_VHT20(self): 580 self._test_rvr() 581 582 @test_tracker_info(uuid='48b6590f-1553-4170-83a5-40d3976e9e77') 583 def test_rvr_TCP_DL_ch100_VHT20(self): 584 self._test_rvr() 585 586 @test_tracker_info(uuid='2d0525fe-57ce-49d3-826d-4ebedd2ca6d6') 587 def test_rvr_TCP_UL_ch100_VHT20(self): 588 self._test_rvr() 589 590 @test_tracker_info(uuid='52da922d-6c2f-4afa-aca3-c19438ae3217') 591 def test_rvr_TCP_DL_ch100_VHT40(self): 592 self._test_rvr() 593 594 @test_tracker_info(uuid='2c7e7106-88c8-47ba-ac28-362475abec41') 595 def test_rvr_TCP_UL_ch100_VHT40(self): 596 self._test_rvr() 597 598 @test_tracker_info(uuid='fd4a7118-e9fe-4931-b32c-f69efd3e6493') 599 def test_rvr_TCP_DL_ch100_VHT80(self): 600 self._test_rvr() 601 602 @test_tracker_info(uuid='146502b2-9cab-4bbe-8a5c-7ec625edc2ef') 603 def test_rvr_TCP_UL_ch100_VHT80(self): 604 self._test_rvr() 605 606 @test_tracker_info(uuid='a5e185d6-b523-4016-bc8a-2a32cdc67ae0') 607 def test_rvr_TCP_DL_ch104_VHT20(self): 608 self._test_rvr() 609 610 @test_tracker_info(uuid='886aed91-0fdc-432d-b47e-ebfa85ac27ad') 611 def test_rvr_TCP_UL_ch104_VHT20(self): 612 self._test_rvr() 613 614 @test_tracker_info(uuid='fda3de6e-3183-401b-b98c-1b076da139e1') 615 def test_rvr_TCP_DL_ch108_VHT20(self): 616 self._test_rvr() 617 618 @test_tracker_info(uuid='29cc30f5-bbc8-4b64-9789-a56154907af5') 619 def test_rvr_TCP_UL_ch108_VHT20(self): 620 self._test_rvr() 621 622 @test_tracker_info(uuid='5c52ccac-8c38-46fa-a7b3-d714b6a814ad') 623 def test_rvr_TCP_DL_ch112_VHT20(self): 624 self._test_rvr() 625 626 @test_tracker_info(uuid='cc1c2a0b-71a3-4343-b7ff-489527c839d2') 627 def test_rvr_TCP_UL_ch112_VHT20(self): 628 self._test_rvr() 629 630 @test_tracker_info(uuid='11c6ccc3-e347-44ce-9a79-6c90e9dfd0a0') 631 def test_rvr_TCP_DL_ch116_VHT20(self): 632 self._test_rvr() 633 634 @test_tracker_info(uuid='29f0fce1-005d-4ad7-97d7-6b43cbdff01b') 635 def test_rvr_TCP_UL_ch116_VHT20(self): 636 self._test_rvr() 637 638 @test_tracker_info(uuid='112302b1-8261-479a-b397-916b08fbbdd2') 639 def test_rvr_TCP_DL_ch132_VHT20(self): 640 self._test_rvr() 641 642 @test_tracker_info(uuid='3bb0efb8-ddfc-4a0b-b7cf-6d6af1dbb9f4') 643 def test_rvr_TCP_UL_ch132_VHT20(self): 644 self._test_rvr() 645 646 @test_tracker_info(uuid='11a4638f-d872-4730-82eb-71d9c64e0e16') 647 def test_rvr_TCP_DL_ch136_VHT20(self): 648 self._test_rvr() 649 650 @test_tracker_info(uuid='4d797c24-3bbe-43a6-ac9e-291db1aa732a') 651 def test_rvr_TCP_UL_ch136_VHT20(self): 652 self._test_rvr() 653 654 @test_tracker_info(uuid='5d433b44-0395-43cb-b85a-be138390b18b') 655 def test_rvr_TCP_DL_ch140_VHT20(self): 656 self._test_rvr() 657 658 @test_tracker_info(uuid='47061772-21b1-4330-bd4f-daec21afa0c8') 659 def test_rvr_TCP_UL_ch140_VHT20(self): 660 self._test_rvr() 661 662 @test_tracker_info(uuid='24aa1e7a-3978-4803-877f-3ac5812ab0ae') 663 def test_rvr_TCP_DL_ch149_VHT20(self): 664 self._test_rvr() 665 666 @test_tracker_info(uuid='59f0443f-822d-4347-9c52-310f0b812500') 667 def test_rvr_TCP_UL_ch149_VHT20(self): 668 self._test_rvr() 669 670 @test_tracker_info(uuid='3b1524b3-af15-41f1-8fca-9ee9b687d59a') 671 def test_rvr_TCP_DL_ch149_VHT40(self): 672 self._test_rvr() 673 674 @test_tracker_info(uuid='36670787-3bfb-4e8b-8881-e88eb608ed46') 675 def test_rvr_TCP_UL_ch149_VHT40(self): 676 self._test_rvr() 677 678 @test_tracker_info(uuid='8350cddd-7c62-4fad-bdae-a8267d321aa3') 679 def test_rvr_TCP_DL_ch149_VHT80(self): 680 self._test_rvr() 681 682 @test_tracker_info(uuid='7432fccb-526e-44d4-b0f4-2c343ca53188') 683 def test_rvr_TCP_UL_ch149_VHT80(self): 684 self._test_rvr() 685 686 @test_tracker_info(uuid='037eec49-2bae-49e3-949e-5af2885dc84b') 687 def test_rvr_TCP_DL_ch153_VHT20(self): 688 self._test_rvr() 689 690 @test_tracker_info(uuid='04d5d873-7d5a-4590-bff3-093edeb92380') 691 def test_rvr_TCP_UL_ch153_VHT20(self): 692 self._test_rvr() 693 694 @test_tracker_info(uuid='4ff83f6e-b130-4a88-8ced-04a09c6af666') 695 def test_rvr_TCP_DL_ch157_VHT20(self): 696 self._test_rvr() 697 698 @test_tracker_info(uuid='c3436402-977e-40a5-a7eb-e2c886379d43') 699 def test_rvr_TCP_UL_ch157_VHT20(self): 700 self._test_rvr() 701 702 @test_tracker_info(uuid='797a218b-1a8e-4233-835b-61b3f057f480') 703 def test_rvr_TCP_DL_ch157_VHT40(self): 704 self._test_rvr() 705 706 @test_tracker_info(uuid='38d3e825-6e2c-4931-b0fd-aa19c5d1ef40') 707 def test_rvr_TCP_UL_ch157_VHT40(self): 708 self._test_rvr() 709 710 @test_tracker_info(uuid='993e98c5-0647-4ed6-b62e-ab386ada37af') 711 def test_rvr_TCP_DL_ch161_VHT20(self): 712 self._test_rvr() 713 714 @test_tracker_info(uuid='3bf9c844-749a-47d8-ac46-89249bd92c4a') 715 def test_rvr_TCP_UL_ch161_VHT20(self): 716 self._test_rvr() 717 718 @test_tracker_info(uuid='05614f92-38fa-4289-bcff-d4b4a2a2ad5b') 719 def test_rvr_UDP_DL_ch6_VHT20(self): 720 self._test_rvr() 721 722 @test_tracker_info(uuid='577632e9-fb2f-4a2b-b3c3-affee8264008') 723 def test_rvr_UDP_UL_ch6_VHT20(self): 724 self._test_rvr() 725 726 @test_tracker_info(uuid='6f3fcc28-5f0c-49e6-8810-69c5873ecafa') 727 def test_rvr_UDP_DL_ch36_VHT20(self): 728 self._test_rvr() 729 730 @test_tracker_info(uuid='8e518aaa-e61f-4c1d-b12f-1bbd550ec3e5') 731 def test_rvr_UDP_UL_ch36_VHT20(self): 732 self._test_rvr() 733 734 @test_tracker_info(uuid='fd68ff32-c789-4a86-9924-2f5aeb3c9651') 735 def test_rvr_UDP_DL_ch149_VHT20(self): 736 self._test_rvr() 737 738 @test_tracker_info(uuid='29d03492-fc0b-42d0-aa15-c0c838ba50c1') 739 def test_rvr_UDP_UL_ch149_VHT20(self): 740 self._test_rvr() 741 742 @test_tracker_info(uuid='044c414c-ac5e-4e28-9b56-a602e0cc9724') 743 def test_rvr_UDP_DL_ch36_VHT40(self): 744 self._test_rvr() 745 746 @test_tracker_info(uuid='9cd16689-5053-4ffa-813c-d901384a105c') 747 def test_rvr_UDP_UL_ch36_VHT40(self): 748 self._test_rvr() 749 750 @test_tracker_info(uuid='4e4b1e73-30ce-4005-9c34-8c0280bdb293') 751 def test_rvr_UDP_DL_ch36_VHT80(self): 752 self._test_rvr() 753 754 @test_tracker_info(uuid='780166a1-1847-45c2-b509-71612c82309d') 755 def test_rvr_UDP_UL_ch36_VHT80(self): 756 self._test_rvr() 757 758 @test_tracker_info(uuid='05abdb89-9744-479e-8443-cb8b9427f5e3') 759 def test_rvr_UDP_DL_ch149_VHT40(self): 760 self._test_rvr() 761 762 @test_tracker_info(uuid='a321590a-4cbc-4044-9c2b-24e90f444213') 763 def test_rvr_UDP_UL_ch149_VHT40(self): 764 self._test_rvr() 765 766 @test_tracker_info(uuid='041fd613-24d9-4606-bca3-0ae0d8436b5e') 767 def test_rvr_UDP_DL_ch149_VHT80(self): 768 self._test_rvr() 769 770 @test_tracker_info(uuid='69aab23d-1408-4cdd-9f57-2520a1e9cea8') 771 def test_rvr_UDP_UL_ch149_VHT80(self): 772 self._test_rvr() 773 774 775# Classes defining test suites 776class WifiRvr_2GHz_Test(WifiRvrTest): 777 def __init__(self, controllers): 778 super().__init__(controllers) 779 self.tests = ("test_rvr_TCP_DL_ch1_VHT20", "test_rvr_TCP_UL_ch1_VHT20", 780 "test_rvr_TCP_DL_ch6_VHT20", "test_rvr_TCP_UL_ch6_VHT20", 781 "test_rvr_TCP_DL_ch11_VHT20", 782 "test_rvr_TCP_UL_ch11_VHT20") 783 784 785class WifiRvr_UNII1_Test(WifiRvrTest): 786 def __init__(self, controllers): 787 super().__init__(controllers) 788 self.tests = ( 789 "test_rvr_TCP_DL_ch36_VHT20", "test_rvr_TCP_UL_ch36_VHT20", 790 "test_rvr_TCP_DL_ch36_VHT40", "test_rvr_TCP_UL_ch36_VHT40", 791 "test_rvr_TCP_DL_ch36_VHT80", "test_rvr_TCP_UL_ch36_VHT80", 792 "test_rvr_TCP_DL_ch40_VHT20", "test_rvr_TCP_UL_ch40_VHT20", 793 "test_rvr_TCP_DL_ch44_VHT20", "test_rvr_TCP_UL_ch44_VHT20", 794 "test_rvr_TCP_DL_ch44_VHT40", "test_rvr_TCP_UL_ch44_VHT40", 795 "test_rvr_TCP_DL_ch48_VHT20", "test_rvr_TCP_UL_ch48_VHT20") 796 797 798class WifiRvr_UNII3_Test(WifiRvrTest): 799 def __init__(self, controllers): 800 super().__init__(controllers) 801 self.tests = ( 802 "test_rvr_TCP_DL_ch149_VHT20", "test_rvr_TCP_UL_ch149_VHT20", 803 "test_rvr_TCP_DL_ch149_VHT40", "test_rvr_TCP_UL_ch149_VHT40", 804 "test_rvr_TCP_DL_ch149_VHT80", "test_rvr_TCP_UL_ch149_VHT80", 805 "test_rvr_TCP_DL_ch153_VHT20", "test_rvr_TCP_UL_ch153_VHT20", 806 "test_rvr_TCP_DL_ch157_VHT20", "test_rvr_TCP_UL_ch157_VHT20", 807 "test_rvr_TCP_DL_ch157_VHT40", "test_rvr_TCP_UL_ch157_VHT40", 808 "test_rvr_TCP_DL_ch161_VHT20", "test_rvr_TCP_UL_ch161_VHT20") 809 810 811class WifiRvr_SampleDFS_Test(WifiRvrTest): 812 def __init__(self, controllers): 813 super().__init__(controllers) 814 self.tests = ( 815 "test_rvr_TCP_DL_ch64_VHT20", "test_rvr_TCP_UL_ch64_VHT20", 816 "test_rvr_TCP_DL_ch100_VHT20", "test_rvr_TCP_UL_ch100_VHT20", 817 "test_rvr_TCP_DL_ch100_VHT40", "test_rvr_TCP_UL_ch100_VHT40", 818 "test_rvr_TCP_DL_ch100_VHT80", "test_rvr_TCP_UL_ch100_VHT80", 819 "test_rvr_TCP_DL_ch116_VHT20", "test_rvr_TCP_UL_ch116_VHT20", 820 "test_rvr_TCP_DL_ch132_VHT20", "test_rvr_TCP_UL_ch132_VHT20", 821 "test_rvr_TCP_DL_ch140_VHT20", "test_rvr_TCP_UL_ch140_VHT20") 822 823 824class WifiRvr_SampleUDP_Test(WifiRvrTest): 825 def __init__(self, controllers): 826 super().__init__(controllers) 827 self.tests = ( 828 "test_rvr_UDP_DL_ch6_VHT20", "test_rvr_UDP_UL_ch6_VHT20", 829 "test_rvr_UDP_DL_ch36_VHT20", "test_rvr_UDP_UL_ch36_VHT20", 830 "test_rvr_UDP_DL_ch36_VHT40", "test_rvr_UDP_UL_ch36_VHT40", 831 "test_rvr_UDP_DL_ch36_VHT80", "test_rvr_UDP_UL_ch36_VHT80", 832 "test_rvr_UDP_DL_ch149_VHT20", "test_rvr_UDP_UL_ch149_VHT20", 833 "test_rvr_UDP_DL_ch149_VHT40", "test_rvr_UDP_UL_ch149_VHT40", 834 "test_rvr_UDP_DL_ch149_VHT80", "test_rvr_UDP_UL_ch149_VHT80") 835 836 837class WifiRvr_TCP_All_Test(WifiRvrTest): 838 def __init__(self, controllers): 839 super().__init__(controllers) 840 self.tests = ( 841 "test_rvr_TCP_DL_ch1_VHT20", "test_rvr_TCP_UL_ch1_VHT20", 842 "test_rvr_TCP_DL_ch6_VHT20", "test_rvr_TCP_UL_ch6_VHT20", 843 "test_rvr_TCP_DL_ch11_VHT20", "test_rvr_TCP_UL_ch11_VHT20", 844 "test_rvr_TCP_DL_ch36_VHT20", "test_rvr_TCP_UL_ch36_VHT20", 845 "test_rvr_TCP_DL_ch36_VHT40", "test_rvr_TCP_UL_ch36_VHT40", 846 "test_rvr_TCP_DL_ch36_VHT80", "test_rvr_TCP_UL_ch36_VHT80", 847 "test_rvr_TCP_DL_ch40_VHT20", "test_rvr_TCP_UL_ch40_VHT20", 848 "test_rvr_TCP_DL_ch44_VHT20", "test_rvr_TCP_UL_ch44_VHT20", 849 "test_rvr_TCP_DL_ch44_VHT40", "test_rvr_TCP_UL_ch44_VHT40", 850 "test_rvr_TCP_DL_ch48_VHT20", "test_rvr_TCP_UL_ch48_VHT20", 851 "test_rvr_TCP_DL_ch149_VHT20", "test_rvr_TCP_UL_ch149_VHT20", 852 "test_rvr_TCP_DL_ch149_VHT40", "test_rvr_TCP_UL_ch149_VHT40", 853 "test_rvr_TCP_DL_ch149_VHT80", "test_rvr_TCP_UL_ch149_VHT80", 854 "test_rvr_TCP_DL_ch153_VHT20", "test_rvr_TCP_UL_ch153_VHT20", 855 "test_rvr_TCP_DL_ch157_VHT20", "test_rvr_TCP_UL_ch157_VHT20", 856 "test_rvr_TCP_DL_ch157_VHT40", "test_rvr_TCP_UL_ch157_VHT40", 857 "test_rvr_TCP_DL_ch161_VHT20", "test_rvr_TCP_UL_ch161_VHT20") 858 859 860class WifiRvr_TCP_Downlink_Test(WifiRvrTest): 861 def __init__(self, controllers): 862 super().__init__(controllers) 863 self.tests = ( 864 "test_rvr_TCP_DL_ch1_VHT20", "test_rvr_TCP_DL_ch6_VHT20", 865 "test_rvr_TCP_DL_ch11_VHT20", "test_rvr_TCP_DL_ch36_VHT20", 866 "test_rvr_TCP_DL_ch36_VHT40", "test_rvr_TCP_DL_ch36_VHT80", 867 "test_rvr_TCP_DL_ch40_VHT20", "test_rvr_TCP_DL_ch44_VHT20", 868 "test_rvr_TCP_DL_ch44_VHT40", "test_rvr_TCP_DL_ch48_VHT20", 869 "test_rvr_TCP_DL_ch149_VHT20", "test_rvr_TCP_DL_ch149_VHT40", 870 "test_rvr_TCP_DL_ch149_VHT80", "test_rvr_TCP_DL_ch153_VHT20", 871 "test_rvr_TCP_DL_ch157_VHT20", "test_rvr_TCP_DL_ch157_VHT40", 872 "test_rvr_TCP_DL_ch161_VHT20") 873 874 875class WifiRvr_TCP_Uplink_Test(WifiRvrTest): 876 def __init__(self, controllers): 877 super().__init__(controllers) 878 self.tests = ( 879 "test_rvr_TCP_UL_ch1_VHT20", "test_rvr_TCP_UL_ch6_VHT20", 880 "test_rvr_TCP_UL_ch11_VHT20", "test_rvr_TCP_UL_ch36_VHT20", 881 "test_rvr_TCP_UL_ch36_VHT40", "test_rvr_TCP_UL_ch36_VHT80", 882 "test_rvr_TCP_UL_ch40_VHT20", "test_rvr_TCP_UL_ch44_VHT20", 883 "test_rvr_TCP_UL_ch44_VHT40", "test_rvr_TCP_UL_ch48_VHT20", 884 "test_rvr_TCP_UL_ch149_VHT20", "test_rvr_TCP_UL_ch149_VHT40", 885 "test_rvr_TCP_UL_ch149_VHT80", "test_rvr_TCP_UL_ch153_VHT20", 886 "test_rvr_TCP_UL_ch157_VHT20", "test_rvr_TCP_UL_ch157_VHT40", 887 "test_rvr_TCP_UL_ch161_VHT20") 888