// 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 <fuchsia/ledger/internal/cpp/fidl.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <lib/callback/capture.h>
#include <lib/callback/set_when_called.h>
#include <lib/callback/waiter.h>

#include "peridot/bin/ledger/testing/ledger_matcher.h"
#include "peridot/bin/ledger/tests/integration/integration_test.h"
#include "peridot/bin/ledger/tests/integration/test_utils.h"

using testing::IsEmpty;

namespace ledger {
namespace {

// Tests in this suite execute a series of operations and check the content of
// the Page afterwards.
class PageMutationTest : public IntegrationTest {
 public:
  void SetUp() override {
    IntegrationTest::SetUp();
    app_instance_ = NewLedgerAppInstance();
    page_ = app_instance_->GetTestPage();
  }

  PageSnapshotPtr PageGetSnapshot() {
    Status status;
    PageSnapshotPtr snapshot;
    auto waiter = NewWaiter();
    page_->GetSnapshot(snapshot.NewRequest(), fidl::VectorPtr<uint8_t>::New(0),
                       nullptr,
                       callback::Capture(waiter->GetCallback(), &status));
    if (!waiter->RunUntilCalled()) {
      ADD_FAILURE() << "|GetSnapshot| failed to called back.";
      return nullptr;
    }
    EXPECT_EQ(Status::OK, status);
    return snapshot;
  }

  std::vector<Entry> GetEntries() {
    PageSnapshotPtr snapshot = PageGetSnapshot();
    return SnapshotGetEntries(this, &snapshot);
  }

  testing::AssertionResult Put(std::string key, std::string value) {
    return Do("Put", [&](auto callback) {
      page_->Put(convert::ToArray(key), convert::ToArray(value),
                 std::move(callback));
    });
  }

  testing::AssertionResult Delete(std::string key) {
    return Do("Delete", [&](auto callback) {
      page_->Delete(convert::ToArray(key), std::move(callback));
    });
  }

  testing::AssertionResult Clear() {
    return Do("Clear",
              [&](auto callback) { page_->Clear(std::move(callback)); });
  }

  testing::AssertionResult StartTransaction() {
    return Do("StartTransaction", [&](auto callback) {
      page_->StartTransaction(std::move(callback));
    });
  }

  testing::AssertionResult Commit() {
    return Do("Commit",
              [&](auto callback) { page_->Commit(std::move(callback)); });
  }

  testing::AssertionResult Rollback() {
    return Do("Rollback",
              [&](auto callback) { page_->Rollback(std::move(callback)); });
  }

 private:
  // Executes the given action on the current page.
  //
  // This helper function handles the heavy lifting of calling an operation of
  // the page, waiting for the result and returning an assertion error in case
  // of non ok status. It expects |action| to operate the operation on the page
  // and returns the status in its callback.
  testing::AssertionResult Do(
      std::string operation_name,
      fit::function<void(fit::function<void(Status)>)> action) {
    Status status;
    auto waiter = NewWaiter();
    action(callback::Capture(waiter->GetCallback(), &status));
    if (!waiter->RunUntilCalled()) {
      return testing::AssertionFailure()
             << "Error while executing " << operation_name
             << ". |action| failed to call back.";
    }
    if (status == Status::OK) {
      return testing::AssertionSuccess();
    }
    return testing::AssertionFailure()
           << "Error while executing " << operation_name
           << ". Status: " << static_cast<uint32_t>(status);
  }

 protected:
  std::unique_ptr<LedgerAppInstanceFactory::LedgerAppInstance> app_instance_;
  PagePtr page_;
};

TEST_P(PageMutationTest, InitialSnapshotIsEmpty) {
  EXPECT_THAT(GetEntries(), IsEmpty());
}

TEST_P(PageMutationTest, PutOutsideOfTransaction) {
  ASSERT_TRUE(Put("key", "value"));

  ASSERT_THAT(GetEntries(), MatchEntries({{"key", "value"}}));

  ASSERT_TRUE(Put("key2", "value2"));

  ASSERT_THAT(GetEntries(),
              MatchEntries({{"key", "value"}, {"key2", "value2"}}));
}

TEST_P(PageMutationTest, PutInsideOfTransaction) {
  ASSERT_TRUE(StartTransaction());
  ASSERT_TRUE(Put("key", "value"));

  ASSERT_THAT(GetEntries(), IsEmpty());

  ASSERT_TRUE(Put("key2", "value2"));
  ASSERT_TRUE(Commit());

  ASSERT_THAT(GetEntries(),
              MatchEntries({{"key", "value"}, {"key2", "value2"}}));
}

TEST_P(PageMutationTest, RollbackTransaction) {
  ASSERT_TRUE(StartTransaction());
  ASSERT_TRUE(Put("key", "value"));

  ASSERT_THAT(GetEntries(), IsEmpty());

  ASSERT_TRUE(Put("key2", "value2"));
  ASSERT_TRUE(Rollback());

  ASSERT_THAT(GetEntries(), IsEmpty());
}

TEST_P(PageMutationTest, DeleteOutsideOfTransaction) {
  ASSERT_TRUE(Put("key", "value"));
  ASSERT_TRUE(Put("key2", "value2"));
  ASSERT_THAT(GetEntries(),
              MatchEntries({{"key", "value"}, {"key2", "value2"}}));

  ASSERT_TRUE(Delete("key"));

  ASSERT_THAT(GetEntries(), MatchEntries({{"key2", "value2"}}));
}

TEST_P(PageMutationTest, DeleteInsideOfTransaction) {
  ASSERT_TRUE(Put("key", "value"));
  ASSERT_TRUE(Put("key2", "value2"));
  ASSERT_THAT(GetEntries(),
              MatchEntries({{"key", "value"}, {"key2", "value2"}}));

  ASSERT_TRUE(StartTransaction());
  ASSERT_TRUE(Delete("key"));
  ASSERT_TRUE(Put("key3", "value3"));
  ASSERT_TRUE(Delete("key3"));
  ASSERT_TRUE(Commit());

  ASSERT_THAT(GetEntries(), MatchEntries({{"key2", "value2"}}));
}

TEST_P(PageMutationTest, ClearOutsideOfTransaction) {
  ASSERT_TRUE(Put("key", "value"));
  ASSERT_TRUE(Put("key2", "value2"));
  ASSERT_THAT(GetEntries(),
              MatchEntries({{"key", "value"}, {"key2", "value2"}}));

  ASSERT_TRUE(Clear());

  ASSERT_THAT(GetEntries(), IsEmpty());
}

TEST_P(PageMutationTest, ClearInsideOfTransaction) {
  ASSERT_TRUE(Put("key", "value"));
  ASSERT_TRUE(Put("key2", "value2"));
  ASSERT_THAT(GetEntries(),
              MatchEntries({{"key", "value"}, {"key2", "value2"}}));

  ASSERT_TRUE(StartTransaction());
  ASSERT_TRUE(Put("key3", "value3"));
  ASSERT_TRUE(Clear());
  ASSERT_TRUE(Put("key4", "value4"));
  ASSERT_TRUE(Commit());

  ASSERT_THAT(GetEntries(), MatchEntries({{"key4", "value4"}}));
}

TEST_P(PageMutationTest, MultipleClearCallsInsideOfTransaction) {
  ASSERT_TRUE(Put("key", "value"));
  ASSERT_TRUE(Put("key2", "value2"));
  ASSERT_THAT(GetEntries(),
              MatchEntries({{"key", "value"}, {"key2", "value2"}}));

  ASSERT_TRUE(StartTransaction());
  ASSERT_TRUE(Put("key3", "value3"));
  ASSERT_TRUE(Clear());
  ASSERT_TRUE(Put("key4", "value4"));
  ASSERT_TRUE(Clear());
  ASSERT_TRUE(Put("key5", "value5"));
  ASSERT_TRUE(Commit());

  ASSERT_THAT(GetEntries(), MatchEntries({{"key5", "value5"}}));
}

TEST_P(PageMutationTest, ClearAndDeleteInsideOfTransaction) {
  ASSERT_TRUE(Put("key", "value"));
  ASSERT_THAT(GetEntries(), MatchEntries({{"key", "value"}}));

  ASSERT_TRUE(StartTransaction());
  ASSERT_TRUE(Clear());
  ASSERT_TRUE(Delete("key"));
  ASSERT_TRUE(Commit());

  ASSERT_THAT(GetEntries(), IsEmpty());
}

TEST_P(PageMutationTest, DeleteAndClearInsideOfTransaction) {
  ASSERT_TRUE(Put("key", "value"));
  ASSERT_THAT(GetEntries(), MatchEntries({{"key", "value"}}));

  ASSERT_TRUE(StartTransaction());
  ASSERT_TRUE(Delete("key"));
  ASSERT_TRUE(Clear());
  ASSERT_TRUE(Commit());

  ASSERT_THAT(GetEntries(), IsEmpty());
}

TEST_P(PageMutationTest, ClearAndRestoreInsideTransaction) {
  ASSERT_TRUE(Put("key", "value"));
  ASSERT_THAT(GetEntries(), MatchEntries({{"key", "value"}}));

  ASSERT_TRUE(StartTransaction());
  ASSERT_TRUE(Clear());
  ASSERT_TRUE(Put("key", "value"));
  ASSERT_TRUE(Commit());

  ASSERT_THAT(GetEntries(), MatchEntries({{"key", "value"}}));
}

INSTANTIATE_TEST_CASE_P(
    PageMutationTest, PageMutationTest,
    ::testing::ValuesIn(GetLedgerAppInstanceFactoryBuilders()));

}  // namespace
}  // namespace ledger
