// 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
