• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
31
32from functools import partial
33
34
35class CellularLteRvrTest(CellularThroughputBaseTest):
36    """Class to test single cell LTE sensitivity"""
37
38    def __init__(self, controllers):
39        base_test.BaseTestClass.__init__(self, controllers)
40        self.testcase_metric_logger = (
41            BlackboxMappedMetricLogger.for_test_case())
42        self.testclass_metric_logger = (
43            BlackboxMappedMetricLogger.for_test_class())
44        self.publish_testcase_metrics = True
45        self.testclass_params = self.user_params['lte_rvr_test_params']
46        self.tests = self.generate_test_cases(lte_dl_mcs_table='QAM256',
47                                              lte_ul_mcs_table='QAM256',
48                                              lte_ul_mcs=4,
49                                              transform_precoding=0)
50
51    def process_testclass_results(self):
52        # Plot individual test id results raw data and compile metrics
53        plots = collections.OrderedDict()
54        compiled_data = collections.OrderedDict()
55        for testcase_name, testcase_data in self.testclass_results.items():
56            cell_config = testcase_data['testcase_params'][
57                'endc_combo_config']['cell_list'][0]
58            test_id = tuple(('band', cell_config['band']))
59            if test_id not in plots:
60                # Initialize test id data when not present
61                compiled_data[test_id] = {
62                    'mcs': [],
63                    'average_throughput': [],
64                    'theoretical_throughput': [],
65                    'cell_power': [],
66                }
67                plots[test_id] = BokehFigure(
68                    title='Band {} ({}) - BLER Curves'.format(
69                        cell_config['band'],
70                        testcase_data['testcase_params']['lte_dl_mcs_table']),
71                    x_label='Cell Power (dBm)',
72                    primary_y_label='BLER (Mbps)')
73                test_id_rvr = test_id + tuple('RvR')
74                plots[test_id_rvr] = BokehFigure(
75                    title='Band {} ({}) - RvR'.format(
76                        cell_config['band'],
77                        testcase_data['testcase_params']['lte_dl_mcs_table']),
78                    x_label='Cell Power (dBm)',
79                    primary_y_label='PHY Rate (Mbps)')
80            # Compile test id data and metrics
81            compiled_data[test_id]['average_throughput'].append(
82                testcase_data['average_throughput_list'])
83            compiled_data[test_id]['cell_power'].append(
84                testcase_data['cell_power_list'])
85            compiled_data[test_id]['mcs'].append(
86                testcase_data['testcase_params']['lte_dl_mcs'])
87            # Add test id to plots
88            plots[test_id].add_line(
89                testcase_data['cell_power_list'],
90                testcase_data['bler_list'],
91                'MCS {}'.format(
92                    testcase_data['testcase_params']['lte_dl_mcs']),
93                width=1)
94            plots[test_id_rvr].add_line(
95                testcase_data['cell_power_list'],
96                testcase_data['average_throughput_list'],
97                'MCS {}'.format(
98                    testcase_data['testcase_params']['lte_dl_mcs']),
99                width=1,
100                style='dashed')
101
102        # Compute average RvRs and compute metrics over orientations
103        for test_id, test_data in compiled_data.items():
104            test_id_rvr = test_id + tuple('RvR')
105            cell_power_interp = sorted(set(sum(test_data['cell_power'], [])))
106            average_throughput_interp = []
107            for mcs, cell_power, throughput in zip(
108                    test_data['mcs'], test_data['cell_power'],
109                    test_data['average_throughput']):
110                throughput_interp = numpy.interp(cell_power_interp,
111                                                 cell_power[::-1],
112                                                 throughput[::-1])
113                average_throughput_interp.append(throughput_interp)
114            rvr = numpy.max(average_throughput_interp, 0)
115            plots[test_id_rvr].add_line(cell_power_interp, rvr,
116                                        'Rate vs. Range')
117
118        figure_list = []
119        for plot_id, plot in plots.items():
120            plot.generate_figure()
121            figure_list.append(plot)
122        output_file_path = os.path.join(self.log_path, 'results.html')
123        BokehFigure.save_figures(figure_list, output_file_path)
124
125    def process_testcase_results(self):
126        if self.current_test_name not in self.testclass_results:
127            return
128        testcase_data = self.testclass_results[self.current_test_name]
129        results_file_path = os.path.join(
130            context.get_current_context().get_full_output_path(),
131            '{}.json'.format(self.current_test_name))
132        with open(results_file_path, 'w') as results_file:
133            json.dump(wputils.serialize_dict(testcase_data),
134                      results_file,
135                      indent=4)
136
137        bler_list = []
138        average_throughput_list = []
139        theoretical_throughput_list = []
140        cell_power_list = testcase_data['testcase_params']['cell_power_sweep'][
141            0]
142        for result in testcase_data['results']:
143            bler_list.append(
144                result['throughput_measurements']['lte_bler_result']['total']['DL']['nack_ratio'])
145            average_throughput_list.append(
146                result['throughput_measurements']['lte_tput_result']['total']['DL']['average_tput'])
147            theoretical_throughput_list.append(
148                result['throughput_measurements']['lte_tput_result']['total']['DL']['theoretical_tput'])
149        padding_len = len(cell_power_list) - len(average_throughput_list)
150        average_throughput_list.extend([0] * padding_len)
151        theoretical_throughput_list.extend([0] * padding_len)
152
153        testcase_data['bler_list'] = bler_list
154        testcase_data['average_throughput_list'] = average_throughput_list
155        testcase_data[
156            'theoretical_throughput_list'] = theoretical_throughput_list
157        testcase_data['cell_power_list'] = cell_power_list
158
159        plot = BokehFigure(
160            title='Band {} - RvR'.format(testcase_data['testcase_params']['endc_combo_config']['cell_list'][0]['band']),
161            x_label='Cell Power (dBm)',
162            primary_y_label='PHY Rate (Mbps)')
163
164        plot.add_line(
165            testcase_data['cell_power_list'],
166            testcase_data['average_throughput_list'],
167            'Average Throughput',
168            width=1)
169        plot.add_line(
170            testcase_data['cell_power_list'],
171            testcase_data['theoretical_throughput_list'],
172            'Average Throughput',
173            width=1,
174            style='dashed')
175        plot.generate_figure()
176        output_file_path = os.path.join(self.log_path, '{}.html'.format(self.current_test_name))
177        BokehFigure.save_figure(plot, output_file_path)
178
179    def get_per_cell_power_sweeps(self, testcase_params):
180        # get current cell power start
181        cell_power_sweeps = [
182            list(
183                numpy.arange(self.testclass_params['lte_cell_power_start'],
184                             self.testclass_params['lte_cell_power_stop'],
185                             self.testclass_params['lte_cell_power_step']))
186        ]
187        return cell_power_sweeps
188
189    def generate_test_cases(self, lte_dl_mcs_table,
190                            lte_ul_mcs_table, lte_ul_mcs, **kwargs):
191        test_cases = []
192        with open(self.testclass_params['lte_single_cell_configs'],
193                  'r') as csvfile:
194            test_configs = csv.DictReader(csvfile)
195            for test_config in test_configs:
196                if int(test_config['skip_test']):
197                    continue
198                endc_combo_config = cputils.generate_endc_combo_config_from_csv_row(
199                    test_config)
200                test_name = 'test_lte_B{}_dl_{}'.format(
201                    test_config['lte_band'], lte_dl_mcs_table)
202                test_params = collections.OrderedDict(
203                    endc_combo_config=endc_combo_config,
204                    lte_dl_mcs_table=lte_dl_mcs_table,
205                    lte_dl_mcs='WCQI',
206                    lte_ul_mcs_table=lte_ul_mcs_table,
207                    lte_ul_mcs=lte_ul_mcs,
208                    **kwargs)
209                setattr(self, test_name,
210                        partial(self._test_throughput_bler, test_params))
211                test_cases.append(test_name)
212        return test_cases
213