// Copyright 2017 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 "src/ledger/bin/app/merging/common_ancestor.h"

#include <lib/callback/cancellable_helper.h>
#include <lib/callback/capture.h>
#include <lib/callback/set_when_called.h>
#include <lib/fit/function.h>

#include <algorithm>
#include <string>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/ledger/bin/app/constants.h"
#include "src/ledger/bin/app/merging/test_utils.h"
#include "src/ledger/bin/encryption/primitives/hash.h"
#include "src/ledger/bin/storage/public/constants.h"
#include "src/ledger/bin/storage/public/page_storage.h"
#include "src/lib/fxl/macros.h"

using testing::ElementsAre;
using testing::IsEmpty;
using testing::UnorderedElementsAre;

namespace ledger {
namespace {
class CommonAncestorTest : public TestWithPageStorage {
 public:
  CommonAncestorTest() {}
  ~CommonAncestorTest() override {}

 protected:
  storage::PageStorage* page_storage() override { return storage_.get(); }

  void SetUp() override {
    TestWithPageStorage::SetUp();
    ASSERT_TRUE(CreatePageStorage(&storage_));
  }

  std::unique_ptr<const storage::Commit> CreateCommit(
      storage::CommitIdView parent_id,
      fit::function<void(storage::Journal*)> contents) {
    storage::Status status;
    bool called;
    std::unique_ptr<const storage::Commit> base;
    storage_->GetCommit(
        parent_id,
        callback::Capture(callback::SetWhenCalled(&called), &status, &base));
    RunLoopUntilIdle();
    EXPECT_TRUE(called);
    EXPECT_EQ(storage::Status::OK, status);

    std::unique_ptr<storage::Journal> journal =
        storage_->StartCommit(std::move(base));

    contents(journal.get());
    std::unique_ptr<const storage::Commit> commit;
    storage_->CommitJournal(
        std::move(journal),
        callback::Capture(callback::SetWhenCalled(&called), &status, &commit));
    RunLoopUntilIdle();
    EXPECT_TRUE(called);
    EXPECT_EQ(storage::Status::OK, status);

    return commit;
  }

  std::unique_ptr<const storage::Commit> CreateMergeCommit(
      std::unique_ptr<const storage::Commit> base_left,
      std::unique_ptr<const storage::Commit> base_right,
      fit::function<void(storage::Journal*)> contents) {
    std::unique_ptr<storage::Journal> journal =
        storage_->StartMergeCommit(std::move(base_left), std::move(base_right));

    contents(journal.get());
    storage::Status actual_status;
    bool called;
    std::unique_ptr<const storage::Commit> actual_commit;
    storage_->CommitJournal(std::move(journal),
                            callback::Capture(callback::SetWhenCalled(&called),
                                              &actual_status, &actual_commit));
    RunLoopUntilIdle();
    EXPECT_TRUE(called);
    EXPECT_EQ(storage::Status::OK, actual_status);
    return actual_commit;
  }

  std::unique_ptr<const storage::Commit> GetRoot() {
    bool called;
    storage::Status status;
    std::unique_ptr<const storage::Commit> root;
    storage_->GetCommit(
        storage::kFirstPageCommitId,
        callback::Capture(callback::SetWhenCalled(&called), &status, &root));
    RunLoopUntilIdle();
    EXPECT_TRUE(called);
    EXPECT_EQ(storage::Status::OK, status);
    return root;
  }

  std::vector<storage::CommitId> GetCommitIds(
      const std::vector<std::unique_ptr<const storage::Commit>>& commits) {
    std::vector<storage::CommitId> ids;
    ids.reserve(commits.size());
    for (auto& commit : commits) {
      ids.push_back(commit->GetId());
    }
    return ids;
  }

  std::unique_ptr<storage::PageStorage> storage_;

 private:
  FXL_DISALLOW_COPY_AND_ASSIGN(CommonAncestorTest);
};

TEST_F(CommonAncestorTest, TwoChildrenOfRoot) {
  std::unique_ptr<const storage::Commit> commit_1 = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "a"));
  std::unique_ptr<const storage::Commit> commit_2 = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "b"));

  RunInCoroutine([&](coroutine::CoroutineHandler* handler) {
    storage::Status status;
    CommitComparison comparison;
    std::vector<std::unique_ptr<const storage::Commit>> result;
    status = FindCommonAncestors(handler, storage_.get(), std::move(commit_1),
                                 std::move(commit_2), &comparison, &result);
    EXPECT_EQ(storage::Status::OK, status);
    EXPECT_EQ(CommitComparison::UNORDERED, comparison);
    EXPECT_THAT(GetCommitIds(result),
                ElementsAre(storage::kFirstPageCommitId.ToString()));
  });
}

TEST_F(CommonAncestorTest, RootAndChild) {
  std::unique_ptr<const storage::Commit> root = GetRoot();

  std::unique_ptr<const storage::Commit> child = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "a"));

  RunInCoroutine([&](coroutine::CoroutineHandler* handler) {
    storage::Status status;
    CommitComparison comparison;
    std::vector<std::unique_ptr<const storage::Commit>> result;
    status = FindCommonAncestors(handler, storage_.get(), std::move(root),
                                 std::move(child), &comparison, &result);
    EXPECT_EQ(storage::Status::OK, status);
    EXPECT_EQ(CommitComparison::LEFT_SUBSET_OF_RIGHT, comparison);
    EXPECT_THAT(result, IsEmpty());
  });
}

TEST_F(CommonAncestorTest, ChildAndRoot) {
  std::unique_ptr<const storage::Commit> root = GetRoot();

  std::unique_ptr<const storage::Commit> child = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "a"));

  RunInCoroutine([&](coroutine::CoroutineHandler* handler) {
    storage::Status status;
    CommitComparison comparison;
    std::vector<std::unique_ptr<const storage::Commit>> result;
    status = FindCommonAncestors(handler, storage_.get(), std::move(child),
                                 std::move(root), &comparison, &result);

    EXPECT_EQ(storage::Status::OK, status);
    EXPECT_EQ(CommitComparison::RIGHT_SUBSET_OF_LEFT, comparison);
    EXPECT_THAT(result, IsEmpty());
  });
}

// In this test the commits have the following structure:
//            (root)
//              /  \
//            (A)  (B)
//           /  \  /   \
//         (1) (merge) (2)
TEST_F(CommonAncestorTest, MergeCommitAndSomeOthers) {
  std::unique_ptr<const storage::Commit> commit_a = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "a"));
  std::unique_ptr<const storage::Commit> commit_b = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "b"));

  std::unique_ptr<const storage::Commit> commit_merge = CreateMergeCommit(
      commit_a->Clone(), commit_b->Clone(), AddKeyValueToJournal("key", "c"));

  std::unique_ptr<const storage::Commit> commit_1 =
      CreateCommit(commit_a->GetId(), AddKeyValueToJournal("key", "1"));
  std::unique_ptr<const storage::Commit> commit_2 =
      CreateCommit(commit_b->GetId(), AddKeyValueToJournal("key", "2"));

  RunInCoroutine([&](coroutine::CoroutineHandler* handler) {
    // LCA of (1) and (merge) needs to be (A).
    storage::Status status;
    CommitComparison comparison;
    std::vector<std::unique_ptr<const storage::Commit>> result;
    status = FindCommonAncestors(handler, storage_.get(), std::move(commit_1),
                                 std::move(commit_merge), &comparison, &result);
    EXPECT_EQ(storage::Status::OK, status);
    EXPECT_EQ(CommitComparison::UNORDERED, comparison);
    EXPECT_THAT(GetCommitIds(result), ElementsAre(commit_a->GetId()));

    // LCA of (2) and (A) is (root).
    result.clear();
    status = FindCommonAncestors(handler, storage_.get(), std::move(commit_2),
                                 std::move(commit_a), &comparison, &result);
    EXPECT_EQ(storage::Status::OK, status);
    EXPECT_EQ(CommitComparison::UNORDERED, comparison);
    EXPECT_THAT(GetCommitIds(result),
                ElementsAre(storage::kFirstPageCommitId.ToString()));
  });
}

// Regression test for LE-187.
TEST_F(CommonAncestorTest, LongChain) {
  const int length = 180;

  std::unique_ptr<const storage::Commit> commit_a = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "a"));
  std::unique_ptr<const storage::Commit> commit_b = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "b"));

  std::unique_ptr<const storage::Commit> last_commit = std::move(commit_a);
  for (int i = 0; i < length; i++) {
    last_commit = CreateCommit(last_commit->GetId(),
                               AddKeyValueToJournal(std::to_string(i), "val"));
  }

  RunInCoroutine([&](coroutine::CoroutineHandler* handler) {
    // Ancestor of (last commit) and (b) needs to be (root).
    storage::Status status;
    CommitComparison comparison;
    std::vector<std::unique_ptr<const storage::Commit>> result;
    status =
        FindCommonAncestors(handler, storage_.get(), std::move(last_commit),
                            std::move(commit_b), &comparison, &result);
    // This test lasts ~2.5s on x86+qemu+kvm.
    EXPECT_EQ(storage::Status::OK, status);
    EXPECT_EQ(CommitComparison::UNORDERED, comparison);
    EXPECT_THAT(GetCommitIds(result),
                ElementsAre(storage::kFirstPageCommitId.ToString()));
  });
}

// Test detection of equivalent commits.
// In this test the commits have the following structure:
//      (root)
//      /   \
//     (A) (B)
//      |\ /|
//      | X |
//      |/ \|
//     (M) (N)
// Requesting the common ancestors of (M) and (N) should return an empty vector
// and EQUIVALENT.
TEST_F(CommonAncestorTest, EquivalentCommits) {
  std::unique_ptr<const storage::Commit> commit_a = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "a"));
  std::unique_ptr<const storage::Commit> commit_b = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "b"));
  std::unique_ptr<const storage::Commit> commit_m = CreateMergeCommit(
      commit_a->Clone(), commit_b->Clone(), AddKeyValueToJournal("key", "m"));
  std::unique_ptr<const storage::Commit> commit_n =
      CreateMergeCommit(std::move(commit_a), std::move(commit_b),
                        AddKeyValueToJournal("key", "n"));

  RunInCoroutine([&](coroutine::CoroutineHandler* handler) {
    storage::Status status;
    CommitComparison comparison;
    std::vector<std::unique_ptr<const storage::Commit>> result;
    status = FindCommonAncestors(handler, storage_.get(), std::move(commit_m),
                                 std::move(commit_n), &comparison, &result);
    EXPECT_EQ(storage::Status::OK, status);
    EXPECT_EQ(CommitComparison::EQUIVALENT, comparison);
    EXPECT_THAT(GetCommitIds(result), IsEmpty());
  });
}

// Multiple common ancestors from the same generation
// In this test, the commits have the following structure:
//       (root)
//       /    \
//     (A)    (B)
//      | \  / |
//     (C) \/ (D)
//      |  /\  |
//      | /  \ |
//     (E)    (F)
// Then the common ancestors of (E) and (F) are (A) and (B).
TEST_F(CommonAncestorTest, TwoBasesSameGeneration) {
  std::unique_ptr<const storage::Commit> commit_a = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "a"));
  std::unique_ptr<const storage::Commit> commit_b = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "b"));
  std::unique_ptr<const storage::Commit> commit_c =
      CreateCommit(commit_a->GetId(), AddKeyValueToJournal("key", "c"));
  std::unique_ptr<const storage::Commit> commit_d =
      CreateCommit(commit_b->GetId(), AddKeyValueToJournal("key", "d"));
  std::unique_ptr<const storage::Commit> commit_e = CreateMergeCommit(
      commit_c->Clone(), commit_b->Clone(), AddKeyValueToJournal("key", "e"));
  std::unique_ptr<const storage::Commit> commit_f = CreateMergeCommit(
      commit_a->Clone(), std::move(commit_d), AddKeyValueToJournal("key", "f"));

  RunInCoroutine([&](coroutine::CoroutineHandler* handler) {
    // The LCAs of (E) and (F) are (A) and (B)
    storage::Status status;
    CommitComparison comparison;
    std::vector<std::unique_ptr<const storage::Commit>> result;
    status = FindCommonAncestors(handler, storage_.get(), std::move(commit_e),
                                 std::move(commit_f), &comparison, &result);
    EXPECT_EQ(storage::Status::OK, status);
    EXPECT_EQ(CommitComparison::UNORDERED, comparison);
    EXPECT_THAT(GetCommitIds(result),
                UnorderedElementsAre(commit_a->GetId(), commit_b->GetId()));
  });
}

// Merges with multiple common ancestors from different generations
// In this test, the commits have the following structure:
//       (root)
//       /    \
//      |     (X)
//      |      |
//     (A)    (B)
//      | \  / |
//     (C) \/ (D)
//      |  /\  |
//      | /  \ |
//     (E)    (F)
// The LCAs of (E) and (F) are (A) and (B).
TEST_F(CommonAncestorTest, TwoBasesDifferentGenerations) {
  std::unique_ptr<const storage::Commit> commit_a = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "a"));
  std::unique_ptr<const storage::Commit> commit_x = CreateCommit(
      storage::kFirstPageCommitId, AddKeyValueToJournal("key", "x"));
  std::unique_ptr<const storage::Commit> commit_b =
      CreateCommit(commit_x->GetId(), AddKeyValueToJournal("key", "b"));
  std::unique_ptr<const storage::Commit> commit_c =
      CreateCommit(commit_a->GetId(), AddKeyValueToJournal("key", "c"));
  std::unique_ptr<const storage::Commit> commit_d =
      CreateCommit(commit_b->GetId(), AddKeyValueToJournal("key", "d"));
  std::unique_ptr<const storage::Commit> commit_e = CreateMergeCommit(
      std::move(commit_c), commit_b->Clone(), AddKeyValueToJournal("key", "e"));
  std::unique_ptr<const storage::Commit> commit_f = CreateMergeCommit(
      commit_a->Clone(), std::move(commit_d), AddKeyValueToJournal("key", "f"));

  RunInCoroutine([&](coroutine::CoroutineHandler* handler) {
    // The LCAs of (E) and (F) are (A) and (B)
    storage::Status status;
    CommitComparison comparison;
    std::vector<std::unique_ptr<const storage::Commit>> result;
    status = FindCommonAncestors(handler, storage_.get(), std::move(commit_e),
                                 std::move(commit_f), &comparison, &result);
    EXPECT_EQ(storage::Status::OK, status);
    EXPECT_EQ(CommitComparison::UNORDERED, comparison);
    EXPECT_THAT(GetCommitIds(result),
                UnorderedElementsAre(commit_a->GetId(), commit_b->GetId()));
  });
}

}  // namespace
}  // namespace ledger
