Updates to WiFi RvR pass/fail, plotting, etc. am: c01e1efd1c
am: 5d462d263b
Change-Id: Id01922b2a063d48f01a4c9e5eb8ceabaeb866274
diff --git a/acts/framework/acts/test_utils/wifi/wifi_power_test_utils.py b/acts/framework/acts/test_utils/wifi/wifi_power_test_utils.py
index ca7557a..7eda9d4 100644
--- a/acts/framework/acts/test_utils/wifi/wifi_power_test_utils.py
+++ b/acts/framework/acts/test_utils/wifi/wifi_power_test_utils.py
@@ -269,15 +269,14 @@
color = ['navy'] * len(current_data)
#Preparing the data and source link for bokehn java callback
- source = ColumnDataSource(
- data=dict(x0=time_relative, y0=current_data, color=color))
- s2 = ColumnDataSource(
- data=dict(
- z0=[mon_info['duration']],
- y0=[round(avg_current, 2)],
- x0=[round(avg_current * voltage, 2)],
- z1=[round(avg_current * voltage * mon_info['duration'], 2)],
- z2=[round(avg_current * mon_info['duration'], 2)]))
+ source = ColumnDataSource(data=dict(
+ x0=time_relative, y0=current_data, color=color))
+ s2 = ColumnDataSource(data=dict(
+ z0=[mon_info['duration']],
+ y0=[round(avg_current, 2)],
+ x0=[round(avg_current * voltage, 2)],
+ z1=[round(avg_current * voltage * mon_info['duration'], 2)],
+ z2=[round(avg_current * mon_info['duration'], 2)]))
#Setting up data table for the output
columns = [
TableColumn(field='z0', title='Total Duration (s)'),
@@ -447,7 +446,11 @@
return brconfigs
-def bokeh_plot(data_sets, legends, fig_property, output_file_path=None):
+def bokeh_plot(data_sets,
+ legends,
+ fig_property,
+ shaded_region=None,
+ output_file_path=None):
"""Plot bokeh figs.
Args:
data_sets: data sets including lists of x_data and lists of y_data
@@ -455,6 +458,8 @@
legends: list of legend for each curve
fig_property: dict containing the plot property, including title,
lables, linewidth, circle size, etc.
+ shaded_region: optional dict containing data for plot shading
+ output_file_path: optional path at which to save figure
Returns:
plot: bokeh plot figure object
"""
@@ -471,6 +476,14 @@
'red', 'green', 'blue', 'olive', 'orange', 'salmon', 'black', 'navy',
'yellow', 'darkred', 'goldenrod'
]
+ if shaded_region:
+ band_x = shaded_region["x_vector"]
+ band_x.extend(shaded_region["x_vector"][::-1])
+ band_y = shaded_region["lower_limit"]
+ band_y.extend(shaded_region["upper_limit"][::-1])
+ plot.patch(
+ band_x, band_y, color='#7570B3', line_alpha=0.1, fill_alpha=0.1)
+
for x_data, y_data, legend in zip(data_sets[0], data_sets[1], legends):
index_now = legends.index(legend)
color = colors[index_now % len(colors)]
@@ -478,6 +491,7 @@
x_data, y_data, legend=str(legend), line_width=3, color=color)
plot.circle(
x_data, y_data, size=10, legend=str(legend), fill_color=color)
+
#Plot properties
plot.xaxis.axis_label = fig_property['x_label']
plot.yaxis.axis_label = fig_property['y_label']
diff --git a/acts/tests/google/wifi/WifiRvrTest.py b/acts/tests/google/wifi/WifiRvrTest.py
index 5cd0835..923525c 100644
--- a/acts/tests/google/wifi/WifiRvrTest.py
+++ b/acts/tests/google/wifi/WifiRvrTest.py
@@ -85,15 +85,19 @@
"markersize": 10
}
output_file_path = "{}/{}.html".format(self.log_path, "rvr_results")
- wputils.bokeh_plot(data_sets, legends, fig_property, output_file_path)
+ wputils.bokeh_plot(
+ data_sets,
+ legends,
+ fig_property,
+ shaded_region=None,
+ output_file_path=output_file_path)
def pass_fail_check(self, rvr_result):
"""Check the test result and decide if it passed or failed.
- Checks the RvR test result and compares to a golden file of results for
+ Checks the RvR test result and compares to a throughput limites for
the same configuration. The pass/fail tolerances are provided in the
- config file. Currently, the test fails if any a single point is out of
- range of the corresponding area in the golden file.
+ config file.
Args:
rvr_result: dict containing attenuation, throughput and other meta
@@ -105,12 +109,54 @@
if test_name in file_name
]
gldn_path = gldn_path[0]
+ throughput_limits = self.compute_throughput_limits(
+ gldn_path, rvr_result)
+
+ failure_count = 0
+ for idx, current_throughput in enumerate(
+ rvr_result["throughput_receive"]):
+ current_att = rvr_result["attenuation"][idx] + rvr_result["fixed_attenuation"]
+ if (current_throughput < throughput_limits["lower_limit"][idx]
+ or current_throughput >
+ throughput_limits["upper_limit"][idx]):
+ failure_count = failure_count + 1
+ self.log.info(
+ "Throughput at {}dB attenuation is beyond limits. "
+ "Throughput is {} Mbps. Expected within [{}, {}] Mbps.".
+ format(current_att, current_throughput,
+ throughput_limits["lower_limit"][idx],
+ throughput_limits["upper_limit"][idx]))
+ if failure_count >= self.test_params["failure_count_tolerance"]:
+ asserts.fail(
+ "Test failed. Found {} points outside throughput limits.".
+ format(failure_count))
+ asserts.explicit_pass(
+ "Test passed. Found {} points outside throughput limits.".format(
+ failure_count))
+
+ def compute_throughput_limits(self, gldn_path, rvr_result):
+ """Compute throughput limits for current test.
+
+ Checks the RvR test result and compares to a throughput limites for
+ the same configuration. The pass/fail tolerances are provided in the
+ config file.
+
+ Args:
+ gldn_path: path to golden file used to generate limits
+ rvr_result: dict containing attenuation, throughput and other meta
+ data
+ Returns:
+ throughput_limits: dict containing attenuation and throughput limit data
+ """
with open(gldn_path, 'r') as gldn_file:
gldn_results = json.load(gldn_file)
gldn_attenuation = [
att + gldn_results["fixed_attenuation"]
for att in gldn_results["attenuation"]
]
+ attenuation = []
+ lower_limit = []
+ upper_limit = []
for idx, current_throughput in enumerate(
rvr_result["throughput_receive"]):
current_att = rvr_result["attenuation"][idx] + rvr_result["fixed_attenuation"]
@@ -119,34 +165,27 @@
]
sorted_distances = sorted(
enumerate(att_distances), key=lambda x: x[1])
- closest_indeces = [dist[0] for dist in sorted_distances[0:2]]
+ closest_indeces = [dist[0] for dist in sorted_distances[0:3]]
closest_throughputs = [
gldn_results["throughput_receive"][index]
for index in closest_indeces
]
closest_throughputs.sort()
- allowed_throughput_range = [
+ attenuation.append(current_att)
+ lower_limit.append(
max(closest_throughputs[0] - max(
self.test_params["abs_tolerance"], closest_throughputs[0] *
- self.test_params["pct_tolerance"] / 100),
- 0), closest_throughputs[1] +
- max(self.test_params["abs_tolerance"], closest_throughputs[1] *
- self.test_params["pct_tolerance"] / 100)
- ]
- throughput_distance = [
- current_throughput - throughput_limit
- for throughput_limit in allowed_throughput_range
- ]
- if (throughput_distance[0] < -self.test_params["abs_tolerance"]
- or throughput_distance[1] >
- self.test_params["abs_tolerance"]):
- asserts.fail(
- "Throughput at {}dB attenuation is beyond limits. "
- "Throughput is {} Mbps. Expected within {} Mbps.".format(
- current_att, current_throughput,
- allowed_throughput_range))
- asserts.explicit_pass("Measurement finished for %s." % test_name)
+ self.test_params["pct_tolerance"] / 100), 0))
+ upper_limit.append(closest_throughputs[-1] + max(
+ self.test_params["abs_tolerance"], closest_throughputs[-1] *
+ self.test_params["pct_tolerance"] / 100))
+ throughput_limits = {
+ "attenuation": attenuation,
+ "lower_limit": lower_limit,
+ "upper_limit": upper_limit
+ }
+ return throughput_limits
def post_process_results(self, rvr_result):
"""Saves plots and JSON formatted results.
@@ -192,10 +231,18 @@
]
data_sets[0].insert(0, gldn_attenuation)
data_sets[1].insert(0, gldn_results["throughput_receive"])
+ throughput_limits = self.compute_throughput_limits(
+ gldn_path, rvr_result)
+ shaded_region = {
+ "x_vector": throughput_limits["attenuation"],
+ "lower_limit": throughput_limits["lower_limit"],
+ "upper_limit": throughput_limits["upper_limit"]
+ }
except:
self.log.warning("ValueError: Golden file not found")
output_file_path = "{}/{}.html".format(self.log_path, test_name)
- wputils.bokeh_plot(data_sets, legends, fig_property, output_file_path)
+ wputils.bokeh_plot(data_sets, legends, fig_property, shaded_region,
+ output_file_path)
def rvr_test(self):
"""Test function to run RvR.
@@ -267,10 +314,6 @@
rvr_result: dict containing rvr_results and meta data
"""
#Initialize RvR test parameters
- if self.test_params["rvr_atten_step"] not in [0.25, 0.5, 0.75, 1]:
- self.log.warning(
- "Attenuation step not supported. Attenuation vector may not be applied exactly."
- )
num_atten_steps = int((self.test_params["rvr_atten_stop"] -
self.test_params["rvr_atten_start"]) /
self.test_params["rvr_atten_step"])
@@ -279,9 +322,6 @@
x * self.test_params["rvr_atten_step"]
for x in range(0, num_atten_steps)
]
- #self.rvr_atten_range = range(self.test_params["rvr_atten_start"],
- # self.test_params["rvr_atten_stop"],
- # self.test_params["rvr_atten_step"])
rvr_result = {}
# Configure AP
band = self.access_point.band_lookup_by_channel(channel)
@@ -333,6 +373,13 @@
#Test cases
class WifiRvr_2GHz_Test(WifiRvrTest):
+ def __init__(self, controllers):
+ base_test.BaseTestClass.__init__(self, controllers)
+ self.tests = ("test_rvr_TCP_DL_ch1_VHT20", "test_rvr_TCP_UL_ch1_VHT20",
+ "test_rvr_TCP_DL_ch6_VHT20", "test_rvr_TCP_UL_ch6_VHT20",
+ "test_rvr_TCP_DL_ch11_VHT20",
+ "test_rvr_TCP_UL_ch11_VHT20")
+
@test_tracker_info(uuid='e7586217-3739-44a4-a87b-d790208b04b9')
def test_rvr_TCP_DL_ch1_VHT20(self):
self._test_rvr()
@@ -359,6 +406,17 @@
class WifiRvr_UNII1_Test(WifiRvrTest):
+ def __init__(self, controllers):
+ base_test.BaseTestClass.__init__(self, controllers)
+ self.tests = (
+ "test_rvr_TCP_DL_ch36_VHT20", "test_rvr_TCP_UL_ch36_VHT20",
+ "test_rvr_TCP_DL_ch36_VHT40", "test_rvr_TCP_UL_ch36_VHT40",
+ "test_rvr_TCP_DL_ch36_VHT80", "test_rvr_TCP_UL_ch36_VHT80",
+ "test_rvr_TCP_DL_ch40_VHT20", "test_rvr_TCP_UL_ch40_VHT20",
+ "test_rvr_TCP_DL_ch44_VHT20", "test_rvr_TCP_UL_ch44_VHT20",
+ "test_rvr_TCP_DL_ch44_VHT40", "test_rvr_TCP_UL_ch44_VHT40",
+ "test_rvr_TCP_DL_ch48_VHT20", "test_rvr_TCP_UL_ch48_VHT20")
+
@test_tracker_info(uuid='a48ee2b4-3fb9-41fd-b292-0051bfc3b0cc')
def test_rvr_TCP_DL_ch36_VHT20(self):
self._test_rvr()
@@ -417,6 +475,17 @@
class WifiRvr_UNII3_Test(WifiRvrTest):
+ def __init__(self, controllers):
+ base_test.BaseTestClass.__init__(self, controllers)
+ self.tests = (
+ "test_rvr_TCP_DL_ch149_VHT20", "test_rvr_TCP_UL_ch149_VHT20",
+ "test_rvr_TCP_DL_ch149_VHT40", "test_rvr_TCP_UL_ch149_VHT40",
+ "test_rvr_TCP_DL_ch149_VHT80", "test_rvr_TCP_UL_ch149_VHT80",
+ "test_rvr_TCP_DL_ch153_VHT20", "test_rvr_TCP_UL_ch153_VHT20",
+ "test_rvr_TCP_DL_ch157_VHT20", "test_rvr_TCP_UL_ch157_VHT20",
+ "test_rvr_TCP_DL_ch157_VHT40", "test_rvr_TCP_UL_ch157_VHT40",
+ "test_rvr_TCP_DL_ch161_VHT20", "test_rvr_TCP_UL_ch161_VHT20")
+
@test_tracker_info(uuid='24aa1e7a-3978-4803-877f-3ac5812ab0ae')
def test_rvr_TCP_DL_ch149_VHT20(self):
self._test_rvr()
@@ -476,6 +545,17 @@
# UDP Tests
class WifiRvr_SampleUDP_Test(WifiRvrTest):
+ def __init__(self, controllers):
+ base_test.BaseTestClass.__init__(self, controllers)
+ self.tests = (
+ "test_rvr_UDP_DL_ch6_VHT20", "test_rvr_UDP_UL_ch6_VHT20",
+ "test_rvr_UDP_DL_ch36_VHT20", "test_rvr_UDP_UL_ch36_VHT20",
+ "test_rvr_UDP_DL_ch36_VHT40", "test_rvr_UDP_UL_ch36_VHT40",
+ "test_rvr_UDP_DL_ch36_VHT80", "test_rvr_UDP_UL_ch36_VHT80",
+ "test_rvr_UDP_DL_ch149_VHT20", "test_rvr_UDP_UL_ch149_VHT20",
+ "test_rvr_UDP_DL_ch149_VHT40", "test_rvr_UDP_UL_ch149_VHT40",
+ "test_rvr_UDP_DL_ch149_VHT80", "test_rvr_UDP_UL_ch149_VHT80")
+
@test_tracker_info(uuid='05614f92-38fa-4289-bcff-d4b4a2a2ad5b')
def test_rvr_UDP_DL_ch6_VHT20(self):
self._test_rvr()