# Copyright 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.
"""


import glob
import pprint
import re
import unittest

import factory_common  # pylint: disable=unused-import
from cros.factory.test import event_log  # TODO(chuntsen): Deprecate event log.
from cros.factory.test import session
from cros.factory.testlog import testlog
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 is not None and observed < min_val:
    return False
  if max_val is not None 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 = 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]):
      session.console.info(
          'Ref power of %s, row[%d], chain[%s] 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:
    session.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, null],\n'
          '   "1": [null, -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):
    # Find 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)

    session.console.info('2.4GHz table=%s',
                         pprint.pformat(low_band_table, width=200))
    session.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)
    testlog.LogParam('low_band_table', low_band_table)
    testlog.LogParam('high_band_table', 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 failed_flag:
      self.fail(
          "Calibration data doesn't meet requirement. 2.4G = %r, 5G = %r." %
          (low_band_table, high_band_table))
