blob: c32b02b4fff2d6a550bb8b20a9356061cc9f7adc [file] [log] [blame]
/* Copyright 2019 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.
*/
#include "hardware_verifier/verifier_impl.h"
#include <map>
#include <string>
#include <utility>
#include <base/logging.h>
#include <base/optional.h>
namespace hardware_verifier {
base::Optional<HwVerificationReport> VerifierImpl::Verify(
const runtime_probe::ProbeResult& probe_result,
const HwVerificationSpec& hw_verification_spec) const {
// A dictionary which maps (component_category, component_uuid) to its
// qualification status.
std::map<int, std::map<std::string, QualificationStatus>> qual_status_dict;
for (int i = 0; i < hw_verification_spec.component_infos_size(); ++i) {
const auto& component_info = hw_verification_spec.component_infos(i);
const auto& category = component_info.component_category();
const auto& uuid = component_info.component_uuid();
const auto& qualification_status = component_info.qualification_status();
const auto& insert_result =
qual_status_dict[static_cast<int>(category)].emplace(
uuid, qualification_status);
if (!insert_result.second) {
LOG(ERROR)
<< "The verification spec contains duplicated component infos.";
return base::nullopt;
}
}
HwVerificationReport hw_verification_report;
hw_verification_report.set_is_compliant(true);
const auto* category_enum_desc =
runtime_probe::ProbeRequest_SupportCategory_descriptor();
const auto* probe_result_refl = probe_result.GetReflection();
for (int i = 0; i < category_enum_desc->value_count(); ++i) {
const auto* category_enum_value_desc = category_enum_desc->value(i);
const auto& category_num = category_enum_value_desc->number();
const auto& category_name = category_enum_value_desc->name();
// We expect the enum item name to be identical to the field name in
// |runtime_probe::ProbeResult| message.
const auto* field_desc =
probe_result.GetDescriptor()->FindFieldByName(category_name);
DCHECK(field_desc) << "Couldn't find the field (" << category_name
<< ") in |runtime_probe::ProbeResult| message.";
DCHECK(field_desc->cpp_type() == field_desc->CPPTYPE_MESSAGE &&
field_desc->is_repeated())
<< "Field (" << category_name
<< ") must be a repeated field for the HW components.";
const auto& comp_name_to_qual_status = qual_status_dict[category_num];
for (int j = 0; j < probe_result_refl->FieldSize(probe_result, field_desc);
++j) {
const auto& comp =
probe_result_refl->GetRepeatedMessage(probe_result, field_desc, j);
const auto* comp_refl = comp.GetReflection();
const auto* comp_name_desc =
comp.GetDescriptor()->FindFieldByName("name");
DCHECK(comp_name_desc &&
comp_name_desc->cpp_type() == comp_name_desc->CPPTYPE_STRING &&
comp_name_desc->is_optional())
<< "Field (" << category_name
<< ") should contain a string of the name of the component.";
if (!comp_refl->HasField(comp, comp_name_desc)) {
LOG(ERROR) << "The component name is missing in the probe result.";
return base::nullopt;
}
const auto& comp_name = comp_refl->GetString(comp, comp_name_desc);
const auto& qual_status_it = comp_name_to_qual_status.find(comp_name);
if (qual_status_it == comp_name_to_qual_status.end()) {
LOG(ERROR) << "The probe result contains unregonizable components "
<< "(category=" << category_name << ", uuid=" << comp_name
<< ").";
return base::nullopt;
}
auto* found_comp_info =
hw_verification_report.add_found_component_infos();
found_comp_info->set_component_category(
static_cast<runtime_probe::ProbeRequest_SupportCategory>(
category_num));
found_comp_info->set_component_uuid(comp_name);
found_comp_info->set_qualification_status(qual_status_it->second);
if (qual_status_it->second != QualificationStatus::QUALIFIED) {
hw_verification_report.set_is_compliant(false);
}
}
}
// TODO(yhong): Implement the SKU specific checks.
return hw_verification_report;
}
} // namespace hardware_verifier