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

#include "src/lib/testing/loop_fixture/test_loop_fixture.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();
}
