blob: dbc948a653cdc26f84f62abf1ee4f69e7104d4b2 [file] [log] [blame]
// Copyright 2019 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.
#include <lib/inspect/cpp/health.h>
#include <lib/inspect/cpp/reader.h>
#include <zxtest/zxtest.h>
#include "lib/inspect/cpp/hierarchy.h"
namespace {
// Example:
// auto* value = GetPropertyValue<inspect::StringPropertyValue>(node, "name");
template <class T>
const T* GetPropertyValue(const inspect::NodeValue& node, const std::string& name) {
for (const auto& property : node.properties()) {
if (property.name() == name && property.Contains<T>()) {
return &property.Get<T>();
}
}
return nullptr;
}
bool ContainsProperty(const inspect::NodeValue& node, const std::string& name) {
for (const auto& property : node.properties()) {
if (property.name() == name) {
return true;
}
}
return false;
}
TEST(InspectHealth, Default) {
auto inspector = inspect::Inspector();
auto health = inspect::NodeHealth(&inspector.GetRoot(), []() -> zx_time_t { return 42; });
auto hierarchy = inspect::ReadFromVmo(inspector.DuplicateVmo()).take_value();
const auto* health_subtree = hierarchy.GetByPath({inspect::kHealthNodeName});
ASSERT_TRUE(health_subtree != nullptr);
EXPECT_STREQ(inspect::kHealthNodeName, health_subtree->name().c_str());
const auto* status =
GetPropertyValue<inspect::StringPropertyValue>(health_subtree->node(), "status");
ASSERT_TRUE(status != nullptr);
ASSERT_FALSE(ContainsProperty(health_subtree->node(), "message"));
EXPECT_STREQ(inspect::kHealthStartingUp, status->value().c_str());
const auto* start_time =
GetPropertyValue<inspect::IntPropertyValue>(health_subtree->node(), "start_timestamp_nanos");
ASSERT_TRUE(status != nullptr);
EXPECT_EQ(42L, start_time->value());
}
TEST(InspectHealth, Ok) {
auto inspector = inspect::Inspector();
auto health = inspect::NodeHealth(&inspector.GetRoot());
health.Ok();
const auto hierarchy = inspect::ReadFromVmo(inspector.DuplicateVmo()).take_value();
const auto* health_subtree = hierarchy.GetByPath({inspect::kHealthNodeName});
ASSERT_TRUE(health_subtree != nullptr);
EXPECT_STREQ(inspect::kHealthNodeName, health_subtree->name().c_str());
const auto* status =
GetPropertyValue<inspect::StringPropertyValue>(health_subtree->node(), "status");
ASSERT_TRUE(status != nullptr);
ASSERT_FALSE(ContainsProperty(health_subtree->node(), "message"));
EXPECT_STREQ(inspect::kHealthOk, status->value().c_str());
}
TEST(InspectHealth, UnhealthyToStartingUp) {
auto inspector = inspect::Inspector();
auto health = inspect::NodeHealth(&inspector.GetRoot());
health.Unhealthy("test");
health.StartingUp();
const auto hierarchy = inspect::ReadFromVmo(inspector.DuplicateVmo()).take_value();
const auto* health_subtree = hierarchy.GetByPath({inspect::kHealthNodeName});
ASSERT_TRUE(health_subtree != nullptr);
EXPECT_STREQ(inspect::kHealthNodeName, health_subtree->name().c_str());
const auto* status =
GetPropertyValue<inspect::StringPropertyValue>(health_subtree->node(), "status");
ASSERT_TRUE(status != nullptr);
ASSERT_FALSE(ContainsProperty(health_subtree->node(), "message"));
EXPECT_STREQ(inspect::kHealthStartingUp, status->value().c_str());
}
TEST(InspectHealth, Unhealthy) {
auto inspector = inspect::Inspector();
auto health = inspect::NodeHealth(&inspector.GetRoot());
health.Unhealthy("test");
auto hierarchy = inspect::ReadFromVmo(inspector.DuplicateVmo()).take_value();
const auto* health_subtree = hierarchy.GetByPath({inspect::kHealthNodeName});
ASSERT_TRUE(health_subtree != nullptr);
EXPECT_STREQ(inspect::kHealthNodeName, health_subtree->name().c_str());
const auto* status =
GetPropertyValue<inspect::StringPropertyValue>(health_subtree->node(), "status");
const auto* message =
GetPropertyValue<inspect::StringPropertyValue>(health_subtree->node(), "message");
ASSERT_TRUE(status != nullptr);
ASSERT_TRUE(message != nullptr);
EXPECT_STREQ(inspect::kHealthUnhealthy, status->value().c_str());
EXPECT_STREQ("test", message->value().c_str());
}
TEST(InspectHealth, StartingUpReason) {
auto inspector = inspect::Inspector();
auto health = inspect::NodeHealth(&inspector.GetRoot());
health.StartingUp("test");
auto hierarchy = inspect::ReadFromVmo(inspector.DuplicateVmo()).take_value();
const auto* health_subtree = hierarchy.GetByPath({inspect::kHealthNodeName});
ASSERT_TRUE(health_subtree != nullptr);
EXPECT_STREQ(inspect::kHealthNodeName, health_subtree->name().c_str());
const auto* status =
GetPropertyValue<inspect::StringPropertyValue>(health_subtree->node(), "status");
const auto* message =
GetPropertyValue<inspect::StringPropertyValue>(health_subtree->node(), "message");
ASSERT_TRUE(status != nullptr);
ASSERT_TRUE(message != nullptr);
EXPECT_STREQ(inspect::kHealthStartingUp, status->value().c_str());
EXPECT_STREQ("test", message->value().c_str());
}
TEST(InspectHealth, CustomMessage) {
auto inspector = inspect::Inspector();
auto health = inspect::NodeHealth(&inspector.GetRoot());
health.SetStatus("BAD CONFIG", "test");
auto hierarchy = inspect::ReadFromVmo(inspector.DuplicateVmo()).take_value();
const auto* health_subtree = hierarchy.GetByPath({inspect::kHealthNodeName});
ASSERT_TRUE(health_subtree != nullptr);
EXPECT_STREQ(inspect::kHealthNodeName, health_subtree->name().c_str());
const auto* status =
GetPropertyValue<inspect::StringPropertyValue>(health_subtree->node(), "status");
const auto* message =
GetPropertyValue<inspect::StringPropertyValue>(health_subtree->node(), "message");
ASSERT_TRUE(status != nullptr);
ASSERT_TRUE(message != nullptr);
EXPECT_STREQ("BAD CONFIG", status->value().c_str());
EXPECT_STREQ("test", message->value().c_str());
}
} // namespace