globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 2 | # |
| 3 | # Copyright (C) 2018 The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| 6 | # use this file except in compliance with the License. You may obtain a copy of |
| 7 | # 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, WITHOUT |
| 13 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 14 | # License for the specific language governing permissions and limitations under |
| 15 | # the License. |
| 16 | |
| 17 | import json |
| 18 | import os |
| 19 | import time |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 20 | from collections import defaultdict |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 21 | |
Sriram Sundararajan | 4f303cf | 2019-03-21 18:32:21 -0700 | [diff] [blame] | 22 | from acts.metrics.loggers.blackbox import BlackboxMetricLogger |
Xianyuan Jia | 63751fb | 2020-11-17 00:07:40 +0000 | [diff] [blame^] | 23 | from acts_contrib.test_utils.bt.bt_test_utils import disable_bluetooth |
| 24 | from acts_contrib.test_utils.coex.audio_test_utils import AudioCaptureResult |
| 25 | from acts_contrib.test_utils.coex.audio_test_utils import get_audio_capture_device |
| 26 | from acts_contrib.test_utils.coex.CoexBaseTest import CoexBaseTest |
| 27 | from acts_contrib.test_utils.coex.coex_test_utils import bokeh_chart_plot |
| 28 | from acts_contrib.test_utils.coex.coex_test_utils import collect_bluetooth_manager_dumpsys_logs |
| 29 | from acts_contrib.test_utils.coex.coex_test_utils import multithread_func |
| 30 | from acts_contrib.test_utils.coex.coex_test_utils import wifi_connection_check |
| 31 | from acts_contrib.test_utils.wifi.wifi_test_utils import wifi_connect |
| 32 | from acts_contrib.test_utils.wifi.wifi_test_utils import wifi_test_device_init |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 33 | from acts.utils import get_current_epoch_time |
| 34 | |
sairam | a70b224 | 2020-01-02 22:19:47 -0800 | [diff] [blame] | 35 | RSSI_POLL_RESULTS = 'Monitoring , Handle: 0x0003, POLL' |
| 36 | RSSI_RESULTS = 'Monitoring , Handle: 0x0003, ' |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 37 | |
| 38 | |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 39 | def get_atten_range(start, stop, step): |
| 40 | """Function to derive attenuation range for tests. |
| 41 | |
| 42 | Args: |
| 43 | start: Start attenuation value. |
| 44 | stop: Stop attenuation value. |
| 45 | step: Step attenuation value. |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 46 | """ |
gobaledge | 9479c54 | 2019-04-04 15:55:02 +0530 | [diff] [blame] | 47 | temp = start |
| 48 | while temp < stop: |
| 49 | yield temp |
| 50 | temp += step |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 51 | |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 52 | |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 53 | class CoexPerformanceBaseTest(CoexBaseTest): |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 54 | """Base test class for performance tests. |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 55 | |
| 56 | Attributes: |
| 57 | rvr : Dict to save attenuation, throughput, fixed_attenuation. |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 58 | a2dp_streaming : Used to denote a2dp test cases. |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 59 | """ |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 60 | |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 61 | def __init__(self, controllers): |
globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 62 | super().__init__(controllers) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 63 | self.a2dp_streaming = False |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 64 | self.rvr = {} |
Sriram Sundararajan | 4f303cf | 2019-03-21 18:32:21 -0700 | [diff] [blame] | 65 | self.bt_range_metric = BlackboxMetricLogger.for_test_case( |
| 66 | metric_name='bt_range') |
| 67 | self.wifi_max_atten_metric = BlackboxMetricLogger.for_test_case( |
| 68 | metric_name='wifi_max_atten') |
| 69 | self.wifi_min_atten_metric = BlackboxMetricLogger.for_test_case( |
| 70 | metric_name='wifi_min_atten') |
| 71 | self.wifi_range_metric = BlackboxMetricLogger.for_test_case( |
| 72 | metric_name='wifi_range_metric') |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 73 | |
| 74 | def setup_class(self): |
sairam | a70b224 | 2020-01-02 22:19:47 -0800 | [diff] [blame] | 75 | req_params = ['test_params', 'Attenuator'] |
| 76 | opt_params = ['audio_params'] |
| 77 | self.unpack_userparams(req_params, opt_params) |
| 78 | if hasattr(self, 'Attenuator'): |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 79 | self.num_atten = self.attenuators[0].instrument.num_atten |
| 80 | else: |
sairam | a70b224 | 2020-01-02 22:19:47 -0800 | [diff] [blame] | 81 | self.log.error('Attenuator should be connected to run tests.') |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 82 | return False |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 83 | for i in range(self.num_atten): |
| 84 | self.attenuators[i].set_atten(0) |
globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 85 | super().setup_class() |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 86 | self.performance_files_list = [] |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 87 | if "performance_result_path" in self.user_params["test_params"]: |
| 88 | self.performance_files_list = [ |
| 89 | os.path.join(self.test_params["performance_result_path"], |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 90 | files) for files in os.listdir( |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 91 | self.test_params["performance_result_path"]) |
| 92 | ] |
gobaledge | 9479c54 | 2019-04-04 15:55:02 +0530 | [diff] [blame] | 93 | self.bt_atten_range = list(get_atten_range( |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 94 | self.test_params["bt_atten_start"], |
| 95 | self.test_params["bt_atten_stop"], |
gobaledge | 9479c54 | 2019-04-04 15:55:02 +0530 | [diff] [blame] | 96 | self.test_params["bt_atten_step"])) |
| 97 | self.wifi_atten_range = list(get_atten_range( |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 98 | self.test_params["attenuation_start"], |
| 99 | self.test_params["attenuation_stop"], |
gobaledge | 9479c54 | 2019-04-04 15:55:02 +0530 | [diff] [blame] | 100 | self.test_params["attenuation_step"])) |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 101 | |
| 102 | def setup_test(self): |
sairam | a70b224 | 2020-01-02 22:19:47 -0800 | [diff] [blame] | 103 | if ('a2dp_streaming' in self.current_test_name and |
| 104 | hasattr(self, 'audio_params')): |
| 105 | self.audio = get_audio_capture_device(self.sec_ad, self.audio_params) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 106 | self.a2dp_streaming = True |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 107 | for i in range(self.num_atten): |
| 108 | self.attenuators[i].set_atten(0) |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 109 | if not wifi_connection_check(self.pri_ad, self.network["SSID"]): |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 110 | wifi_connect(self.pri_ad, self.network, num_of_tries=5) |
globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 111 | super().setup_test() |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 112 | |
| 113 | def teardown_test(self): |
| 114 | self.performance_baseline_check() |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 115 | for i in range(self.num_atten): |
| 116 | self.attenuators[i].set_atten(0) |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 117 | current_atten = int(self.attenuators[i].get_atten()) |
| 118 | self.log.debug( |
| 119 | "Setting attenuation to zero : Current atten {} : {}".format( |
| 120 | self.attenuators[i], current_atten)) |
gobaledge | 9e77fc2 | 2019-02-27 17:08:18 +0530 | [diff] [blame] | 121 | self.a2dp_streaming = False |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 122 | if not disable_bluetooth(self.pri_ad.droid): |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 123 | self.log.info("Failed to disable bluetooth") |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 124 | return False |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 125 | self.destroy_android_and_relay_object() |
global edge | 92de59d | 2018-10-03 15:17:35 +0530 | [diff] [blame] | 126 | self.rvr = {} |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 127 | |
| 128 | def teardown_class(self): |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 129 | self.reset_wifi_and_store_results() |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 130 | |
| 131 | def set_attenuation_and_run_iperf(self, called_func=None): |
| 132 | """Sets attenuation and runs iperf for Attenuation max value. |
| 133 | |
| 134 | Args: |
| 135 | called_func : Function object to run. |
| 136 | |
| 137 | Returns: |
| 138 | True if Pass |
| 139 | False if Fail |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 140 | """ |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 141 | self.attenuators[self.num_atten - 1].set_atten(0) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 142 | self.rvr["bt_attenuation"] = [] |
| 143 | self.rvr["test_name"] = self.current_test_name |
gobaledge | 9e77fc2 | 2019-02-27 17:08:18 +0530 | [diff] [blame] | 144 | self.rvr["bt_gap_analysis"] = {} |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 145 | self.rvr["bt_range"] = [] |
| 146 | status_flag = True |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 147 | for bt_atten in self.bt_atten_range: |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 148 | self.rvr[bt_atten] = {} |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 149 | self.rvr[bt_atten]["fixed_attenuation"] = ( |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 150 | self.test_params["fixed_attenuation"][str( |
| 151 | self.network["channel"])]) |
sairam | 1870b88 | 2019-11-25 10:37:19 -0800 | [diff] [blame] | 152 | self.log.info('Setting bt attenuation to: {} dB'.format(bt_atten)) |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 153 | self.attenuators[self.num_atten - 1].set_atten(bt_atten) |
| 154 | for i in range(self.num_atten - 1): |
| 155 | self.attenuators[i].set_atten(0) |
| 156 | if not wifi_connection_check(self.pri_ad, self.network["SSID"]): |
| 157 | wifi_test_device_init(self.pri_ad) |
| 158 | wifi_connect(self.pri_ad, self.network, num_of_tries=5) |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 159 | adb_rssi_results = self.pri_ad.search_logcat(RSSI_RESULTS) |
| 160 | if adb_rssi_results: |
| 161 | self.log.debug(adb_rssi_results[-1]) |
sairam | 1870b88 | 2019-11-25 10:37:19 -0800 | [diff] [blame] | 162 | self.log.info('Android device: {}'.format( |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 163 | (adb_rssi_results[-1]['log_message']).split(',')[5])) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 164 | (self.rvr[bt_atten]["throughput_received"], |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 165 | self.rvr[bt_atten]["a2dp_packet_drop"], |
| 166 | status_flag) = self.rvr_throughput(bt_atten, called_func) |
Sriram Sundararajan | 4f303cf | 2019-03-21 18:32:21 -0700 | [diff] [blame] | 167 | self.wifi_max_atten_metric.metric_value = max(self.rvr[bt_atten] |
| 168 | ["attenuation"]) |
| 169 | self.wifi_min_atten_metric.metric_value = min(self.rvr[bt_atten] |
| 170 | ["attenuation"]) |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 171 | |
| 172 | if self.rvr[bt_atten]["throughput_received"]: |
| 173 | for i, atten in enumerate(self.rvr[bt_atten]["attenuation"]): |
| 174 | if self.rvr[bt_atten]["throughput_received"][i] < 1.0: |
| 175 | self.wifi_range_metric.metric_value = ( |
| 176 | self.rvr[bt_atten]["attenuation"][i-1]) |
| 177 | break |
| 178 | else: |
| 179 | self.wifi_range_metric.metric_value = max( |
| 180 | self.rvr[bt_atten]["attenuation"]) |
Sriram Sundararajan | 4f303cf | 2019-03-21 18:32:21 -0700 | [diff] [blame] | 181 | else: |
gobaledge | 4471acf | 2019-04-16 16:09:29 +0530 | [diff] [blame] | 182 | self.wifi_range_metric.metric_value = max( |
| 183 | self.rvr[bt_atten]["attenuation"]) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 184 | if self.a2dp_streaming: |
| 185 | if not any(x > 0 for x in self.a2dp_dropped_list): |
global edge | 421efee | 2018-10-31 14:55:16 +0530 | [diff] [blame] | 186 | self.rvr[bt_atten]["a2dp_packet_drop"] = [] |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 187 | if not self.rvr["bt_range"]: |
| 188 | self.rvr["bt_range"].append(0) |
| 189 | return status_flag |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 190 | |
global edge | 421efee | 2018-10-31 14:55:16 +0530 | [diff] [blame] | 191 | def rvr_throughput(self, bt_atten, called_func=None): |
global edge | a50cc63 | 2018-10-10 17:00:32 +0530 | [diff] [blame] | 192 | """Sets attenuation and runs the function passed. |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 193 | |
| 194 | Args: |
global edge | 421efee | 2018-10-31 14:55:16 +0530 | [diff] [blame] | 195 | bt_atten: Bluetooth attenuation. |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 196 | called_func: Functions object to run parallely. |
| 197 | |
| 198 | Returns: |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 199 | Throughput, a2dp_drops and True/False. |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 200 | """ |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 201 | self.iperf_received = [] |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 202 | self.iperf_variables.received = [] |
| 203 | self.a2dp_dropped_list = [] |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 204 | self.rvr["bt_attenuation"].append(bt_atten) |
global edge | 421efee | 2018-10-31 14:55:16 +0530 | [diff] [blame] | 205 | self.rvr[bt_atten]["audio_artifacts"] = {} |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 206 | self.rvr[bt_atten]["attenuation"] = [] |
gobaledge | 9e77fc2 | 2019-02-27 17:08:18 +0530 | [diff] [blame] | 207 | self.rvr["bt_gap_analysis"][bt_atten] = {} |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 208 | for atten in self.wifi_atten_range: |
sairam | b44460f | 2019-11-27 09:17:34 -0800 | [diff] [blame] | 209 | tag = '{}_{}'.format(bt_atten, atten) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 210 | self.rvr[bt_atten]["attenuation"].append( |
| 211 | atten + self.rvr[bt_atten]["fixed_attenuation"]) |
sairam | 1870b88 | 2019-11-25 10:37:19 -0800 | [diff] [blame] | 212 | self.log.info('Setting wifi attenuation to: {} dB'.format(atten)) |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 213 | for i in range(self.num_atten - 1): |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 214 | self.attenuators[i].set_atten(atten) |
| 215 | if not wifi_connection_check(self.pri_ad, self.network["SSID"]): |
gobaledge | 4471acf | 2019-04-16 16:09:29 +0530 | [diff] [blame] | 216 | self.iperf_received.append(0) |
gobaledge | 9479c54 | 2019-04-04 15:55:02 +0530 | [diff] [blame] | 217 | return self.iperf_received, self.a2dp_dropped_list, False |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 218 | time.sleep(5) # Time for attenuation to set. |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 219 | begin_time = get_current_epoch_time() |
sairam | a70b224 | 2020-01-02 22:19:47 -0800 | [diff] [blame] | 220 | if self.a2dp_streaming: |
| 221 | self.audio.start() |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 222 | if called_func: |
| 223 | if not multithread_func(self.log, called_func): |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 224 | self.iperf_received.append(float(str( |
| 225 | self.iperf_variables.received[-1]).strip("Mb/s"))) |
| 226 | return self.iperf_received, self.a2dp_dropped_list, False |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 227 | else: |
| 228 | self.run_iperf_and_get_result() |
sairam | b44460f | 2019-11-27 09:17:34 -0800 | [diff] [blame] | 229 | |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 230 | adb_rssi_poll_results = self.pri_ad.search_logcat( |
| 231 | RSSI_POLL_RESULTS, begin_time) |
| 232 | adb_rssi_results = self.pri_ad.search_logcat( |
| 233 | RSSI_RESULTS, begin_time) |
| 234 | if adb_rssi_results: |
| 235 | self.log.debug(adb_rssi_poll_results) |
| 236 | self.log.debug(adb_rssi_results[-1]) |
sairam | 1870b88 | 2019-11-25 10:37:19 -0800 | [diff] [blame] | 237 | self.log.info('Android device: {}'.format(( |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 238 | adb_rssi_results[-1]['log_message']).split(',')[5])) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 239 | if self.a2dp_streaming: |
sairam | a70b224 | 2020-01-02 22:19:47 -0800 | [diff] [blame] | 240 | self.path = self.audio.stop() |
| 241 | analysis_path = AudioCaptureResult( |
| 242 | self.path).audio_quality_analysis(self.audio_params) |
global edge | 421efee | 2018-10-31 14:55:16 +0530 | [diff] [blame] | 243 | with open(analysis_path) as f: |
| 244 | self.rvr[bt_atten]["audio_artifacts"][atten] = f.readline() |
gobaledge | 9e77fc2 | 2019-02-27 17:08:18 +0530 | [diff] [blame] | 245 | content = json.loads(self.rvr[bt_atten]["audio_artifacts"][atten]) |
| 246 | self.rvr["bt_gap_analysis"][bt_atten][atten] = {} |
| 247 | for idx, data in enumerate(content["quality_result"]): |
| 248 | if data['artifacts']['delay_during_playback']: |
| 249 | self.rvr["bt_gap_analysis"][bt_atten][atten][idx] = ( |
| 250 | data['artifacts']['delay_during_playback']) |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 251 | self.rvr["bt_range"].append(bt_atten) |
gobaledge | 9e77fc2 | 2019-02-27 17:08:18 +0530 | [diff] [blame] | 252 | else: |
| 253 | self.rvr["bt_gap_analysis"][bt_atten][atten][idx] = 0 |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 254 | file_path = collect_bluetooth_manager_dumpsys_logs( |
global edge | 421efee | 2018-10-31 14:55:16 +0530 | [diff] [blame] | 255 | self.pri_ad, self.current_test_name) |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 256 | self.a2dp_dropped_list.append( |
| 257 | self.a2dp_dumpsys.parse(file_path)) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 258 | self.iperf_received.append( |
sairam | b44460f | 2019-11-27 09:17:34 -0800 | [diff] [blame] | 259 | float(str(self.iperf_variables.throughput[-1]).strip("Mb/s"))) |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 260 | for i in range(self.num_atten - 1): |
| 261 | self.attenuators[i].set_atten(0) |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 262 | return self.iperf_received, self.a2dp_dropped_list, True |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 263 | |
| 264 | def performance_baseline_check(self): |
| 265 | """Checks for performance_result_path in config. If present, plots |
| 266 | comparision chart else plot chart for that particular test run. |
| 267 | |
| 268 | Returns: |
| 269 | True if success, False otherwise. |
| 270 | """ |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 271 | if self.rvr: |
globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 272 | with open(self.json_file, 'a') as results_file: |
Globaledge | 68f5f2a | 2019-03-25 17:50:23 +0530 | [diff] [blame] | 273 | json.dump({str(k): v for k, v in self.rvr.items()}, |
Globaledge | ba01cfc | 2019-03-19 17:45:17 +0530 | [diff] [blame] | 274 | results_file, indent=4, sort_keys=True) |
gobaledge | 4471acf | 2019-04-16 16:09:29 +0530 | [diff] [blame] | 275 | self.bt_range_metric.metric_value = self.rvr["bt_range"][0] |
sairam | 1870b88 | 2019-11-25 10:37:19 -0800 | [diff] [blame] | 276 | self.log.info('First occurrence of audio gap in bt ' |
| 277 | 'range: {}'.format(self.bt_range_metric.metric_value)) |
| 278 | self.log.info('Bluetooth min range: ' |
| 279 | '{} dB'.format(min(self.rvr['bt_attenuation']))) |
| 280 | self.log.info('Bluetooth max range: ' |
| 281 | '{} dB'.format(max(self.rvr['bt_attenuation']))) |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 282 | self.plot_graph_for_attenuation() |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 283 | if not self.performance_files_list: |
sairam | 1870b88 | 2019-11-25 10:37:19 -0800 | [diff] [blame] | 284 | self.log.warning('Performance file list is empty. Could not ' |
| 285 | 'calculate throughput limits') |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 286 | return |
globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 287 | self.throughput_pass_fail_check() |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 288 | else: |
globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 289 | self.log.error("Throughput dict empty!") |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 290 | return False |
| 291 | return True |
| 292 | |
globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 293 | def plot_graph_for_attenuation(self): |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 294 | """Plots graph and add as JSON formatted results for attenuation with |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 295 | respect to its iperf values. |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 296 | """ |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 297 | data_sets = defaultdict(dict) |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 298 | legends = defaultdict(list) |
| 299 | |
global edge | 421efee | 2018-10-31 14:55:16 +0530 | [diff] [blame] | 300 | x_label = 'WIFI Attenuation (dB)' |
| 301 | y_label = [] |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 302 | |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 303 | fig_property = { |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 304 | "title": self.current_test_name, |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 305 | "x_label": x_label, |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 306 | "linewidth": 3, |
| 307 | "markersize": 10 |
| 308 | } |
global edge | 421efee | 2018-10-31 14:55:16 +0530 | [diff] [blame] | 309 | |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 310 | for bt_atten in self.rvr["bt_attenuation"]: |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 311 | y_label.insert(0, 'Throughput (Mbps)') |
| 312 | legends[bt_atten].insert( |
global edge | 421efee | 2018-10-31 14:55:16 +0530 | [diff] [blame] | 313 | 0, str("BT Attenuation @ %sdB" % bt_atten)) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 314 | data_sets[bt_atten]["attenuation"] = ( |
| 315 | self.rvr[bt_atten]["attenuation"]) |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 316 | data_sets[bt_atten]["throughput_received"] = ( |
| 317 | self.rvr[bt_atten]["throughput_received"]) |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 318 | |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 319 | if self.a2dp_streaming: |
| 320 | for bt_atten in self.bt_atten_range: |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 321 | legends[bt_atten].insert( |
| 322 | 0, ('Packet drops(in %) @ {}dB'.format(bt_atten))) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 323 | data_sets[bt_atten]["a2dp_attenuation"] = ( |
| 324 | self.rvr[bt_atten]["attenuation"]) |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 325 | data_sets[bt_atten]["a2dp_packet_drops"] = ( |
| 326 | self.rvr[bt_atten]["a2dp_packet_drop"]) |
| 327 | y_label.insert(0, "Packets Dropped") |
| 328 | fig_property["y_label"] = y_label |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 329 | shaded_region = None |
| 330 | |
| 331 | if "performance_result_path" in self.user_params["test_params"]: |
| 332 | shaded_region = self.comparision_results_calculation(data_sets, legends) |
| 333 | |
| 334 | output_file_path = os.path.join(self.pri_ad.log_path, |
| 335 | self.current_test_name, |
global edge | a50cc63 | 2018-10-10 17:00:32 +0530 | [diff] [blame] | 336 | "attenuation_plot.html") |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 337 | bokeh_chart_plot(list(self.rvr["bt_attenuation"]), |
| 338 | data_sets, |
| 339 | legends, |
| 340 | fig_property, |
| 341 | shaded_region=shaded_region, |
| 342 | output_file_path=output_file_path) |
| 343 | |
| 344 | def comparision_results_calculation(self, data_sets, legends): |
| 345 | """Compares rvr results with baseline values by calculating throughput |
| 346 | limits. |
| 347 | |
| 348 | Args: |
| 349 | data_sets: including lists of x_data and lists of y_data. |
| 350 | ex: [[[x_data1], [x_data2]], [[y_data1],[y_data2]]] |
| 351 | legends: list of legend for each curve. |
| 352 | |
| 353 | Returns: |
| 354 | None if test_file is not found, otherwise shaded_region |
| 355 | will be returned. |
| 356 | """ |
| 357 | try: |
| 358 | attenuation_path = next( |
| 359 | file_name for file_name in self.performance_files_list |
| 360 | if self.current_test_name in file_name |
| 361 | ) |
| 362 | except StopIteration: |
| 363 | self.log.warning("Test_file not found. " |
| 364 | "No comparision values to calculate") |
| 365 | return |
| 366 | with open(attenuation_path, 'r') as throughput_file: |
| 367 | throughput_results = json.load(throughput_file) |
| 368 | for bt_atten in self.bt_atten_range: |
| 369 | throughput_received = [] |
| 370 | user_attenuation = [] |
| 371 | legends[bt_atten].insert( |
| 372 | 0, ('Performance Results @ {}dB'.format(bt_atten))) |
| 373 | for att in self.rvr[bt_atten]["attenuation"]: |
| 374 | attenuation = att - self.rvr[bt_atten]["fixed_attenuation"] |
| 375 | throughput_received.append(throughput_results[str(bt_atten)] |
| 376 | ["throughput_received"][attenuation]) |
| 377 | user_attenuation.append(att) |
| 378 | data_sets[bt_atten][ |
| 379 | "user_attenuation"] = user_attenuation |
| 380 | data_sets[bt_atten]["user_throughput"] = throughput_received |
| 381 | throughput_limits = self.get_throughput_limits(attenuation_path) |
| 382 | shaded_region = defaultdict(dict) |
| 383 | for bt_atten in self.bt_atten_range: |
| 384 | shaded_region[bt_atten] = { |
| 385 | "x_vector": throughput_limits[bt_atten]["attenuation"], |
| 386 | "lower_limit": |
| 387 | throughput_limits[bt_atten]["lower_limit"], |
| 388 | "upper_limit": |
| 389 | throughput_limits[bt_atten]["upper_limit"] |
| 390 | } |
| 391 | return shaded_region |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 392 | |
| 393 | def total_attenuation(self, performance_dict): |
| 394 | """Calculates attenuation with adding fixed attenuation. |
| 395 | |
| 396 | Args: |
| 397 | performance_dict: dict containing attenuation and fixed attenuation. |
| 398 | |
| 399 | Returns: |
| 400 | Total attenuation is returned. |
| 401 | """ |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 402 | if "fixed_attenuation" in self.test_params: |
| 403 | total_atten = [ |
| 404 | att + performance_dict["fixed_attenuation"] |
| 405 | for att in performance_dict["attenuation"] |
| 406 | ] |
| 407 | return total_atten |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 408 | |
globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 409 | def throughput_pass_fail_check(self): |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 410 | """Check the test result and decide if it passed or failed |
| 411 | by comparing with throughput limits.The pass/fail tolerances are |
| 412 | provided in the config file. |
| 413 | |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 414 | Returns: |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 415 | None if test_file is not found, True if successful, |
| 416 | False otherwise. |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 417 | """ |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 418 | try: |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 419 | performance_path = next( |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 420 | file_name for file_name in self.performance_files_list |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 421 | if self.current_test_name in file_name |
| 422 | ) |
| 423 | except StopIteration: |
| 424 | self.log.warning("Test_file not found. Couldn't " |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 425 | "calculate throughput limits") |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 426 | return |
| 427 | throughput_limits = self.get_throughput_limits(performance_path) |
| 428 | |
| 429 | failure_count = 0 |
| 430 | for bt_atten in self.bt_atten_range: |
| 431 | for idx, current_throughput in enumerate( |
| 432 | self.rvr[bt_atten]["throughput_received"]): |
| 433 | current_att = self.rvr[bt_atten]["attenuation"][idx] |
| 434 | if (current_throughput < |
| 435 | (throughput_limits[bt_atten]["lower_limit"][idx]) or |
| 436 | current_throughput > |
| 437 | (throughput_limits[bt_atten]["upper_limit"][idx])): |
| 438 | failure_count = failure_count + 1 |
| 439 | self.log.info( |
| 440 | "Throughput at {} dB attenuation is beyond limits. " |
| 441 | "Throughput is {} Mbps. Expected within [{}, {}] Mbps.". |
| 442 | format( |
| 443 | current_att, current_throughput, |
| 444 | throughput_limits[bt_atten]["lower_limit"][idx], |
| 445 | throughput_limits[bt_atten]["upper_limit"][ |
| 446 | idx])) |
| 447 | if failure_count >= self.test_params["failure_count_tolerance"]: |
| 448 | self.log.error( |
| 449 | "Test failed. Found {} points outside throughput limits.". |
| 450 | format(failure_count)) |
| 451 | return False |
| 452 | self.log.info( |
| 453 | "Test passed. Found {} points outside throughput limits.". |
| 454 | format(failure_count)) |
| 455 | return True |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 456 | |
globaledge | 32decca | 2018-05-14 18:00:38 +0530 | [diff] [blame] | 457 | def get_throughput_limits(self, performance_path): |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 458 | """Compute throughput limits for current test. |
| 459 | |
| 460 | Checks the RvR test result and compares to a throughput limits for |
| 461 | the same configuration. The pass/fail tolerances are provided in the |
| 462 | config file. |
| 463 | |
| 464 | Args: |
| 465 | performance_path: path to baseline file used to generate limits |
globaledge | c16ad34 | 2018-03-19 17:53:16 +0530 | [diff] [blame] | 466 | |
| 467 | Returns: |
| 468 | throughput_limits: dict containing attenuation and throughput |
| 469 | limit data |
| 470 | """ |
| 471 | with open(performance_path, 'r') as performance_file: |
| 472 | performance_results = json.load(performance_file) |
gobaledge | e61f522 | 2019-02-07 16:54:29 +0530 | [diff] [blame] | 473 | throughput_limits = defaultdict(dict) |
| 474 | for bt_atten in self.bt_atten_range: |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 475 | performance_attenuation = (self.total_attenuation( |
| 476 | performance_results[str(bt_atten)])) |
| 477 | attenuation = [] |
| 478 | lower_limit = [] |
| 479 | upper_limit = [] |
| 480 | for idx, current_throughput in enumerate( |
| 481 | self.rvr[bt_atten]["throughput_received"]): |
Globaledge | e778933 | 2019-04-30 17:35:20 +0530 | [diff] [blame] | 482 | current_att = self.rvr[bt_atten]["attenuation"][idx] |
globaledge | dbc4642 | 2018-08-27 20:08:26 +0530 | [diff] [blame] | 483 | att_distances = [ |
| 484 | abs(current_att - performance_att) |
| 485 | for performance_att in performance_attenuation |
| 486 | ] |
| 487 | sorted_distances = sorted( |
| 488 | enumerate(att_distances), key=lambda x: x[1]) |
| 489 | closest_indeces = [dist[0] for dist in sorted_distances[0:3]] |
| 490 | closest_throughputs = [ |
| 491 | performance_results[str(bt_atten)]["throughput_received"][ |
| 492 | index] for index in closest_indeces |
| 493 | ] |
| 494 | closest_throughputs.sort() |
| 495 | attenuation.append(current_att) |
| 496 | lower_limit.append( |
| 497 | max(closest_throughputs[0] - |
| 498 | max(self.test_params["abs_tolerance"], |
| 499 | closest_throughputs[0] * |
| 500 | self.test_params["pct_tolerance"] / 100), 0)) |
| 501 | upper_limit.append(closest_throughputs[-1] + max( |
| 502 | self.test_params["abs_tolerance"], closest_throughputs[-1] * |
| 503 | self.test_params["pct_tolerance"] / 100)) |
| 504 | throughput_limits[bt_atten]["attenuation"] = attenuation |
| 505 | throughput_limits[bt_atten]["lower_limit"] = lower_limit |
| 506 | throughput_limits[bt_atten]["upper_limit"] = upper_limit |
| 507 | return throughput_limits |
Sriram Sundararajan | 4f303cf | 2019-03-21 18:32:21 -0700 | [diff] [blame] | 508 | |