blob: 9bb78aece475836af53932a733cd6445e03f2e01 [file] [log] [blame]
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Checks Wifi calibration table from
/sys/kernel/debug/ieee80211/phy*/ath9k/dump_eep_power.
If the test fails, then the test displays tables and hangs forever.
"""
import glob
import pprint
import re
import unittest
import factory_common # pylint: disable=unused-import
from cros.factory.test import event_log
from cros.factory.test import factory
from cros.factory.test.i18n import test_ui as i18n_test_ui
from cros.factory.test import test_ui
from cros.factory.test import ui_templates
from cros.factory.utils.arg_utils import Arg
ANCHOR_FOR_LOW_BAND_CALIBRATION_DATA = 'calPierData2G'
ANCHOR_FOR_HIGH_BAND_CALIBRATION_DATA = 'calPierData5G'
EEP_POWER_PATH = '/sys/kernel/debug/ieee80211/phy*/ath9k/dump_eep_power'
def IsInRange(observed, min_val, max_val):
"""Returns True if min_val <= observed <= max_val.
If any of min_val or max_val is missing, it means there is no lower or
upper bounds respectively.
"""
if min_val and observed < min_val:
return False
if max_val and observed > max_val:
return False
return True
def CheckRefPowerRange(table, expected_range_dict, band_name):
"""Checks if the ref power is in range."""
for row_idx, single_row in enumerate(table):
chain = int(single_row[0])
ref_power = int(single_row[1])
expected_range = expected_range_dict[chain]
if not IsInRange(ref_power, expected_range[0], expected_range[1]):
factory.console.info(
'Ref power of %s, row[%d], chain[%d] is out of range',
band_name, row_idx, chain)
return False
return True
def CheckCalibratedUnits(table, min_required_units, band_name):
"""Checks min_required_units presented in calibration table."""
if len(table) < min_required_units:
factory.console.info(
'%s table has only %d calibrated units, %d required',
band_name, len(table), min_required_units)
return False
return True
class CheckWifiCalibrationTest(unittest.TestCase):
ARGS = [
Arg('min_low_band_required_unit', int,
'Expected the minimum numbers of calibrate units in 2.4G'),
Arg('min_high_band_required_unit', int,
'Expected the minimum numbers of calibrate units in 5G'),
Arg('expected_low_band_ref_power_range', dict,
'Expected range (min, max) for each chain in 2.4G.\n'
'Chain is the key of the dict.\n'
'For example::\n'
'\n'
' {0: (-20, None),\n'
' 1: (None, -10)}\n'
'\n'
'will check all refPower for chain 0 is greater than -20\n'
'and all refPower for chain 1 is less than -10.\n'),
Arg('expected_high_band_ref_power_range', dict,
'Expected range (min, max) for each chain in 5G.\n'
'Chain is the key of the dict.')
]
def readCalibrationTable(self, path, anchor_string):
with open(path) as f:
lines = f.readlines()
idx = 0
# Find the anchor
for line in lines:
idx = idx + 1
if re.search(anchor_string, line):
break
# Read the table until reach an empty line.
table = []
for line in lines[idx:]:
if re.search('^$', line):
break
table.append(line.split())
return table
def runTest(self):
# Found location of dump_eep_power
eep_power_path = glob.glob(EEP_POWER_PATH)
if len(eep_power_path) != 1:
raise IOError('unable to read dump_eep_power')
eep_power_path = eep_power_path[0]
low_band_table = self.readCalibrationTable(
eep_power_path, ANCHOR_FOR_LOW_BAND_CALIBRATION_DATA)
high_band_table = self.readCalibrationTable(
eep_power_path, ANCHOR_FOR_HIGH_BAND_CALIBRATION_DATA)
factory.console.info('2.4GHz table=%s',
pprint.pformat(low_band_table, width=200))
factory.console.info('5GHz table=%s',
pprint.pformat(high_band_table, width=200))
event_log.Log('low_band_table', value=low_band_table)
event_log.Log('high_band_table', value=high_band_table)
# Check numbers of calibrated units.
failed_flag = False
if not CheckCalibratedUnits(
low_band_table[1:], self.args.min_low_band_required_unit, '2.4G'):
failed_flag = True
if not CheckCalibratedUnits(
high_band_table[1:], self.args.min_high_band_required_unit, '5G'):
failed_flag = True
# Check ref power
if not CheckRefPowerRange(
low_band_table[1:],
self.args.expected_low_band_ref_power_range, '2.4G'):
failed_flag = True
if not CheckRefPowerRange(
high_band_table[1:],
self.args.expected_high_band_ref_power_range, '5G'):
failed_flag = True
if not failed_flag:
return # Pass the test
ui = test_ui.UI()
template = ui_templates.OneSection(ui)
template.SetTitle(
i18n_test_ui.MakeI18nLabel("Calibration data doesn't meet requirement"))
template.SetState(
'<div class=test-status-failed '
'style="font-size: 100%; white-space: pre-wrap">' +
'2.4G = %s\n' % pprint.pformat(low_band_table, width=200) +
'5G = %s\n' % pprint.pformat(high_band_table, width=200) +
'</div>')
ui.Run() # Forever