blob: e10a5262aa93203647bddb6e197923ca74fa57f5 [file]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_DRIVER_TESTING_CPP_HEALTH_TEST_UTILS_H_
#define LIB_DRIVER_TESTING_CPP_HEALTH_TEST_UTILS_H_
#include <fidl/fuchsia.driver.framework/cpp/natural_types.h>
#include <lib/stdcompat/span.h>
#include <lib/zx/time.h>
#include <cstdint>
#include <optional>
#include <string_view>
namespace fdf_testing {
// Derives the overall `HealthStatus` (`kUnhealthy > kDegraded > kOk`) across `conditions`.
// Per `fuchsia.driver.framework/HealthCondition`, an omitted condition status is treated as
// `kUnhealthy`. Returns `kOk` when `conditions` is empty.
inline fuchsia_driver_framework::HealthStatus OverallHealthStatus(
cpp20::span<const fuchsia_driver_framework::HealthCondition> conditions) {
auto overall = fuchsia_driver_framework::HealthStatus::kOk;
for (const auto& condition : conditions) {
if (!condition.status().has_value()) {
return fuchsia_driver_framework::HealthStatus::kUnhealthy;
}
switch (*condition.status()) {
case fuchsia_driver_framework::HealthStatus::kOk:
break;
case fuchsia_driver_framework::HealthStatus::kDegraded:
overall = fuchsia_driver_framework::HealthStatus::kDegraded;
break;
case fuchsia_driver_framework::HealthStatus::kUnhealthy:
return fuchsia_driver_framework::HealthStatus::kUnhealthy;
}
}
return overall;
}
// Derives the overall `HealthStatus` (`kUnhealthy > kDegraded > kOk`) of `response` from its
// `conditions` list, or `kOk` if `conditions` is absent or empty.
inline fuchsia_driver_framework::HealthStatus OverallHealthStatus(
const fuchsia_driver_framework::HealthCheckResponse& response) {
if (!response.conditions().has_value()) {
return fuchsia_driver_framework::HealthStatus::kOk;
}
return OverallHealthStatus(*response.conditions());
}
// Returns a pointer to the first condition in `conditions` whose `reason_code` equals
// `reason_code`, or `nullptr` if none matches.
inline const fuchsia_driver_framework::HealthCondition* FindCondition(
cpp20::span<const fuchsia_driver_framework::HealthCondition> conditions,
std::string_view reason_code) {
for (const auto& condition : conditions) {
if (condition.reason_code().has_value() && *condition.reason_code() == reason_code) {
return &condition;
}
}
return nullptr;
}
// Returns a pointer to the first condition in `response.conditions()` whose `reason_code` equals
// `reason_code`, or `nullptr` if `conditions` is absent or no condition matches.
inline const fuchsia_driver_framework::HealthCondition* FindCondition(
const fuchsia_driver_framework::HealthCheckResponse& response, std::string_view reason_code) {
if (!response.conditions().has_value()) {
return nullptr;
}
return FindCondition(*response.conditions(), reason_code);
}
// Returns a pointer to the `HealthDiagnosticValue` for the first item in `items` with `key`, or
// `nullptr` if not found.
inline const fuchsia_driver_framework::HealthDiagnosticValue* FindDiagnostic(
cpp20::span<const fuchsia_driver_framework::HealthDiagnosticItem> items, std::string_view key) {
for (const auto& item : items) {
if (item.key() == key) {
return &item.value();
}
}
return nullptr;
}
inline const fuchsia_driver_framework::HealthDiagnosticValue* FindDiagnostic(
const fuchsia_driver_framework::HealthCheckResponse& response, std::string_view key) {
if (!response.diagnostics().has_value()) {
return nullptr;
}
return FindDiagnostic(*response.diagnostics(), key);
}
inline const fuchsia_driver_framework::HealthDiagnosticValue* FindDiagnostic(
const fuchsia_driver_framework::HealthCondition& condition, std::string_view key) {
if (!condition.diagnostics().has_value()) {
return nullptr;
}
return FindDiagnostic(*condition.diagnostics(), key);
}
inline std::optional<bool> GetDiagnosticBool(
cpp20::span<const fuchsia_driver_framework::HealthDiagnosticItem> items, std::string_view key) {
const auto* val = FindDiagnostic(items, key);
if (val != nullptr && val->bool_value().has_value()) {
return val->bool_value().value();
}
return std::nullopt;
}
inline std::optional<bool> GetDiagnosticBool(
const fuchsia_driver_framework::HealthCheckResponse& response, std::string_view key) {
if (!response.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticBool(*response.diagnostics(), key);
}
inline std::optional<bool> GetDiagnosticBool(
const fuchsia_driver_framework::HealthCondition& condition, std::string_view key) {
if (!condition.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticBool(*condition.diagnostics(), key);
}
inline std::optional<uint64_t> GetDiagnosticUint(
cpp20::span<const fuchsia_driver_framework::HealthDiagnosticItem> items, std::string_view key) {
const auto* val = FindDiagnostic(items, key);
if (val != nullptr && val->uint_value().has_value()) {
return val->uint_value().value();
}
return std::nullopt;
}
inline std::optional<uint64_t> GetDiagnosticUint(
const fuchsia_driver_framework::HealthCheckResponse& response, std::string_view key) {
if (!response.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticUint(*response.diagnostics(), key);
}
inline std::optional<uint64_t> GetDiagnosticUint(
const fuchsia_driver_framework::HealthCondition& condition, std::string_view key) {
if (!condition.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticUint(*condition.diagnostics(), key);
}
inline std::optional<int64_t> GetDiagnosticInt(
cpp20::span<const fuchsia_driver_framework::HealthDiagnosticItem> items, std::string_view key) {
const auto* val = FindDiagnostic(items, key);
if (val != nullptr && val->int_value().has_value()) {
return val->int_value().value();
}
return std::nullopt;
}
inline std::optional<int64_t> GetDiagnosticInt(
const fuchsia_driver_framework::HealthCheckResponse& response, std::string_view key) {
if (!response.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticInt(*response.diagnostics(), key);
}
inline std::optional<int64_t> GetDiagnosticInt(
const fuchsia_driver_framework::HealthCondition& condition, std::string_view key) {
if (!condition.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticInt(*condition.diagnostics(), key);
}
// The returned view borrows from `items`; it is only valid while the diagnostics it was
// read from are alive.
inline std::optional<std::string_view> GetDiagnosticString(
cpp20::span<const fuchsia_driver_framework::HealthDiagnosticItem> items, std::string_view key) {
const auto* val = FindDiagnostic(items, key);
if (val != nullptr && val->string_value().has_value()) {
return std::string_view(val->string_value().value());
}
return std::nullopt;
}
inline std::optional<std::string_view> GetDiagnosticString(
const fuchsia_driver_framework::HealthCheckResponse& response, std::string_view key) {
if (!response.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticString(*response.diagnostics(), key);
}
inline std::optional<std::string_view> GetDiagnosticString(
const fuchsia_driver_framework::HealthCondition& condition, std::string_view key) {
if (!condition.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticString(*condition.diagnostics(), key);
}
inline std::optional<zx::time_boot> GetDiagnosticTimestamp(
cpp20::span<const fuchsia_driver_framework::HealthDiagnosticItem> items, std::string_view key) {
const auto* val = FindDiagnostic(items, key);
if (val != nullptr && val->timestamp().has_value()) {
return val->timestamp().value();
}
return std::nullopt;
}
inline std::optional<zx::time_boot> GetDiagnosticTimestamp(
const fuchsia_driver_framework::HealthCheckResponse& response, std::string_view key) {
if (!response.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticTimestamp(*response.diagnostics(), key);
}
inline std::optional<zx::time_boot> GetDiagnosticTimestamp(
const fuchsia_driver_framework::HealthCondition& condition, std::string_view key) {
if (!condition.diagnostics().has_value()) {
return std::nullopt;
}
return GetDiagnosticTimestamp(*condition.diagnostics(), key);
}
} // namespace fdf_testing
#endif // LIB_DRIVER_TESTING_CPP_HEALTH_TEST_UTILS_H_