// Copyright 2020 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 "build_info.h"

#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/namespace.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/gtest/test_loop_fixture.h>
#include <lib/sys/cpp/testing/component_context_provider.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/vfs/cpp/pseudo_dir.h>
#include <lib/vfs/cpp/pseudo_file.h>
#include <zircon/status.h>

namespace {
const char kFuchsiaBuildInfoDirectoryPath[] = "/config/build-info";

const char kProductFileName[] = "product";
const char kBoardFileName[] = "board";
const char kVersionFileName[] = "version";
const char kLastCommitDateFileName[] = "latest-commit-date";
}  // namespace

class BuildInfoServiceInstance {
 public:
  explicit BuildInfoServiceInstance(std::unique_ptr<sys::ComponentContext> context) {
    context_ = std::move(context);
    binding_ = std::make_unique<fidl::Binding<fuchsia::buildinfo::Provider>>(&impl_);
    fidl::InterfaceRequestHandler<fuchsia::buildinfo::Provider> handler =
        [&](fidl::InterfaceRequest<fuchsia::buildinfo::Provider> request) {
          binding_->Bind(std::move(request));
        };
    context_->outgoing()->AddPublicService(std::move(handler));
  }

 private:
  ProviderImpl impl_;
  std::unique_ptr<fidl::Binding<fuchsia::buildinfo::Provider>> binding_;
  std::unique_ptr<sys::ComponentContext> context_;
};

class BuildInfoServiceTestFixture : public gtest::TestLoopFixture {
 public:
  BuildInfoServiceTestFixture() : loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {}

  void SetUp() override {
    TestLoopFixture::SetUp();
    build_info_service_instance_.reset(new BuildInfoServiceInstance(provider_.TakeContext()));

    loop_.StartThread();

    // Create a channel.
    zx_handle_t endpoint0;
    zx_handle_t endpoint1;
    zx_status_t status = zx_channel_create(0, &endpoint0, &endpoint1);
    ZX_ASSERT_MSG(status == ZX_OK, "Cannot create channel: %s\n", zx_status_get_string(status));

    // Get the process's namespace.
    fdio_ns_t *ns;
    status = fdio_ns_get_installed(&ns);
    ZX_ASSERT_MSG(status == ZX_OK, "Cannot get namespace: %s\n", zx_status_get_string(status));

    // Create the /config/build-info path in the namespace.
    std::string build_info_directory_path(kFuchsiaBuildInfoDirectoryPath);
    status = fdio_ns_bind(ns, build_info_directory_path.c_str(), endpoint0);
    ZX_ASSERT_MSG(status == ZX_OK, "Cannot bind %s to namespace: %s\n",
                  build_info_directory_path.c_str(), zx_status_get_string(status));

    // Connect the build-info PseudoDir to the /config/build-info path.
    zx::channel channel(endpoint1);
    build_info_directory_.Serve(
        fuchsia::io::OpenFlags::RIGHT_READABLE | fuchsia::io::OpenFlags::RIGHT_WRITABLE,
        std::move(channel), loop_.dispatcher());
  }

  // Creates a PsuedoDir named |build_info_filename| in the PsuedoDir "/config/build-info" in
  // the component's namespace. The file contains |build_info_filename| followed optionally by
  // a trailing newline.
  void CreateBuildInfoFile(std::string build_info_filename, bool with_trailing_newline = true) {
    std::string file_contents(build_info_filename);

    // Some build info files contain a trailing newline which the build info service strips.
    // Optionally add a trailing newline to test the trailing whitespace stripping.
    if (with_trailing_newline) {
      file_contents.append("\n");
    }

    vfs::PseudoFile::ReadHandler versionFileReadFn = [file_contents](std::vector<uint8_t> *output,
                                                                     size_t max_file_size) {
      output->resize(file_contents.length());
      std::copy(file_contents.begin(), file_contents.end(), output->begin());
      return ZX_OK;
    };
    vfs::PseudoFile::WriteHandler versionFileWriteFn;

    // Create a PseudoFile.
    std::unique_ptr<vfs::PseudoFile> pseudo_file = std::make_unique<vfs::PseudoFile>(
        file_contents.length(), std::move(versionFileReadFn), std::move(versionFileWriteFn));

    // Add the file to the build-info PseudoDir.
    build_info_directory_.AddEntry(std::move(build_info_filename), std::move(pseudo_file));
  }

  void TearDown() override {
    TestLoopFixture::TearDown();
    build_info_service_instance_.reset();
    DestroyBuildInfoFile();
  }

 protected:
  fuchsia::buildinfo::ProviderPtr GetProxy() {
    fuchsia::buildinfo::ProviderPtr provider;
    provider_.ConnectToPublicService(provider.NewRequest());
    return provider;
  }

 private:
  void DestroyBuildInfoFile() {
    fdio_ns_t *ns;
    zx_status_t status = fdio_ns_get_installed(&ns);
    ZX_ASSERT_MSG(status == ZX_OK, "Cannot retrieve the namespace: %s\n",
                  zx_status_get_string(status));

    std::string build_info_directory_path(kFuchsiaBuildInfoDirectoryPath);
    status = fdio_ns_unbind(ns, build_info_directory_path.c_str());
    ZX_ASSERT_MSG(status == ZX_OK, "Cannot unbind from a namespace: %s\n",
                  zx_status_get_string(status));

    loop_.Quit();
    loop_.JoinThreads();
  }

  std::unique_ptr<BuildInfoServiceInstance> build_info_service_instance_;
  sys::testing::ComponentContextProvider provider_;
  vfs::PseudoDir build_info_directory_;
  async::Loop loop_;
};

TEST_F(BuildInfoServiceTestFixture, BuildInfo) {
  CreateBuildInfoFile(kProductFileName);
  CreateBuildInfoFile(kBoardFileName);
  CreateBuildInfoFile(kVersionFileName);
  CreateBuildInfoFile(kLastCommitDateFileName);

  fuchsia::buildinfo::ProviderPtr proxy = GetProxy();
  proxy->GetBuildInfo([&](const fuchsia::buildinfo::BuildInfo &response) {
    EXPECT_TRUE(response.has_product_config());
    EXPECT_EQ(response.product_config(), kProductFileName);
    EXPECT_TRUE(response.has_board_config());
    EXPECT_EQ(response.board_config(), kBoardFileName);
    EXPECT_TRUE(response.has_version());
    EXPECT_EQ(response.version(), kVersionFileName);
    EXPECT_TRUE(response.has_latest_commit_date());
    EXPECT_EQ(response.latest_commit_date(), kLastCommitDateFileName);
  });

  RunLoopUntilIdle();
}

TEST_F(BuildInfoServiceTestFixture, EmptyBuildInfo) {
  CreateBuildInfoFile("");
  CreateBuildInfoFile("");
  CreateBuildInfoFile("");
  CreateBuildInfoFile("");

  fuchsia::buildinfo::ProviderPtr proxy = GetProxy();
  proxy->GetBuildInfo([&](const fuchsia::buildinfo::BuildInfo &response) {
    EXPECT_FALSE(response.has_product_config());
    EXPECT_FALSE(response.has_board_config());
    EXPECT_FALSE(response.has_version());
    EXPECT_FALSE(response.has_latest_commit_date());
  });

  RunLoopUntilIdle();
}

TEST_F(BuildInfoServiceTestFixture, NonPresentBuildInfo) {
  fuchsia::buildinfo::ProviderPtr proxy = GetProxy();
  proxy->GetBuildInfo([&](const fuchsia::buildinfo::BuildInfo &response) {
    EXPECT_FALSE(response.has_product_config());
    EXPECT_FALSE(response.has_board_config());
    EXPECT_FALSE(response.has_version());
    EXPECT_FALSE(response.has_latest_commit_date());
  });

  RunLoopUntilIdle();
}
