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 17 import json 18 import logging 19 import math 20 import os 21 import time 22 from acts import asserts 23 from acts import base_test 24 from acts import utils 25 from acts.controllers import iperf_server as ipf 26 from acts.test_decorators import test_tracker_info 27 from acts.test_utils.wifi import wifi_power_test_utils as wputils 28 from acts.test_utils.wifi import wifi_retail_ap as retail_ap 29 from acts.test_utils.wifi import wifi_test_utils as wutils 30 31 TEST_TIMEOUT = 10 32 33 34 class WifiThroughputStabilityTest(base_test.BaseTestClass): 35 def __init__(self, controllers): 36 base_test.BaseTestClass.__init__(self, controllers) 37 self.tests = ("test_tput_stability_high_TCP_DL_ch6_VHT20", 38 "test_tput_stability_high_TCP_UL_ch6_VHT20", 39 "test_tput_stability_low_TCP_DL_ch6_VHT20", 40 "test_tput_stability_low_TCP_UL_ch6_VHT20", 41 "test_tput_stability_high_UDP_DL_ch6_VHT20", 42 "test_tput_stability_high_UDP_UL_ch6_VHT20", 43 "test_tput_stability_low_UDP_DL_ch6_VHT20", 44 "test_tput_stability_low_UDP_UL_ch6_VHT20", 45 "test_tput_stability_high_TCP_DL_ch36_VHT20", 46 "test_tput_stability_high_TCP_UL_ch36_VHT20", 47 "test_tput_stability_low_TCP_DL_ch36_VHT20", 48 "test_tput_stability_low_TCP_UL_ch36_VHT20", 49 "test_tput_stability_high_UDP_DL_ch36_VHT20", 50 "test_tput_stability_high_UDP_UL_ch36_VHT20", 51 "test_tput_stability_low_UDP_DL_ch36_VHT20", 52 "test_tput_stability_low_UDP_UL_ch36_VHT20", 53 "test_tput_stability_high_TCP_DL_ch36_VHT40", 54 "test_tput_stability_high_TCP_UL_ch36_VHT40", 55 "test_tput_stability_low_TCP_DL_ch36_VHT40", 56 "test_tput_stability_low_TCP_UL_ch36_VHT40", 57 "test_tput_stability_high_UDP_DL_ch36_VHT40", 58 "test_tput_stability_high_UDP_UL_ch36_VHT40", 59 "test_tput_stability_low_UDP_DL_ch36_VHT40", 60 "test_tput_stability_low_UDP_UL_ch36_VHT40", 61 "test_tput_stability_high_TCP_DL_ch36_VHT80", 62 "test_tput_stability_high_TCP_UL_ch36_VHT80", 63 "test_tput_stability_low_TCP_DL_ch36_VHT80", 64 "test_tput_stability_low_TCP_UL_ch36_VHT80", 65 "test_tput_stability_high_UDP_DL_ch36_VHT80", 66 "test_tput_stability_high_UDP_UL_ch36_VHT80", 67 "test_tput_stability_low_UDP_DL_ch36_VHT80", 68 "test_tput_stability_low_UDP_UL_ch36_VHT80", 69 "test_tput_stability_high_TCP_DL_ch149_VHT20", 70 "test_tput_stability_high_TCP_UL_ch149_VHT20", 71 "test_tput_stability_low_TCP_DL_ch149_VHT20", 72 "test_tput_stability_low_TCP_UL_ch149_VHT20", 73 "test_tput_stability_high_UDP_DL_ch149_VHT20", 74 "test_tput_stability_high_UDP_UL_ch149_VHT20", 75 "test_tput_stability_low_UDP_DL_ch149_VHT20", 76 "test_tput_stability_low_UDP_UL_ch149_VHT20", 77 "test_tput_stability_high_TCP_DL_ch149_VHT40", 78 "test_tput_stability_high_TCP_UL_ch149_VHT40", 79 "test_tput_stability_low_TCP_DL_ch149_VHT40", 80 "test_tput_stability_low_TCP_UL_ch149_VHT40", 81 "test_tput_stability_high_UDP_DL_ch149_VHT40", 82 "test_tput_stability_high_UDP_UL_ch149_VHT40", 83 "test_tput_stability_low_UDP_DL_ch149_VHT40", 84 "test_tput_stability_low_UDP_UL_ch149_VHT40", 85 "test_tput_stability_high_TCP_DL_ch149_VHT80", 86 "test_tput_stability_high_TCP_UL_ch149_VHT80", 87 "test_tput_stability_low_TCP_DL_ch149_VHT80", 88 "test_tput_stability_low_TCP_UL_ch149_VHT80", 89 "test_tput_stability_high_UDP_DL_ch149_VHT80", 90 "test_tput_stability_high_UDP_UL_ch149_VHT80", 91 "test_tput_stability_low_UDP_DL_ch149_VHT80", 92 "test_tput_stability_low_UDP_UL_ch149_VHT80") 93 94 def setup_class(self): 95 self.dut = self.android_devices[0] 96 req_params = [ 97 "throughput_stability_test_params", "testbed_params", 98 "main_network" 99 ] 100 opt_params = ["RetailAccessPoints"] 101 self.unpack_userparams(req_params, opt_params) 102 self.test_params = self.throughput_stability_test_params 103 self.num_atten = self.attenuators[0].instrument.num_atten 104 self.iperf_server = self.iperf_servers[0] 105 self.access_points = retail_ap.create(self.RetailAccessPoints) 106 self.access_point = self.access_points[0] 107 self.log_path = os.path.join(logging.log_path, "test_results") 108 utils.create_dir(self.log_path) 109 self.log.info("Access Point Configuration: {}".format( 110 self.access_point.ap_settings)) 111 if not hasattr(self, "golden_files_list"): 112 self.golden_files_list = [ 113 os.path.join(self.testbed_params["golden_results_path"], 114 file) for file in os.listdir( 115 self.testbed_params["golden_results_path"]) 116 ] 117 118 def teardown_test(self): 119 self.iperf_server.stop() 120 121 def pass_fail_check(self, test_result_dict): 122 """Check the test result and decide if it passed or failed. 123 124 Checks the throughput stability test's PASS/FAIL criteria based on 125 minimum instantaneous throughput, and standard deviation. 126 127 Args: 128 test_result_dict: dict containing attenuation, throughput and other 129 meta data 130 """ 131 #TODO(@oelayach): Check throughput vs RvR golden file 132 min_throughput_check = ( 133 (test_result_dict["iperf_results"]["min_throughput"] / 134 test_result_dict["iperf_results"]["avg_throughput"]) * 135 100) > self.test_params["min_throughput_threshold"] 136 std_deviation_check = ( 137 (test_result_dict["iperf_results"]["std_deviation"] / 138 test_result_dict["iperf_results"]["avg_throughput"]) * 139 100) < self.test_params["std_deviation_threshold"] 140 141 if min_throughput_check and std_deviation_check: 142 asserts.explicit_pass( 143 "Test Passed. Throughput at {}dB attenuation is unstable. " 144 "Average throughput is {} Mbps with a standard deviation of " 145 "{} Mbps and dips down to {} Mbps.".format( 146 self.atten_level, 147 test_result_dict["iperf_results"]["avg_throughput"], 148 test_result_dict["iperf_results"]["std_deviation"], 149 test_result_dict["iperf_results"]["min_throughput"])) 150 asserts.fail( 151 "Test Failed. Throughput at {}dB attenuation is unstable. " 152 "Average throughput is {} Mbps with a standard deviation of " 153 "{} Mbps and dips down to {} Mbps.".format( 154 self.atten_level, 155 test_result_dict["iperf_results"]["avg_throughput"], 156 test_result_dict["iperf_results"]["std_deviation"], 157 test_result_dict["iperf_results"]["min_throughput"])) 158 159 def post_process_results(self, test_result): 160 """Extracts results and saves plots and JSON formatted results. 161 162 Args: 163 test_result: dict containing attenuation, iPerfResult object and 164 other meta data 165 Returns: 166 test_result_dict: dict containing post-processed results including 167 avg throughput, other metrics, and other meta data 168 """ 169 # Save output as text file 170 test_name = self.current_test_name 171 results_file_path = "{}/{}.txt".format(self.log_path, 172 self.current_test_name) 173 test_result_dict = {} 174 test_result_dict["ap_settings"] = test_result["ap_settings"].copy() 175 test_result_dict["attenuation"] = self.atten_level 176 instantaneous_rates_Mbps = [ 177 rate * 8 * (1.024**2) for rate in test_result["iperf_result"] 178 .instantaneous_rates[self.test_params["iperf_ignored_interval"]:-1] 179 ] 180 test_result_dict["iperf_results"] = { 181 "instantaneous_rates": 182 instantaneous_rates_Mbps, 183 "avg_throughput": 184 math.fsum(instantaneous_rates_Mbps) / 185 len(instantaneous_rates_Mbps), 186 "std_deviation": 187 test_result["iperf_result"].get_std_deviation( 188 self.test_params["iperf_ignored_interval"]) * 8, 189 "min_throughput": 190 min(instantaneous_rates_Mbps) 191 } 192 with open(results_file_path, 'w') as results_file: 193 json.dump(test_result_dict, results_file) 194 # Plot and save 195 legends = self.current_test_name 196 x_label = 'Time (s)' 197 y_label = 'Throughput (Mbps)' 198 time_data = list(range(0, len(instantaneous_rates_Mbps))) 199 data_sets = [[time_data], [instantaneous_rates_Mbps]] 200 fig_property = { 201 "title": test_name, 202 "x_label": x_label, 203 "y_label": y_label, 204 "linewidth": 3, 205 "markersize": 10 206 } 207 output_file_path = "{}/{}.html".format(self.log_path, test_name) 208 wputils.bokeh_plot( 209 data_sets, 210 legends, 211 fig_property, 212 shaded_region=None, 213 output_file_path=output_file_path) 214 return test_result_dict 215 216 def throughput_stability_test_func(self, channel, mode): 217 """Main function to test throughput stability. 218 219 The function sets up the AP in the correct channel and mode 220 configuration and runs an iperf test to measure throughput. 221 222 Args: 223 channel: Specifies AP's channel 224 mode: Specifies AP's bandwidth/mode (11g, VHT20, VHT40, VHT80) 225 Returns: 226 test_result: dict containing test result and meta data 227 """ 228 #Initialize RvR test parameters 229 test_result = {} 230 # Configure AP 231 band = self.access_point.band_lookup_by_channel(channel) 232 self.access_point.set_channel(band, channel) 233 self.access_point.set_bandwidth(band, mode) 234 self.log.info("Access Point Configuration: {}".format( 235 self.access_point.ap_settings)) 236 # Set attenuator to test level 237 self.log.info("Setting attenuation to {} dB".format(self.atten_level)) 238 [ 239 self.attenuators[i].set_atten(self.atten_level) 240 for i in range(self.num_atten) 241 ] 242 # Connect DUT to Network 243 self.main_network[band]["channel"] = channel 244 wutils.reset_wifi(self.dut) 245 wutils.wifi_connect(self.dut, self.main_network[band], num_of_tries=5) 246 time.sleep(5) 247 # Run test and log result 248 # Start iperf session 249 self.log.info("Starting iperf test.") 250 self.iperf_server.start(tag=str(self.atten_level)) 251 try: 252 client_output = "" 253 client_status, client_output = self.dut.run_iperf_client( 254 self.testbed_params["iperf_server_address"], 255 self.iperf_args, 256 timeout=self.test_params["iperf_duration"] + TEST_TIMEOUT) 257 except: 258 self.log.warning("TimeoutError: Iperf measurement timed out.") 259 client_output_path = os.path.join(self.iperf_server.log_path, 260 "iperf_client_output_{}".format( 261 self.current_test_name)) 262 with open(client_output_path, 'w') as out_file: 263 out_file.write("\n".join(client_output)) 264 self.iperf_server.stop() 265 # Set attenuator to 0 dB 266 [self.attenuators[i].set_atten(0) for i in range(self.num_atten)] 267 # Parse and log result 268 if self.use_client_output: 269 iperf_file = client_output_path 270 else: 271 iperf_file = self.iperf_server.log_files[-1] 272 try: 273 iperf_result = ipf.IPerfResult(iperf_file) 274 except: 275 self.log.warning("ValueError: Cannot get iperf result.") 276 iperf_result = None 277 test_result["ap_settings"] = self.access_point.ap_settings.copy() 278 test_result["attenuation"] = self.atten_level 279 test_result["iperf_result"] = iperf_result 280 return test_result 281 282 def get_target_atten_tput(self): 283 """Function gets attenuation used for test 284 285 The function fetches the attenuation at which the test should be 286 performed, and the expected target average throughput. 287 288 Returns: 289 test_target: dict containing target test attenuation and expected 290 throughput 291 """ 292 # Fetch the golden RvR results 293 test_name = self.current_test_name 294 rvr_golden_file_name = "test_rvr_" + "_".join(test_name.split("_")[4:]) 295 golden_path = [ 296 file_name for file_name in self.golden_files_list 297 if rvr_golden_file_name in file_name 298 ] 299 with open(golden_path[0], 'r') as golden_file: 300 golden_results = json.load(golden_file) 301 test_target = {} 302 rssi_high_low = test_name.split("_")[3] 303 if rssi_high_low == "low": 304 # Get 0 Mbps attenuation and backoff by low_rssi_backoff_from_range 305 atten_idx = golden_results["throughput_receive"].index(0) 306 max_atten = golden_results["attenuation"][atten_idx] 307 test_target[ 308 "target_attenuation"] = max_atten - self.test_params["low_rssi_backoff_from_range"] 309 tput_idx = golden_results["attenuation"].index( 310 test_target["target_attenuation"]) 311 test_target["target_throughput"] = golden_results[ 312 "throughput_receive"][tput_idx] 313 if rssi_high_low == "high": 314 # Test at lowest attenuation point 315 test_target["target_attenuation"] = golden_results["attenuation"][ 316 0] 317 test_target["target_throughput"] = golden_results[ 318 "throughput_receive"][0] 319 return test_target 320 321 def _test_throughput_stability(self): 322 """ Function that gets called for each test case 323 324 The function gets called in each test case. The function customizes 325 the test based on the test name of the test that called it 326 """ 327 test_params = self.current_test_name.split("_") 328 channel = int(test_params[6][2:]) 329 mode = test_params[7] 330 test_target = self.get_target_atten_tput() 331 self.atten_level = test_target["target_attenuation"] 332 self.iperf_args = '-i 1 -t {} -J'.format( 333 self.test_params["iperf_duration"]) 334 if test_params[4] == "UDP": 335 self.iperf_args = self.iperf_args + "-u -b {}".format( 336 self.test_params["UDP_rates"][mode]) 337 if test_params[5] == "DL": 338 self.iperf_args = self.iperf_args + ' -R' 339 self.use_client_output = True 340 else: 341 self.use_client_output = False 342 test_result = self.throughput_stability_test_func(channel, mode) 343 test_result_postprocessed = self.post_process_results(test_result) 344 self.pass_fail_check(test_result_postprocessed) 345 346 #Test cases 347 @test_tracker_info(uuid='cf6e1c5a-a54e-4efc-a5db-90e02029fe10') 348 def test_tput_stability_high_TCP_DL_ch6_VHT20(self): 349 self._test_throughput_stability() 350 351 @test_tracker_info(uuid='86f8d2ed-a35e-49fd-983a-7af528e94426') 352 def test_tput_stability_high_TCP_UL_ch6_VHT20(self): 353 self._test_throughput_stability() 354 355 @test_tracker_info(uuid='71f615c0-9de8-4070-ba40-43b59278722e') 356 def test_tput_stability_low_TCP_DL_ch6_VHT20(self): 357 self._test_throughput_stability() 358 359 @test_tracker_info(uuid='ad4774d7-4b2c-49f5-8407-3aa72eb43537') 360 def test_tput_stability_low_TCP_UL_ch6_VHT20(self): 361 self._test_throughput_stability() 362 363 @test_tracker_info(uuid='586e1745-a97e-4b6c-af3a-00566aded442') 364 def test_tput_stability_high_UDP_DL_ch6_VHT20(self): 365 self._test_throughput_stability() 366 367 @test_tracker_info(uuid='66af3329-f40f-46fb-a156-69b9047711ec') 368 def test_tput_stability_high_UDP_UL_ch6_VHT20(self): 369 self._test_throughput_stability() 370 371 @test_tracker_info(uuid='bfebc69d-6636-4f95-b709-9d31040ab8cc') 372 def test_tput_stability_low_UDP_DL_ch6_VHT20(self): 373 self._test_throughput_stability() 374 375 @test_tracker_info(uuid='f7cc0211-a18e-4502-a713-e4f88b446776') 376 def test_tput_stability_low_UDP_UL_ch6_VHT20(self): 377 self._test_throughput_stability() 378 379 @test_tracker_info(uuid='594f0359-600c-4b5f-9b96-90e5aa0f2ffb') 380 def test_tput_stability_high_TCP_DL_ch36_VHT20(self): 381 self._test_throughput_stability() 382 383 @test_tracker_info(uuid='fd0a2604-2b69-40c5-906f-c3da45c062e8') 384 def test_tput_stability_high_TCP_UL_ch36_VHT20(self): 385 self._test_throughput_stability() 386 387 @test_tracker_info(uuid='4ead8dc9-6beb-4ce0-8490-66cdd343d355') 388 def test_tput_stability_low_TCP_DL_ch36_VHT20(self): 389 self._test_throughput_stability() 390 391 @test_tracker_info(uuid='2657454c-5a12-4d50-859a-2adb56910920') 392 def test_tput_stability_low_TCP_UL_ch36_VHT20(self): 393 self._test_throughput_stability() 394 395 @test_tracker_info(uuid='4a446a64-a1ab-441a-bfec-5e3fd509c43b') 396 def test_tput_stability_high_UDP_DL_ch36_VHT20(self): 397 self._test_throughput_stability() 398 399 @test_tracker_info(uuid='e4f07efe-71cb-4891-898d-127bd74ca8a7') 400 def test_tput_stability_high_UDP_UL_ch36_VHT20(self): 401 self._test_throughput_stability() 402 403 @test_tracker_info(uuid='aa0270cb-d18b-4048-a3d8-e09eb01ac417') 404 def test_tput_stability_low_UDP_DL_ch36_VHT20(self): 405 self._test_throughput_stability() 406 407 @test_tracker_info(uuid='40b18d99-40b9-4592-a624-a63bee9d55f4') 408 def test_tput_stability_low_UDP_UL_ch36_VHT20(self): 409 self._test_throughput_stability() 410 411 @test_tracker_info(uuid='ce9a9d88-6d39-4a19-a5d6-5296ed480afa') 412 def test_tput_stability_high_TCP_DL_ch36_VHT40(self): 413 self._test_throughput_stability() 414 415 @test_tracker_info(uuid='23a5f845-0871-481a-898d-e0d6aceed4d4') 416 def test_tput_stability_high_TCP_UL_ch36_VHT40(self): 417 self._test_throughput_stability() 418 419 @test_tracker_info(uuid='6e12ee9e-8f27-46e4-8645-9e7a2cdc354f') 420 def test_tput_stability_low_TCP_DL_ch36_VHT40(self): 421 self._test_throughput_stability() 422 423 @test_tracker_info(uuid='2325dd69-17b2-49ce-ac02-dfaa839e638e') 424 def test_tput_stability_low_TCP_UL_ch36_VHT40(self): 425 self._test_throughput_stability() 426 427 @test_tracker_info(uuid='28ae4bcb-2e50-4d74-9b77-4a5e199bc7a4') 428 def test_tput_stability_high_UDP_DL_ch36_VHT40(self): 429 self._test_throughput_stability() 430 431 @test_tracker_info(uuid='a8c3b5bf-ccb8-435b-8861-3b21ed5072fa') 432 def test_tput_stability_high_UDP_UL_ch36_VHT40(self): 433 self._test_throughput_stability() 434 435 @test_tracker_info(uuid='8a15662a-ed78-4a0d-8271-15927963a2c0') 436 def test_tput_stability_low_UDP_DL_ch36_VHT40(self): 437 self._test_throughput_stability() 438 439 @test_tracker_info(uuid='005a84de-689d-4b40-9912-66c137872312') 440 def test_tput_stability_low_UDP_UL_ch36_VHT40(self): 441 self._test_throughput_stability() 442 443 @test_tracker_info(uuid='b1506bec-f3dd-4d93-87b1-3e9a7172a904') 444 def test_tput_stability_high_TCP_DL_ch36_VHT80(self): 445 self._test_throughput_stability() 446 447 @test_tracker_info(uuid='bdebd1df-3e7c-40fc-ad28-1b817b9cb228') 448 def test_tput_stability_high_TCP_UL_ch36_VHT80(self): 449 self._test_throughput_stability() 450 451 @test_tracker_info(uuid='08c7bb18-681f-4a93-90c8-bc0df7169211') 452 def test_tput_stability_low_TCP_DL_ch36_VHT80(self): 453 self._test_throughput_stability() 454 455 @test_tracker_info(uuid='2ddbb7b-496b-4fce-8697-f90409b6e441') 456 def test_tput_stability_low_TCP_UL_ch36_VHT80(self): 457 self._test_throughput_stability() 458 459 @test_tracker_info(uuid='db41ce61-1d8f-4fe8-a904-77f8dcc50ba3') 460 def test_tput_stability_high_UDP_DL_ch36_VHT80(self): 461 self._test_throughput_stability() 462 463 @test_tracker_info(uuid='cd537cb0-8936-41f4-a0fb-1c8b4f38fb62') 464 def test_tput_stability_high_UDP_UL_ch36_VHT80(self): 465 self._test_throughput_stability() 466 467 @test_tracker_info(uuid='4a0209df-42b2-4143-8321-4023355bd663') 468 def test_tput_stability_low_UDP_DL_ch36_VHT80(self): 469 self._test_throughput_stability() 470 471 @test_tracker_info(uuid='64304510-bd5f-4497-9b18-0d4b1a8eb026') 472 def test_tput_stability_low_UDP_UL_ch36_VHT80(self): 473 self._test_throughput_stability() 474 475 @test_tracker_info(uuid='d121fc54-2f1f-4722-8adb-17cb89fba3e6') 476 def test_tput_stability_high_TCP_DL_ch149_VHT20(self): 477 self._test_throughput_stability() 478 479 @test_tracker_info(uuid='cdfca524-7387-4a08-a256-4696b76aa90f') 480 def test_tput_stability_high_TCP_UL_ch149_VHT20(self): 481 self._test_throughput_stability() 482 483 @test_tracker_info(uuid='99280d2d-0096-4862-b27c-85aa46dcfb79') 484 def test_tput_stability_low_TCP_DL_ch149_VHT20(self): 485 self._test_throughput_stability() 486 487 @test_tracker_info(uuid='c09a0f67-0383-4d6a-ac52-f4afd830971c') 488 def test_tput_stability_low_TCP_UL_ch149_VHT20(self): 489 self._test_throughput_stability() 490 491 @test_tracker_info(uuid='7d6dbd39-1dea-4770-a2e0-d9fb9f32904d') 492 def test_tput_stability_high_UDP_DL_ch149_VHT20(self): 493 self._test_throughput_stability() 494 495 @test_tracker_info(uuid='f7e0574e-29b7-429e-9f47-e5cecc0e2bec') 496 def test_tput_stability_high_UDP_UL_ch149_VHT20(self): 497 self._test_throughput_stability() 498 499 @test_tracker_info(uuid='31bd4b12-1be5-46b3-8f86-914e739b0082') 500 def test_tput_stability_low_UDP_DL_ch149_VHT20(self): 501 self._test_throughput_stability() 502 503 @test_tracker_info(uuid='dc88a5bb-646d-407c-aabe-f8d533f4fbc1') 504 def test_tput_stability_low_UDP_UL_ch149_VHT20(self): 505 self._test_throughput_stability() 506 507 @test_tracker_info(uuid='9a101716-7774-451c-b0a3-4ac993143841') 508 def test_tput_stability_high_TCP_DL_ch149_VHT40(self): 509 self._test_throughput_stability() 510 511 @test_tracker_info(uuid='3533c6ba-1510-4559-9f76-5aef8d996c71') 512 def test_tput_stability_high_TCP_UL_ch149_VHT40(self): 513 self._test_throughput_stability() 514 515 @test_tracker_info(uuid='e83840a0-805e-408a-87b6-4bfce5306b1d') 516 def test_tput_stability_low_TCP_DL_ch149_VHT40(self): 517 self._test_throughput_stability() 518 519 @test_tracker_info(uuid='c55edf2b-b0ce-469e-bd98-e407a9f14126') 520 def test_tput_stability_low_TCP_UL_ch149_VHT40(self): 521 self._test_throughput_stability() 522 523 @test_tracker_info(uuid='0704b56e-e986-4bb8-84dc-e7a1ef94ed91') 524 def test_tput_stability_high_UDP_DL_ch149_VHT40(self): 525 self._test_throughput_stability() 526 527 @test_tracker_info(uuid='71a979c0-a7d9-45bc-a57a-d71f5629b191') 528 def test_tput_stability_high_UDP_UL_ch149_VHT40(self): 529 self._test_throughput_stability() 530 531 @test_tracker_info(uuid='b4d0f554-f49b-46a8-897b-fc0d3af2e4b5') 532 def test_tput_stability_low_UDP_DL_ch149_VHT40(self): 533 self._test_throughput_stability() 534 535 @test_tracker_info(uuid='5bcb5950-db7f-435f-8fcb-55620c757f4f') 536 def test_tput_stability_low_UDP_UL_ch149_VHT40(self): 537 self._test_throughput_stability() 538 539 @test_tracker_info(uuid='d05bcae5-48ac-410b-8083-a05951839121') 540 def test_tput_stability_high_TCP_DL_ch149_VHT80(self): 541 self._test_throughput_stability() 542 543 @test_tracker_info(uuid='038f0c6d-527b-4094-af41-d8732b7594ed') 544 def test_tput_stability_high_TCP_UL_ch149_VHT80(self): 545 self._test_throughput_stability() 546 547 @test_tracker_info(uuid='7ebd1735-b495-4385-a1d4-e2a2991ecbcd') 548 def test_tput_stability_low_TCP_DL_ch149_VHT80(self): 549 self._test_throughput_stability() 550 551 @test_tracker_info(uuid='f9e2679a-0c2e-42ac-a7b2-81aae8680a8f') 552 def test_tput_stability_low_TCP_UL_ch149_VHT80(self): 553 self._test_throughput_stability() 554 555 @test_tracker_info(uuid='39e90233-404e-48ed-a71d-aa55b8047641') 556 def test_tput_stability_high_UDP_DL_ch149_VHT80(self): 557 self._test_throughput_stability() 558 559 @test_tracker_info(uuid='e68a8b64-9278-4c75-8f98-37b415287d9c') 560 def test_tput_stability_high_UDP_UL_ch149_VHT80(self): 561 self._test_throughput_stability() 562 563 @test_tracker_info(uuid='f710c4f8-5ae3-4e70-8d1f-dfa3fb7222a8') 564 def test_tput_stability_low_UDP_DL_ch149_VHT80(self): 565 self._test_throughput_stability() 566 567 @test_tracker_info(uuid='ce8c125c-73d1-4aab-8d09-0b67d8598d20') 568 def test_tput_stability_low_UDP_UL_ch149_VHT80(self): 569 self._test_throughput_stability() 570