// Copyright 2016 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 <string.h>

#include <fuchsia/ledger/internal/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/callback/capture.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fidl/cpp/synchronous_interface_ptr.h>
#include <lib/fit/function.h>
#include <lib/fsl/io/fd.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/fxl/files/directory.h>
#include <lib/fxl/files/file.h>
#include <lib/gtest/real_loop_fixture.h>
#include <lib/svc/cpp/services.h>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "peridot/bin/ledger/app/serialization_version.h"
#include "peridot/bin/ledger/fidl/include/types.h"
#include "peridot/bin/ledger/filesystem/detached_path.h"
#include "peridot/bin/ledger/filesystem/directory_reader.h"
#include "peridot/bin/ledger/testing/cloud_provider/fake_cloud_provider.h"
#include "peridot/bin/ledger/testing/cloud_provider/types.h"
#include "peridot/lib/scoped_tmpfs/scoped_tmpfs.h"

namespace test {
namespace e2e_local {
namespace {

using ::testing::ElementsAre;

template <class A>
bool Equals(const fidl::VectorPtr<uint8_t>& a1, const A& a2) {
  if (a1->size() != a2.size())
    return false;
  return memcmp(a1->data(), a2.data(), a1->size()) == 0;
}

fidl::VectorPtr<uint8_t> TestArray() {
  std::string value = "value";
  fidl::VectorPtr<uint8_t> result(value.size());
  memcpy(&result->at(0), &value[0], value.size());
  return result;
}

class LedgerEndToEndTest : public gtest::RealLoopFixture {
 public:
  LedgerEndToEndTest()
      : startup_context_(
            component::StartupContext::CreateFromStartupInfoNotChecked()) {}
  ~LedgerEndToEndTest() override {}

 protected:
  void Init(std::vector<std::string> additional_args) {
    component::Services child_services;
    fuchsia::sys::LaunchInfo launch_info;
    launch_info.url = "ledger";
    launch_info.directory_request = child_services.NewRequest();
    launch_info.arguments.push_back("--disable_reporting");
    for (auto& additional_arg : additional_args) {
      launch_info.arguments.push_back(additional_arg);
    }
    startup_context()->launcher()->CreateComponent(
        std::move(launch_info), ledger_controller_.NewRequest());

    ledger_controller_.set_error_handler([this](zx_status_t status) {
      for (const auto& callback : ledger_shutdown_callbacks_) {
        callback();
      }
    });

    ledger_repository_factory_.set_error_handler([](zx_status_t status) {
      if (status != ZX_ERR_PEER_CLOSED) {
        ADD_FAILURE() << "Ledger repository error: " << status;
      }
    });
    child_services.ConnectToService(ledger_repository_factory_.NewRequest());
    child_services.ConnectToService(controller_.NewRequest());
  }

  void RegisterShutdownCallback(fit::function<void()> callback) {
    ledger_shutdown_callbacks_.push_back(std::move(callback));
  }

  component::StartupContext* startup_context() {
    return startup_context_.get();
  }

 private:
  fuchsia::sys::ComponentControllerPtr ledger_controller_;
  std::vector<fit::function<void()>> ledger_shutdown_callbacks_;
  std::unique_ptr<component::StartupContext> startup_context_;

 protected:
  ledger_internal::LedgerRepositoryFactoryPtr ledger_repository_factory_;
  fidl::SynchronousInterfacePtr<ledger::Ledger> ledger_;
  fidl::SynchronousInterfacePtr<ledger_internal::LedgerController> controller_;
};

TEST_F(LedgerEndToEndTest, PutAndGet) {
  Init({});
  ledger::Status status;
  fidl::SynchronousInterfacePtr<ledger_internal::LedgerRepository>
      ledger_repository;
  scoped_tmpfs::ScopedTmpFS tmpfs;
  ledger_repository_factory_->GetRepository(
      fsl::CloneChannelFromFileDescriptor(tmpfs.root_fd()), nullptr, "",
      ledger_repository.NewRequest());

  ledger_repository->GetLedger(TestArray(), ledger_.NewRequest());
  ASSERT_EQ(ZX_OK, ledger_repository->Sync());

  fidl::SynchronousInterfacePtr<ledger::Page> page;
  ledger_->GetRootPage(page.NewRequest(), &status);
  ASSERT_EQ(ledger::Status::OK, status);
  page->Put(TestArray(), TestArray(), &status);
  EXPECT_EQ(ledger::Status::OK, status);
  fidl::SynchronousInterfacePtr<ledger::PageSnapshot> snapshot;
  page->GetSnapshot(snapshot.NewRequest(), fidl::VectorPtr<uint8_t>::New(0),
                    nullptr, &status);
  EXPECT_EQ(ledger::Status::OK, status);
  fuchsia::mem::BufferPtr value;
  snapshot->Get(TestArray(), &status, &value);
  EXPECT_EQ(ledger::Status::OK, status);
  std::string value_as_string;
  EXPECT_TRUE(fsl::StringFromVmo(*value, &value_as_string));
  EXPECT_TRUE(Equals(TestArray(), value_as_string));
}

TEST_F(LedgerEndToEndTest, Terminate) {
  Init({});
  bool called = false;
  RegisterShutdownCallback([this, &called] {
    called = true;
    QuitLoop();
  });
  controller_->Terminate();
  RunLoop();
  EXPECT_TRUE(called);
}

// Verifies the cloud erase recovery in case of a cloud that was erased before
// startup.
//
// Expected behavior: Ledger disconnects the clients and the local state is
// cleared.
TEST_F(LedgerEndToEndTest, CloudEraseRecoveryOnInitialCheck) {
  Init({});
  bool ledger_shut_down = false;
  RegisterShutdownCallback([&ledger_shut_down] { ledger_shut_down = true; });

  ledger_internal::LedgerRepositoryPtr ledger_repository;
  scoped_tmpfs::ScopedTmpFS tmpfs;
  const std::string content_path = ledger::kSerializationVersion.ToString();
  const std::string deletion_sentinel_path = content_path + "/sentinel";
  ASSERT_TRUE(files::CreateDirectoryAt(tmpfs.root_fd(), content_path));
  ASSERT_TRUE(
      files::WriteFileAt(tmpfs.root_fd(), deletion_sentinel_path, "", 0));
  ASSERT_TRUE(files::IsFileAt(tmpfs.root_fd(), deletion_sentinel_path));

  // Write a fingerprint file, so that Ledger will check if it is still in the
  // cloud device set.
  const std::string fingerprint_path = content_path + "/fingerprint";
  const std::string fingerprint = "bazinga";
  ASSERT_TRUE(files::WriteFileAt(tmpfs.root_fd(), fingerprint_path,
                                 fingerprint.c_str(), fingerprint.size()));

  // Create a cloud provider configured to trigger the cloude erase recovery on
  // initial check.
  auto cloud_provider =
      ledger::FakeCloudProvider::Builder()
          .SetCloudEraseOnCheck(ledger::CloudEraseOnCheck::YES)
          .Build();
  cloud_provider::CloudProviderPtr cloud_provider_ptr;
  fidl::Binding<cloud_provider::CloudProvider> cloud_provider_binding(
      cloud_provider.get(), cloud_provider_ptr.NewRequest());

  ledger_repository_factory_->GetRepository(
      fsl::CloneChannelFromFileDescriptor(tmpfs.root_fd()),
      std::move(cloud_provider_ptr), "user_id", ledger_repository.NewRequest());

  bool repo_disconnected = false;
  ledger_repository.set_error_handler(
      [&repo_disconnected](zx_status_t status) { repo_disconnected = true; });

  // Run the message loop until Ledger clears the repo directory and disconnects
  // the client.
  RunLoopUntil([&] {
    return !files::IsFileAt(tmpfs.root_fd(), deletion_sentinel_path) &&
           repo_disconnected;
  });
  EXPECT_FALSE(files::IsFileAt(tmpfs.root_fd(), deletion_sentinel_path));
  EXPECT_TRUE(repo_disconnected);

  // Make sure all the contents are deleted. Only the staging directory should
  // be present.
  std::vector<std::string> directory_entries;
  auto on_next_directory_entry = [&](fxl::StringView entry) {
    directory_entries.push_back(entry.ToString());
    return true;
  };
  EXPECT_TRUE(ledger::GetDirectoryEntries(ledger::DetachedPath(tmpfs.root_fd()),
                                          on_next_directory_entry));
  EXPECT_THAT(directory_entries, ElementsAre("staging"));

  // Verify that the Ledger app didn't crash.
  EXPECT_FALSE(ledger_shut_down);
}

// Verifies the cloud erase recovery in case of a cloud that is erased while
// Ledger is connected to it.
//
// Expected behavior: Ledger disconnects the clients and the local state is
// cleared.
TEST_F(LedgerEndToEndTest, CloudEraseRecoveryFromTheWatcher) {
  Init({});
  bool ledger_shut_down = false;
  RegisterShutdownCallback([&ledger_shut_down] { ledger_shut_down = true; });

  ledger_internal::LedgerRepositoryPtr ledger_repository;
  scoped_tmpfs::ScopedTmpFS tmpfs;
  const std::string content_path = ledger::kSerializationVersion.ToString();
  const std::string deletion_sentinel_path = content_path + "/sentinel";
  ASSERT_TRUE(files::CreateDirectoryAt(tmpfs.root_fd(), content_path));
  ASSERT_TRUE(
      files::WriteFileAt(tmpfs.root_fd(), deletion_sentinel_path, "", 0));
  ASSERT_TRUE(files::IsFileAt(tmpfs.root_fd(), deletion_sentinel_path));

  // Create a cloud provider configured to trigger the cloud erase recovery
  // while Ledger is connected.
  auto cloud_provider =
      ledger::FakeCloudProvider::Builder()
          .SetCloudEraseFromWatcher(ledger::CloudEraseFromWatcher::YES)
          .Build();
  cloud_provider::CloudProviderPtr cloud_provider_ptr;
  fidl::Binding<cloud_provider::CloudProvider> cloud_provider_binding(
      cloud_provider.get(), cloud_provider_ptr.NewRequest());

  ledger_repository_factory_->GetRepository(
      fsl::CloneChannelFromFileDescriptor(tmpfs.root_fd()),
      std::move(cloud_provider_ptr), "user_id", ledger_repository.NewRequest());

  bool repo_disconnected = false;
  ledger_repository.set_error_handler(
      [&repo_disconnected](zx_status_t status) { repo_disconnected = true; });

  // Run the message loop until Ledger clears the repo directory and disconnects
  // the client.
  RunLoopUntil([&] {
    return !files::IsFileAt(tmpfs.root_fd(), deletion_sentinel_path) &&
           repo_disconnected;
  });
  EXPECT_FALSE(files::IsFileAt(tmpfs.root_fd(), deletion_sentinel_path));
  EXPECT_TRUE(repo_disconnected);

  // Verify that the Ledger app didn't crash.
  EXPECT_FALSE(ledger_shut_down);
}

// Verifies that Ledger instance continues to work even if the cloud provider
// goes away (for example, because it crashes).
//
// In the future, we need to also be able to reconnect/request a new cloud
// provider, see LE-567.
TEST_F(LedgerEndToEndTest, HandleCloudProviderDisconnectBeforePageInit) {
  Init({});
  bool ledger_app_shut_down = false;
  RegisterShutdownCallback(
      [&ledger_app_shut_down] { ledger_app_shut_down = true; });
  ledger::Status status;
  scoped_tmpfs::ScopedTmpFS tmpfs;

  cloud_provider::CloudProviderPtr cloud_provider_ptr;
  fidl::SynchronousInterfacePtr<ledger_internal::LedgerRepository>
      ledger_repository;
  ledger::FakeCloudProvider cloud_provider;
  fidl::Binding<cloud_provider::CloudProvider> cloud_provider_binding(
      &cloud_provider, cloud_provider_ptr.NewRequest());
  ledger_repository_factory_->GetRepository(
      fsl::CloneChannelFromFileDescriptor(tmpfs.root_fd()),
      std::move(cloud_provider_ptr), "user_id", ledger_repository.NewRequest());

  ledger_repository->GetLedger(TestArray(), ledger_.NewRequest());
  ASSERT_EQ(ZX_OK, ledger_repository->Sync());

  // Close the cloud provider channel.
  cloud_provider_binding.Unbind();

  // Write and read some data to verify that Ledger still works.
  fidl::SynchronousInterfacePtr<ledger::Page> page;
  status = ledger::Status::INTERNAL_ERROR;
  ledger_->GetPage(nullptr, page.NewRequest(), &status);
  ASSERT_EQ(ledger::Status::OK, status);
  status = ledger::Status::INTERNAL_ERROR;
  page->Put(TestArray(), TestArray(), &status);
  EXPECT_EQ(ledger::Status::OK, status);
  fidl::SynchronousInterfacePtr<ledger::PageSnapshot> snapshot;
  status = ledger::Status::INTERNAL_ERROR;
  page->GetSnapshot(snapshot.NewRequest(), fidl::VectorPtr<uint8_t>::New(0),
                    nullptr, &status);
  EXPECT_EQ(ledger::Status::OK, status);
  fuchsia::mem::BufferPtr value;
  status = ledger::Status::INTERNAL_ERROR;
  snapshot->Get(TestArray(), &status, &value);
  ASSERT_EQ(ledger::Status::OK, status);
  std::string value_as_string;
  EXPECT_TRUE(fsl::StringFromVmo(*value, &value_as_string));
  EXPECT_TRUE(Equals(TestArray(), value_as_string));

  // Verify that the Ledger app didn't crash or shut down.
  EXPECT_TRUE(ledger_repository);
  EXPECT_FALSE(ledger_app_shut_down);
}

TEST_F(LedgerEndToEndTest, HandleCloudProviderDisconnectBetweenReadAndWrite) {
  Init({});
  bool ledger_app_shut_down = false;
  RegisterShutdownCallback(
      [&ledger_app_shut_down] { ledger_app_shut_down = true; });
  ledger::Status status;
  scoped_tmpfs::ScopedTmpFS tmpfs;

  cloud_provider::CloudProviderPtr cloud_provider_ptr;
  fidl::SynchronousInterfacePtr<ledger_internal::LedgerRepository>
      ledger_repository;
  ledger::FakeCloudProvider cloud_provider;
  fidl::Binding<cloud_provider::CloudProvider> cloud_provider_binding(
      &cloud_provider, cloud_provider_ptr.NewRequest());
  ledger_repository_factory_->GetRepository(
      fsl::CloneChannelFromFileDescriptor(tmpfs.root_fd()),
      std::move(cloud_provider_ptr), "user_id", ledger_repository.NewRequest());

  ledger_repository->GetLedger(TestArray(), ledger_.NewRequest());
  ASSERT_EQ(ZX_OK, ledger_repository->Sync());

  // Write some data.
  fidl::SynchronousInterfacePtr<ledger::Page> page;
  status = ledger::Status::INTERNAL_ERROR;
  ledger_->GetPage(nullptr, page.NewRequest(), &status);
  ASSERT_EQ(ledger::Status::OK, status);
  status = ledger::Status::INTERNAL_ERROR;
  page->Put(TestArray(), TestArray(), &status);
  EXPECT_EQ(ledger::Status::OK, status);

  // Close the cloud provider channel.
  cloud_provider_binding.Unbind();

  // Read the data back.
  fidl::SynchronousInterfacePtr<ledger::PageSnapshot> snapshot;
  status = ledger::Status::INTERNAL_ERROR;
  page->GetSnapshot(snapshot.NewRequest(), fidl::VectorPtr<uint8_t>::New(0),
                    nullptr, &status);
  EXPECT_EQ(ledger::Status::OK, status);
  fuchsia::mem::BufferPtr value;
  status = ledger::Status::INTERNAL_ERROR;
  snapshot->Get(TestArray(), &status, &value);
  ASSERT_EQ(ledger::Status::OK, status);
  std::string value_as_string;
  EXPECT_TRUE(fsl::StringFromVmo(*value, &value_as_string));
  EXPECT_TRUE(Equals(TestArray(), value_as_string));

  // Verify that the Ledger app didn't crash or shut down.
  EXPECT_TRUE(ledger_repository);
  EXPECT_FALSE(ledger_app_shut_down);
}

}  // namespace
}  // namespace e2e_local
}  // namespace test
