Home | History | Annotate | Download | only in wifi
      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