1#!/usr/bin/env python3.4 2# 3# Copyright 2022 - 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 csv 19import itertools 20import numpy 21import json 22import re 23import os 24from acts import context 25from acts import base_test 26from acts.metrics.loggers.blackbox import BlackboxMappedMetricLogger 27from acts_contrib.test_utils.cellular.performance import cellular_performance_test_utils as cputils 28from acts_contrib.test_utils.cellular.performance.CellularThroughputBaseTest import CellularThroughputBaseTest 29from acts_contrib.test_utils.wifi import wifi_performance_test_utils as wputils 30from acts_contrib.test_utils.wifi.wifi_performance_test_utils.bokeh_figure import BokehFigure 31from functools import partial 32 33 34class CellularLteFr1EndcRvrTest(CellularThroughputBaseTest): 35 """Class to test ENDC sensitivity""" 36 37 def __init__(self, controllers): 38 base_test.BaseTestClass.__init__(self, controllers) 39 self.testcase_metric_logger = ( 40 BlackboxMappedMetricLogger.for_test_case()) 41 self.testclass_metric_logger = ( 42 BlackboxMappedMetricLogger.for_test_class()) 43 self.publish_testcase_metrics = True 44 self.testclass_params = self.user_params['endc_rvr_test_params'] 45 self.tests = self.generate_test_cases(lte_dl_mcs_table='QAM256', 46 lte_ul_mcs_table='QAM256', 47 lte_ul_mcs=4, 48 nr_ul_mcs=4, 49 transform_precoding=0, 50 schedule_scenario='FULL_TPUT', 51 schedule_slot_ratio=80, 52 nr_dl_mcs_table='Q256', 53 nr_ul_mcs_table='Q64') 54 55 def process_testclass_results(self): 56 pass 57 58 def process_testcase_results(self): 59 if self.current_test_name not in self.testclass_results: 60 return 61 testcase_data = self.testclass_results[self.current_test_name] 62 63 average_power_list = [] 64 cell_throughput_lists = {} 65 for current_cell_idx, current_cell in enumerate(testcase_data['testcase_params']['endc_combo_config']['cell_list']): 66 cell_throughput_lists[current_cell_idx]=[] 67 68 for result in testcase_data['results']: 69 for current_cell_idx, current_cell in enumerate(testcase_data['testcase_params']['endc_combo_config']['cell_list']): 70 if current_cell['cell_type'] == 'LTE': 71 cell_throughput_lists[current_cell_idx].append( 72 result['throughput_measurements']['lte_tput_result'][current_cell['cell_number']] 73 ['DL']['average_tput']) 74 else: 75 cell_throughput_lists[current_cell_idx].append( 76 result['throughput_measurements']['nr_tput_result'][current_cell['cell_number']] 77 ['DL']['average_tput']) 78 if self.power_monitor: 79 average_power_list.append(result['average_power']) 80 81 plot = BokehFigure( 82 title='ENDC RvR', 83 x_label='Cell Power (dBm/SCS)', 84 primary_y_label='PHY Rate (Mbps)', 85 secondary_y_label='Power Consumption (mW)') 86 87 for cell_idx, cell_throughput_list in cell_throughput_lists.items(): 88 plot.add_line( 89 testcase_data['testcase_params']['cell_power_sweep'][cell_idx], 90 cell_throughput_lists[cell_idx], 91 'Cell {} - Average Throughput'.format(cell_idx), 92 width=1) 93 94 if self.power_monitor: 95 plot.add_line( 96 testcase_data['testcase_params']['cell_power_sweep'][0], 97 average_power_list, 98 'Power Consumption (mW)', 99 width=1, 100 style='dashdot', 101 y_axis='secondary') 102 103 plot.generate_figure() 104 output_file_path = os.path.join(self.log_path, '{}.html'.format(self.current_test_name)) 105 BokehFigure.save_figure(plot, output_file_path) 106 107 results_file_path = os.path.join( 108 context.get_current_context().get_full_output_path(), 109 '{}.json'.format(self.current_test_name)) 110 with open(results_file_path, 'w') as results_file: 111 json.dump(wputils.serialize_dict(testcase_data), 112 results_file, 113 indent=4) 114 115 def get_per_cell_power_sweeps(self, testcase_params): 116 cell_power_sweeps = [] 117 # Construct test cell sweep 118 lte_sweep = list( 119 numpy.arange(self.testclass_params['lte_cell_power_start'], 120 self.testclass_params['lte_cell_power_stop'], 121 self.testclass_params['lte_cell_power_step'])) 122 nr_sweep = list( 123 numpy.arange(self.testclass_params['nr_cell_power_start'], 124 self.testclass_params['nr_cell_power_stop'], 125 self.testclass_params['nr_cell_power_step'])) 126 if len(lte_sweep) > len(nr_sweep): 127 nr_sweep_pad = len(lte_sweep) - len(nr_sweep) 128 nr_sweep.extend([nr_sweep[-1]]*nr_sweep_pad) 129 elif len(lte_sweep) < len(nr_sweep): 130 lte_sweep_pad = len(nr_sweep) - len(lte_sweep) 131 lte_sweep.extend([lte_sweep[-1]]*lte_sweep_pad) 132 133 134 for cell_idx, cell_config in enumerate(testcase_params['endc_combo_config']['cell_list']): 135 if testcase_params['test_cell_idx'] in [cell_idx, 'all']: 136 if cell_config['cell_type'] == 'LTE': 137 cell_power_sweeps.append(lte_sweep) 138 elif cell_config['cell_type'] == 'NR5G': 139 cell_power_sweeps.append(nr_sweep) 140 elif cell_config['cell_type'] == 'LTE': 141 cell_power_sweeps.append([self.testclass_params['lte_cell_power_start'] 142 ] * len(nr_sweep)) 143 elif cell_config['cell_type'] == 'NR5G': 144 cell_power_sweeps.append([self.testclass_params['nr_cell_power_start'] 145 ] * len(lte_sweep)) 146 return cell_power_sweeps 147 148 def generate_test_cases(self, lte_dl_mcs_table, 149 lte_ul_mcs_table, lte_ul_mcs, 150 nr_ul_mcs, **kwargs): 151 test_cases = [] 152 with open(self.testclass_params['endc_combo_file'], 153 'r') as endc_combos: 154 for endc_combo_str in endc_combos: 155 if endc_combo_str[0] == '#': 156 continue 157 endc_combo_config = cputils.generate_endc_combo_config_from_string( 158 endc_combo_str) 159 special_chars = '+[]=;,\n' 160 for char in special_chars: 161 endc_combo_str = endc_combo_str.replace(char, '_') 162 endc_combo_str = endc_combo_str.replace('__', '_') 163 endc_combo_str = endc_combo_str.strip('_') 164 test_cell_list = list(range(len(endc_combo_config['cell_list']))) 165 test_cell_list.append('all') 166 for cell_idx in test_cell_list: 167 test_name = 'test_rvr_{}_cell_{}'.format( 168 endc_combo_str, cell_idx) 169 test_params = collections.OrderedDict( 170 endc_combo_config=endc_combo_config, 171 test_cell_idx=cell_idx, 172 lte_dl_mcs_table=lte_dl_mcs_table, 173 lte_dl_mcs=self.testclass_params['link_adaptation_config']['LTE'], 174 lte_ul_mcs_table=lte_ul_mcs_table, 175 lte_ul_mcs=lte_ul_mcs, 176 nr_dl_mcs=self.testclass_params['link_adaptation_config']['NR5G'], 177 nr_ul_mcs=nr_ul_mcs, 178 **kwargs) 179 setattr(self, test_name, 180 partial(self._test_throughput_bler, test_params)) 181 test_cases.append(test_name) 182 return test_cases