blob: 1d136cb713e973703ad22b296aff57fe0666ffc1 [file] [log] [blame]
# Copyright 2018 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.
"""Verify peripheral components.
Verify the number of components from probed results and from device data
are the same. And verify the status of components are supported when the
phase is PVT or PVT_DOGFOOD.
"""
import hashlib
import factory_common # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.hwid.v3 import common
from cros.factory.test import device_data
from cros.factory.test.rules import phase
from cros.factory.test import session
from cros.factory.test import test_case
from cros.factory.test.utils import deploy_utils
from cros.factory.test.utils import update_utils
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import json_utils
_NUMBER_NOT_IN_DEVICE_DATA = 1
class VerifyComponentTest(test_case.TestCase):
ARGS = [
Arg('approx_match', bool,
'Enable apporximate matching results.',
default=True),
Arg('enable_factory_server', bool,
'Update hwid data from factory server.',
default=True),
Arg('max_mismatch', int,
'The number of mismatched rules at most.',
default=1),
Arg('verify_checksum', bool,
'Enable converted statements checksum verification.',
default=True)
]
def setUp(self):
self.ui.SetupStaticFiles()
self.dut = device_utils.CreateDUTInterface()
self.factory_tools = deploy_utils.CreateFactoryTools(self.dut)
self.tmpdir = self.dut.temp.mktemp(is_dir=True, prefix='verify_component')
self.num_mismatch = []
self.not_supported = []
self.probed_results = {}
self.perfect_match_results = {}
self.component_data = {}
self.converted_statement_file = self.dut.path.join(
self.tmpdir, 'converted_statement_file.json')
def tearDown(self):
self.dut.Call(['rm', '-rf', self.tmpdir])
def runTest(self):
converted_statement, converted_checksum = self._GetConvertedStatement()
if self.args.verify_checksum:
if hashlib.sha1(converted_statement).hexdigest() != converted_checksum:
self.FailTask('Checksum failed.')
else:
session.console.info('Checksum passed.')
self.probed_results = json_utils.LoadStr(self.factory_tools.CheckOutput(
['probe', 'probe', '--config-file', self.converted_statement_file,
'--approx-match', '--max-mismatch',
'{}'.format(self.args.max_mismatch)]))
self.perfect_match_results = self._GetPerfectMatchProbeResult()
self.component_data = {k[4:]: int(v) for k, v in
device_data.GetDeviceData('component').iteritems()
if k.startswith('has_')}
self._VerifyNumMismatch()
self._VerifyNotSupported()
if self.num_mismatch or self.not_supported:
self.ui.CallJSFunction('setFailedMessage')
if self.num_mismatch:
self.ui.CallJSFunction(
'createNumMismatchResult', self.num_mismatch,
self.args.approx_match, self.probed_results)
if self.not_supported:
self.ui.CallJSFunction(
'createNotSupportedResult', self.not_supported)
self.WaitTaskEnd()
def _CheckPhase(self):
current_phase = phase.GetPhase()
return current_phase == phase.PVT or current_phase == phase.PVT_DOGFOOD
def _VerifyNumMismatch(self):
def _ExtractInfoToName(comp_info):
return [comp['name'] for comp in comp_info]
for comp_cls, correct_num in self.component_data.iteritems():
comp_info = self.perfect_match_results.get(comp_cls, [])
actual_num = len(comp_info)
if correct_num != actual_num:
self.num_mismatch.append((comp_cls, correct_num,
_ExtractInfoToName(comp_info)))
# The number of component should be _NUMBER_NOT_IN_DEVICE_DATA
# when the component is not in device data.
for comp_cls, comp_info in self.perfect_match_results.iteritems():
if comp_cls not in self.component_data:
actual_num = len(comp_info)
if actual_num != _NUMBER_NOT_IN_DEVICE_DATA:
self.num_mismatch.append(
(comp_cls, _NUMBER_NOT_IN_DEVICE_DATA,
_ExtractInfoToName(comp_info)))
def _VerifyNotSupported(self):
if self._CheckPhase():
for comp_cls, comp_info in self.perfect_match_results.iteritems():
for comp_item in comp_info:
status = comp_item['information']['status']
if status != common.COMPONENT_STATUS.supported:
self.not_supported.append((comp_cls, comp_item['name'], status))
def _GetConvertedStatement(self):
if self.args.enable_factory_server:
update_utils.UpdateHWIDDatabase(self.dut)
converted_checksum_file = self.dut.path.join(
self.tmpdir, 'converted_checksum')
self.factory_tools.CallOutput(
['hwid', 'converter', '--output-file', self.converted_statement_file,
'--output-checksum-file', converted_checksum_file])
converted_statement = self.dut.ReadFile(self.converted_statement_file)
converted_checksum = self.dut.ReadFile(converted_checksum_file)
return converted_statement, converted_checksum
def _GetPerfectMatchProbeResult(self):
res = {}
for comp_cls, comp_info in self.probed_results.iteritems():
res[comp_cls] = [item for item in comp_info if item['perfect_match']]
return res