// 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 <fuchsia/kernel/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/executor.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/spawn.h>
#include <lib/inspect/cpp/reader.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/syslog/cpp/log_settings.h>
#include <lib/vfs/cpp/vmo_file.h>

#include <gtest/gtest.h>

#include "src/lib/files/file.h"
#include "src/lib/files/glob.h"
#include "src/lib/fxl/strings/split_string.h"
#include "src/lib/fxl/strings/substitute.h"

namespace {

// Confirm we can connect via FIDL to the real environment service
// fuchsia.kernel.Counter and retrieve something.
TEST(KcounterInspectIntegrationTest, FidlConnection) {
  fuchsia::kernel::CounterSyncPtr kcounter;
  auto environment_services = ::sys::ServiceDirectory::CreateFromNamespace();
  environment_services->Connect(kcounter.NewRequest());

  fuchsia::mem::Buffer buffer;
  zx_status_t status;
  ASSERT_TRUE(kcounter->GetInspectVmo(&status, &buffer) == ZX_OK);
  ASSERT_TRUE(status == ZX_OK);
}

std::vector<std::string> ToString(const inspect::Hierarchy& root, const std::string& indent = "") {
  std::vector<std::string> result;
  result.push_back(indent + root.name());
  for (const auto& prop : root.node().properties()) {
    result.push_back(indent + "  " + prop.name());
  }
  for (const auto& child : root.children()) {
    auto child_result = ToString(child, indent + "  ");
    result.insert(result.end(), child_result.begin(), child_result.end());
  }
  return result;
}

bool Contains(const std::vector<std::string>& vec, const std::string& look_for) {
  for (const auto& v : vec) {
    if (v == look_for) {
      return true;
    }
  }
  return false;
}

TEST(KcounterInspectIntegrationTest, InspectReading) {
  fuchsia::kernel::CounterSyncPtr kcounter;
  auto environment_services = ::sys::ServiceDirectory::CreateFromNamespace();
  environment_services->Connect(kcounter.NewRequest());

  fuchsia::mem::Buffer buffer;
  zx_status_t status;
  ASSERT_TRUE(kcounter->GetInspectVmo(&status, &buffer) == ZX_OK);
  ASSERT_TRUE(status == ZX_OK);

  auto result = inspect::ReadFromVmo(buffer.vmo);
  ASSERT_TRUE(result.is_ok());
  auto object_hierarchy = result.take_value();
  auto as_vector = ToString(object_hierarchy);
  EXPECT_TRUE(Contains(as_vector, "  handles"));
  EXPECT_TRUE(Contains(as_vector, "    handles.duped"));
  EXPECT_TRUE(Contains(as_vector, "    handles.live"));
  EXPECT_TRUE(Contains(as_vector, "    handles.made"));
  EXPECT_TRUE(Contains(as_vector, "        init.userboot.time.msec"));

  // There's no particular guarantee on update frequency, but at least ensure we
  // can call the update function, and that the VMO is readable after doing so.
  ASSERT_TRUE(kcounter->UpdateInspectVmo(&status) == ZX_OK);
  ASSERT_TRUE(status == ZX_OK);

  result = inspect::ReadFromVmo(buffer.vmo);
  ASSERT_TRUE(result.is_ok());
  object_hierarchy = result.take_value();
  as_vector = ToString(object_hierarchy);
  EXPECT_TRUE(Contains(as_vector, "  handles"));
  EXPECT_TRUE(Contains(as_vector, "    handles.duped"));
  EXPECT_TRUE(Contains(as_vector, "    handles.live"));
  EXPECT_TRUE(Contains(as_vector, "    handles.made"));
  EXPECT_TRUE(Contains(as_vector, "        init.userboot.time.msec"));
}

}  // namespace
