// Copyright 2018 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 "peridot/bin/ledger/app/ledger_repository_factory_impl.h"

#include <fuchsia/inspect/cpp/fidl.h>
#include <lib/callback/capture.h>
#include <lib/callback/set_when_called.h>
#include <lib/fsl/io/fd.h>
#include <lib/fxl/files/directory.h>
#include <lib/fxl/files/unique_fd.h>
#include <lib/fxl/strings/string_view.h>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "peridot/bin/ledger/app/constants.h"
#include "peridot/bin/ledger/testing/inspect.h"
#include "peridot/bin/ledger/testing/test_with_environment.h"
#include "peridot/lib/scoped_tmpfs/scoped_tmpfs.h"

namespace ledger {
namespace {

using ::testing::ElementsAre;
using ::testing::IsEmpty;
using ::testing::Not;
using ::testing::SizeIs;
using ::testing::UnorderedElementsAre;

constexpr fxl::StringView kObjectsName = "test objects";
constexpr fxl::StringView kUserID = "test user ID";

class LedgerRepositoryFactoryImplTest : public TestWithEnvironment {
 public:
  LedgerRepositoryFactoryImplTest() {
    object_dir_ =
        component::ObjectDir::Make({kObjectsName.data(), kObjectsName.size()});
    repository_factory_ = std::make_unique<LedgerRepositoryFactoryImpl>(
        &environment_, nullptr, object_dir_);
    object_dir_.set_children_callback(
        {kRepositoriesInspectPathComponent},
        [this](component::Object::ObjectVector* out) {
          repository_factory_->GetChildren(out);
        });
  }

  ~LedgerRepositoryFactoryImplTest() override {
    object_dir_.set_children_callback({kRepositoriesInspectPathComponent},
                                      nullptr);
  }

 protected:
  ::testing::AssertionResult CreateDirectory(std::string name);
  ::testing::AssertionResult CallGetRepository(
      std::string name,
      ledger_internal::LedgerRepositoryPtr* ledger_repository_ptr);
  ::testing::AssertionResult ReadTopLevelData(fuchsia::inspect::Object* object);
  ::testing::AssertionResult ListTopLevelChildren(
      std::vector<std::string>* children);
  ::testing::AssertionResult OpenTopLevelRepositoriesChild(
      fuchsia::inspect::InspectPtr* repositories_inspect_ptr);
  ::testing::AssertionResult ReadData(fuchsia::inspect::InspectPtr* inspect_ptr,
                                      fuchsia::inspect::Object* object);
  ::testing::AssertionResult ListChildren(
      fuchsia::inspect::InspectPtr* inspect_ptr,
      std::vector<std::string>* children_names);
  ::testing::AssertionResult OpenChild(
      fuchsia::inspect::InspectPtr* parent_inspect_ptr,
      std::string child_name,
      fuchsia::inspect::InspectPtr* child_inspect_ptr);

  scoped_tmpfs::ScopedTmpFS tmpfs_;
  component::ObjectDir object_dir_;
  std::unique_ptr<LedgerRepositoryFactoryImpl> repository_factory_;

 private:
  FXL_DISALLOW_COPY_AND_ASSIGN(LedgerRepositoryFactoryImplTest);
};

::testing::AssertionResult LedgerRepositoryFactoryImplTest::CreateDirectory(
    std::string name) {
  if (!files::CreateDirectoryAt(tmpfs_.root_fd(), name)) {
    return ::testing::AssertionFailure()
           << "Failed to create directory \"" << name << "\"!";
  }
  return ::testing::AssertionSuccess();
}

::testing::AssertionResult LedgerRepositoryFactoryImplTest::CallGetRepository(
    std::string name,
    ledger_internal::LedgerRepositoryPtr* ledger_repository_ptr) {
  fxl::UniqueFD fd(openat(tmpfs_.root_fd(), name.c_str(), O_PATH));
  if (!fd.is_valid()) {
    return ::testing::AssertionFailure()
           << "Failed to validate directory \"" << name << "\"!";
  }

  bool callback_called;
  Status status = Status::UNKNOWN_ERROR;

  repository_factory_->GetRepository(
      fsl::CloneChannelFromFileDescriptor(fd.get()), nullptr,
      kUserID.ToString(), ledger_repository_ptr->NewRequest(),
      callback::Capture(callback::SetWhenCalled(&callback_called), &status));

  if (!callback_called) {
    return ::testing::AssertionFailure()
           << "Callback passed to GetRepository not called!";
  }
  if (status != Status::OK) {
    return ::testing::AssertionFailure() << "Status of GetRepository call was "
                                         << static_cast<int32_t>(status) << "!";
  }
  return ::testing::AssertionSuccess();
}

::testing::AssertionResult LedgerRepositoryFactoryImplTest::ReadTopLevelData(
    fuchsia::inspect::Object* object) {
  bool callback_called;

  object_dir_.object()->ReadData(
      callback::Capture(callback::SetWhenCalled(&callback_called), object));
  RunLoopUntilIdle();

  if (!callback_called) {
    return ::testing::AssertionFailure()
           << "Callback passed to object_dir_.object()->ReadData not called!";
  }
  return ::testing::AssertionSuccess();
}

::testing::AssertionResult
LedgerRepositoryFactoryImplTest::ListTopLevelChildren(
    std::vector<std::string>* children) {
  bool callback_called;

  object_dir_.object()->ListChildren(
      callback::Capture(callback::SetWhenCalled(&callback_called), children));
  RunLoopUntilIdle();

  if (!callback_called) {
    return ::testing::AssertionFailure()
           << "Callback passed to object_dir_.object()->ListChildren not "
              "called!";
  }
  return ::testing::AssertionSuccess();
}

::testing::AssertionResult
LedgerRepositoryFactoryImplTest::OpenTopLevelRepositoriesChild(
    fuchsia::inspect::InspectPtr* repositories_inspect_ptr) {
  bool callback_called;
  bool success = false;

  object_dir_.object()->OpenChild(
      kRepositoriesInspectPathComponent, repositories_inspect_ptr->NewRequest(),
      callback::Capture(callback::SetWhenCalled(&callback_called), &success));
  RunLoopUntilIdle();

  if (!callback_called) {
    return ::testing::AssertionFailure()
           << "Callback passed to object_dir_.object()->OpenChild not called!";
  }
  if (!success) {
    return ::testing::AssertionFailure()
           << "object_dir_.object()->OpenChild call unsuccessful!";
  }
  return ::testing::AssertionSuccess();
}

::testing::AssertionResult LedgerRepositoryFactoryImplTest::ReadData(
    fuchsia::inspect::InspectPtr* inspect_ptr,
    fuchsia::inspect::Object* object) {
  bool callback_called;

  (*inspect_ptr)
      ->ReadData(
          callback::Capture(callback::SetWhenCalled(&callback_called), object));
  RunLoopUntilIdle();

  if (!callback_called) {
    return ::testing::AssertionFailure() << "ReadData callback not called!";
  }
  return ::testing::AssertionSuccess();
}

::testing::AssertionResult LedgerRepositoryFactoryImplTest::ListChildren(
    fuchsia::inspect::InspectPtr* inspect_ptr,
    std::vector<std::string>* children_names) {
  bool callback_called;

  (*inspect_ptr)
      ->ListChildren(callback::Capture(
          callback::SetWhenCalled(&callback_called), children_names));
  RunLoopUntilIdle();

  if (!callback_called) {
    return ::testing::AssertionFailure() << "ListChildren callback not called!";
  }
  return ::testing::AssertionSuccess();
}

::testing::AssertionResult LedgerRepositoryFactoryImplTest::OpenChild(
    fuchsia::inspect::InspectPtr* parent_inspect_ptr,
    std::string child_name,
    fuchsia::inspect::InspectPtr* child_inspect_ptr) {
  bool callback_called;
  bool success = false;

  (*parent_inspect_ptr)
      ->OpenChild(child_name, child_inspect_ptr->NewRequest(),
                  callback::Capture(callback::SetWhenCalled(&callback_called),
                                    &success));
  RunLoopUntilIdle();

  if (!callback_called) {
    return ::testing::AssertionFailure() << "OpenChild callback not called!";
  }
  if (!success) {
    return ::testing::AssertionFailure() << "OpenChild call unsuccessful!";
  }
  return ::testing::AssertionSuccess();
}

TEST_F(LedgerRepositoryFactoryImplTest, InspectAPINoRepositories) {
  fuchsia::inspect::Object object;
  std::vector<std::string> children;

  ASSERT_TRUE(ReadTopLevelData(&object));
  ASSERT_TRUE(ListTopLevelChildren(&children));

  EXPECT_EQ(kObjectsName, object.name);
  EXPECT_THAT(*object.properties, IsEmpty());
  EXPECT_THAT(*object.metrics, IsEmpty());
  EXPECT_THAT(children, ElementsAre(kRepositoriesInspectPathComponent));
}

TEST_F(LedgerRepositoryFactoryImplTest,
       InspectAPITwoRepositoriesOneAccessedTwice) {
  // The directories in which the two repositories will be created.
  std::string first_directory = "first directory";
  std::string second_directory = "second directory";

  // The names of the two repositories, determined by the
  // LedgerRepositoryFactoryImpl under test.
  fidl::StringPtr first_repository_name;
  fidl::StringPtr second_repository_name;

  // Bindings to the two repositories. If these are not maintained, the
  // LedgerRepositoryFactoryImpl::LedgerRepositoryContainer objects associated
  // with the repositories will be destroyed and the repositories will no
  // longer appear represented in the Inspect API.
  ledger_internal::LedgerRepositoryPtr first_ledger_repository_ptr;
  ledger_internal::LedgerRepositoryPtr second_ledger_repository_ptr;
  ledger_internal::LedgerRepositoryPtr first_again_ledger_repository_ptr;

  // Bindings to Inspect API "Inspect" objects. Because the Ledger objects'
  // parent-child relationships are dynamically computed, these need to be
  // unbound and rebound for each inspection of the repositories.
  fuchsia::inspect::InspectPtr repositories_inspect_ptr;
  fuchsia::inspect::InspectPtr first_repository_inspect_ptr;
  fuchsia::inspect::InspectPtr second_repository_inspect_ptr;

  // Temporary objects populated and cleared throughout the test.
  fuchsia::inspect::Object object;
  std::vector<std::string> children_names;

  // Create the directories for the repositories.
  ASSERT_TRUE(CreateDirectory(first_directory));
  ASSERT_TRUE(CreateDirectory(second_directory));

  // Request one repository, then query the object_dir_ (and its children) to
  // verify that that repository is listed (and to learn the name under which
  // it is listed) and that it was requested once.
  ASSERT_TRUE(CallGetRepository(first_directory, &first_ledger_repository_ptr));
  ASSERT_TRUE(ListTopLevelChildren(&children_names));
  EXPECT_THAT(children_names, ElementsAre(kRepositoriesInspectPathComponent));
  ASSERT_TRUE(OpenTopLevelRepositoriesChild(&repositories_inspect_ptr));
  ASSERT_TRUE(ListChildren(&repositories_inspect_ptr, &children_names));
  EXPECT_THAT(children_names, SizeIs(1));
  first_repository_name = children_names.at(0);
  EXPECT_THAT(*first_repository_name, Not(IsEmpty()));
  ASSERT_TRUE(OpenChild(&repositories_inspect_ptr, first_repository_name,
                        &first_repository_inspect_ptr));
  ASSERT_TRUE(ReadData(&first_repository_inspect_ptr, &object));
  EXPECT_EQ(first_repository_name, object.name);
  ExpectRequestsMetric(&object, 1UL);

  // Request a second repository, then query the "repositories" Inspect object
  // to verify that that second repository is listed in addition to the first
  // (and to learn the name under which it is listed) and that the two
  // repositories were each requested once.
  ASSERT_TRUE(
      CallGetRepository(second_directory, &second_ledger_repository_ptr));
  ASSERT_TRUE(ListTopLevelChildren(&children_names));
  EXPECT_THAT(children_names, ElementsAre(kRepositoriesInspectPathComponent));
  ASSERT_TRUE(OpenTopLevelRepositoriesChild(&repositories_inspect_ptr));
  ASSERT_TRUE(ListChildren(&repositories_inspect_ptr, &children_names));
  EXPECT_THAT(children_names, SizeIs(2));
  second_repository_name =
      *find_if_not(children_names.begin(), children_names.end(),
                   [&first_repository_name](const auto& name) {
                     return name == first_repository_name;
                   });
  EXPECT_THAT(children_names, UnorderedElementsAre(first_repository_name,
                                                    second_repository_name));
  EXPECT_THAT(*second_repository_name, Not(IsEmpty()));
  ASSERT_TRUE(OpenChild(&repositories_inspect_ptr, first_repository_name,
                        &first_repository_inspect_ptr));
  ASSERT_TRUE(OpenChild(&repositories_inspect_ptr, second_repository_name,
                        &second_repository_inspect_ptr));
  ASSERT_TRUE(ReadData(&first_repository_inspect_ptr, &object));
  EXPECT_EQ(first_repository_name, object.name);
  ExpectRequestsMetric(&object, 1UL);
  ASSERT_TRUE(ReadData(&second_repository_inspect_ptr, &object));
  EXPECT_EQ(second_repository_name, object.name);
  ExpectRequestsMetric(&object, 1UL);

  // Request the first repository a second time, then query the "repositories"
  // Inspect object to verify that both repositories remain listed (with their
  // same names) and are described as having been requested twice and once,
  // respectively.
  ASSERT_TRUE(
      CallGetRepository(first_directory, &first_again_ledger_repository_ptr));
  ASSERT_TRUE(ListTopLevelChildren(&children_names));
  EXPECT_THAT(children_names, ElementsAre(kRepositoriesInspectPathComponent));
  ASSERT_TRUE(OpenTopLevelRepositoriesChild(&repositories_inspect_ptr));
  ASSERT_TRUE(ListChildren(&repositories_inspect_ptr, &children_names));
  EXPECT_THAT(children_names, UnorderedElementsAre(first_repository_name,
                                                    second_repository_name));
  ASSERT_TRUE(OpenChild(&repositories_inspect_ptr, first_repository_name,
                        &first_repository_inspect_ptr));
  ASSERT_TRUE(OpenChild(&repositories_inspect_ptr, second_repository_name,
                        &second_repository_inspect_ptr));
  ASSERT_TRUE(ReadData(&first_repository_inspect_ptr, &object));
  EXPECT_EQ(first_repository_name, object.name);
  ExpectRequestsMetric(&object, 2UL);
  ASSERT_TRUE(ReadData(&second_repository_inspect_ptr, &object));
  EXPECT_EQ(second_repository_name, object.name);
  ExpectRequestsMetric(&object, 1UL);
}

}  // namespace
}  // namespace ledger
