// 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 "src/lib/util/consistent_proto_store.h"

#include <fstream>

#include <gtest/gtest.h>

#include "src/lib/util/consistent_proto_store_test.pb.h"
#include "src/lib/util/posix_file_system.h"

namespace cobalt::util {

int path_suffix = 0;
constexpr char test_dir_base[] = "/tmp/cps_test";

const Status fake_fail(StatusCode::INTERNAL, "BAD", "BAD");

std::string GetTestDirName(const std::string &base) {
  std::stringstream fname;
  fname << base << "_"
        << std::chrono::duration_cast<std::chrono::milliseconds>(
               std::chrono::system_clock::now().time_since_epoch())
               .count()
        << "_" << path_suffix++;
  return fname.str();
}

class TestConsistentProtoStore : public ConsistentProtoStore {
 public:
  explicit TestConsistentProtoStore(const std::string &filename)
      : ConsistentProtoStore(filename, &fs_) {}

  ~TestConsistentProtoStore() override = default;

  void FailNextWriteToTmp() { fail_write_tmp_ = true; }
  void FailNextMoveTmpToOverride() { fail_move_tmp_ = true; }
  void FailNextDeletePrimary() { fail_delete_primary_ = true; }
  void FailNextMoveOverrideToPrimary() { fail_move_override_to_primary_ = true; }

 private:
  Status WriteToTmp(const std::string &tmp_filename,
                    const google::protobuf::MessageLite &proto) override {
    if (fail_write_tmp_) {
      fail_write_tmp_ = false;
      return fake_fail;
    }
    return ConsistentProtoStore::WriteToTmp(tmp_filename, proto);
  }

  Status MoveTmpToOverride(const std::string &tmp_filename,
                           const std::string &override_filename) override {
    if (fail_move_tmp_) {
      fail_move_tmp_ = false;
      return fake_fail;
    }
    return ConsistentProtoStore::MoveTmpToOverride(tmp_filename, override_filename);
  }

  Status DeletePrimary(const std::string &primary_filename) override {
    if (fail_delete_primary_) {
      fail_delete_primary_ = false;
      return fake_fail;
    }
    return ConsistentProtoStore::DeletePrimary(primary_filename);
  }

  Status MoveOverrideToPrimary(const std::string &override_filename,
                               const std::string &primary_filename) override {
    if (fail_move_override_to_primary_) {
      fail_move_override_to_primary_ = false;
      return fake_fail;
    }
    return ConsistentProtoStore::MoveOverrideToPrimary(override_filename, primary_filename);
  }

  PosixFileSystem fs_;
  bool fail_write_tmp_ = false;
  bool fail_move_tmp_ = false;
  bool fail_delete_primary_ = false;
  bool fail_move_override_to_primary_ = false;
};

class ConsistentProtoStoreTest : public ::testing::Test {
 public:
  ConsistentProtoStoreTest()
      : directory_(GetTestDirName(test_dir_base)), store_(directory_ + "/Proto") {}

  void Mkdir() {
    PosixFileSystem fs;
    fs.MakeDirectory(directory_);
  }

  void TearDown() override {
    // Clean up the directory
    PosixFileSystem fs;
    auto files = fs.ListFiles(directory_).ConsumeValueOr({});
    for (const auto &file : files) {
      fs.Delete(directory_ + "/" + file);
    }
    fs.Delete(directory_);
  }

 protected:
  std::string directory_;
  TestConsistentProtoStore store_;
};

TEST_F(ConsistentProtoStoreTest, DirectoryMissing) {
  TestProto p;
  p.set_b(true);
  auto stat = store_.Write(p);

  EXPECT_FALSE(stat.ok());
  EXPECT_EQ(stat.error_details(), "No such file or directory");

  stat = store_.Read(&p);
  EXPECT_FALSE(stat.ok());
  EXPECT_EQ(stat.error_details(), "No such file or directory");
}

TEST_F(ConsistentProtoStoreTest, NoFileToRead) {
  Mkdir();
  TestProto p;
  auto stat = store_.Read(&p);

  EXPECT_FALSE(stat.ok());
  EXPECT_EQ(stat.error_details(), "No such file or directory");
}

TEST_F(ConsistentProtoStoreTest, Normal) {
  Mkdir();
  TestProto pin, pout;
  pin.set_b(true);
  pin.set_i(42);
  pin.set_s("Data!");
  auto stat = store_.Write(pin);
  EXPECT_TRUE(stat.ok());
  EXPECT_EQ(stat.error_message(), "");
  EXPECT_EQ(stat.error_details(), "");

  stat = store_.Read(&pout);
  EXPECT_TRUE(stat.ok());
  EXPECT_EQ(stat.error_message(), "");
  EXPECT_EQ(stat.error_details(), "");

  EXPECT_EQ(pout.b(), true);
  EXPECT_EQ(pout.i(), 42);
  EXPECT_EQ(pout.s(), "Data!");
}

TEST_F(ConsistentProtoStoreTest, OverriddenPrimaryFilename) {
  Mkdir();
  TestProto pin, pout;
  pin.set_b(true);
  pin.set_i(42);
  pin.set_s("Data!");
  auto stat = store_.Write(directory_ + "/Proto2", pin);
  EXPECT_TRUE(stat.ok());
  EXPECT_EQ(stat.error_message(), "");
  EXPECT_EQ(stat.error_details(), "");

  // Can't read from default directory.
  stat = store_.Read(&pout);
  EXPECT_FALSE(stat.ok());

  // Can read from the alternate.
  stat = store_.Read(directory_ + "/Proto2", &pout);
  EXPECT_TRUE(stat.ok());
  EXPECT_EQ(stat.error_message(), "");
  EXPECT_EQ(stat.error_details(), "");

  EXPECT_EQ(pout.b(), true);
  EXPECT_EQ(pout.i(), 42);
  EXPECT_EQ(pout.s(), "Data!");
}

TEST_F(ConsistentProtoStoreTest, ReadCompatible) {
  Mkdir();
  TestProto pin;
  CompatibleProto pout;
  pin.set_b(true);
  pin.set_i(44);
  auto stat = store_.Write(pin);
  EXPECT_TRUE(stat.ok());
  EXPECT_EQ(stat.error_message(), "");
  EXPECT_EQ(stat.error_details(), "");

  stat = store_.Read(&pout);
  EXPECT_TRUE(stat.ok());
  EXPECT_EQ(stat.error_message(), "");
  EXPECT_EQ(stat.error_details(), "");

  EXPECT_EQ(pout.a_boolean(), true);
}

TEST_F(ConsistentProtoStoreTest, ReadIncompatible) {
  Mkdir();
  TestProto pin;
  IncompatibleProto pout;
  pin.set_s("strang");
  auto stat = store_.Write(pin);
  EXPECT_TRUE(stat.ok());
  EXPECT_EQ(stat.error_message(), "");
  EXPECT_EQ(stat.error_details(), "");

  // Reading an incompatible proto works, but the data is wrong.
  stat = store_.Read(&pout);
  EXPECT_TRUE(stat.ok());
  EXPECT_EQ(stat.error_message(), "");
  EXPECT_EQ(stat.error_details(), "");

  EXPECT_NE(pout.s(), "strang");
}

TEST_F(ConsistentProtoStoreTest, ReadCorrupt) {
  Mkdir();
  {
    std::ofstream f(directory_ + "/Proto");
    f << "Invalid data and stuff";
  }

  TestProto p;
  auto stat = store_.Read(&p);
  EXPECT_FALSE(stat.ok());
  EXPECT_EQ(stat.error_message(), "Unable to parse the protobuf from the store. Data is corrupt.");
  EXPECT_EQ(stat.error_details(), "");
}

TEST_F(ConsistentProtoStoreTest, TestFailures) {
  Mkdir();

  TestProto p, pread;
  p.set_b(true);
  p.set_i(10000);
  p.set_s("testing123");

  store_.FailNextWriteToTmp();
  p.set_i(p.i() + 1);
  EXPECT_FALSE(store_.Write(p).ok());
  EXPECT_FALSE(store_.Read(&pread).ok());

  store_.FailNextMoveTmpToOverride();
  p.set_i(p.i() + 1);
  EXPECT_FALSE(store_.Write(p).ok());
  EXPECT_FALSE(store_.Read(&pread).ok());

  store_.FailNextDeletePrimary();
  p.set_i(p.i() + 1);
  EXPECT_FALSE(store_.Write(p).ok());
  // The read should succeed since the tmp file was renamed to new file.
  EXPECT_TRUE(store_.Read(&pread).ok());
  EXPECT_EQ(pread.i(), p.i());

  store_.FailNextDeletePrimary();
  p.set_i(p.i() + 1);
  // This write should succeed, since the delete will fail during recovery,
  // which is ignored.
  EXPECT_TRUE(store_.Write(p).ok());
  EXPECT_TRUE(store_.Read(&pread).ok());
  EXPECT_EQ(pread.i(), p.i());

  store_.FailNextMoveOverrideToPrimary();
  p.set_i(p.i() + 1);
  EXPECT_FALSE(store_.Write(p).ok());
  // A failed finalize should still update the value in the store.
  EXPECT_TRUE(store_.Read(&pread).ok());
  EXPECT_EQ(pread.i(), p.i());

  store_.FailNextMoveTmpToOverride();
  p.set_i(p.i() + 1);
  EXPECT_FALSE(store_.Write(p).ok());
  // If we fail te rename tmp, the value in the store shouldn't change, but it
  // should still be valid.
  EXPECT_TRUE(store_.Read(&pread).ok());
  EXPECT_EQ(pread.i(), p.i() - 1);
}

}  // namespace cobalt::util
