// 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 "src/ledger/bin/storage/impl/object_impl.h"

#include <lib/fsl/vmo/strings.h>
#include <zircon/syscalls.h>

#include <memory>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "peridot/lib/scoped_tmpfs/scoped_tmpfs.h"
#include "src/ledger/bin/storage/impl/btree/encoding.h"
#include "src/ledger/bin/storage/impl/constants.h"
#include "src/ledger/bin/storage/impl/file_index.h"
#include "src/ledger/bin/storage/impl/object_digest.h"
#include "src/ledger/bin/storage/impl/storage_test_utils.h"
#include "src/ledger/bin/storage/public/data_source.h"
#include "src/ledger/bin/storage/public/types.h"
#include "src/ledger/bin/testing/test_with_environment.h"
#include "src/lib/fxl/logging.h"
#include "third_party/leveldb/include/leveldb/db.h"
#include "util/env_fuchsia.h"

namespace storage {
namespace {
using ::testing::IsEmpty;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;

ObjectIdentifier CreateObjectIdentifier(ObjectDigest digest) {
  return {1u, 2u, std::move(digest)};
}

::testing::AssertionResult CheckObjectValue(const Object& object,
                                            ObjectIdentifier identifier,
                                            fxl::StringView data) {
  if (object.GetIdentifier() != identifier) {
    return ::testing::AssertionFailure()
           << "Expected id: " << identifier
           << ", but got: " << object.GetIdentifier();
  }

  fxl::StringView found_data;
  Status status = object.GetData(&found_data);
  if (status != Status::OK) {
    return ::testing::AssertionFailure()
           << "Unable to call GetData on object, status: " << status;
  }

  if (data != found_data) {
    return ::testing::AssertionFailure()
           << "Expected data: " << convert::ToHex(data)
           << ", but got: " << convert::ToHex(found_data);
  }

  fsl::SizedVmo vmo;
  status = object.GetVmo(&vmo);
  if (status != Status::OK) {
    return ::testing::AssertionFailure()
           << "Unable to call GetVmo on object, status: " << status;
  }

  std::string found_data_in_vmo;
  if (!fsl::StringFromVmo(vmo, &found_data_in_vmo)) {
    return ::testing::AssertionFailure() << "Unable to read from VMO.";
  }

  if (data != found_data_in_vmo) {
    return ::testing::AssertionFailure()
           << "Expected data in vmo: " << convert::ToHex(data)
           << ", but got: " << convert::ToHex(found_data_in_vmo);
  }

  return ::testing::AssertionSuccess();
}

::testing::AssertionResult CheckPieceValue(const Piece& piece,
                                           ObjectIdentifier identifier,
                                           fxl::StringView data) {
  if (piece.GetIdentifier() != identifier) {
    return ::testing::AssertionFailure()
           << "Expected id: " << identifier
           << ", but got: " << piece.GetIdentifier();
  }

  fxl::StringView found_data = piece.GetData();

  if (data != found_data) {
    return ::testing::AssertionFailure()
           << "Expected data: " << convert::ToHex(data)
           << ", but got: " << convert::ToHex(found_data);
  }

  return ::testing::AssertionSuccess();
}

using ObjectImplTest = ledger::TestWithEnvironment;

TEST_F(ObjectImplTest, InlinedPiece) {
  std::string data = RandomString(environment_.random(), 12);
  ObjectIdentifier identifier = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB, data));

  const InlinePiece piece(identifier);
  EXPECT_TRUE(CheckPieceValue(piece, identifier, data));
}

TEST_F(ObjectImplTest, DataChunkPiece) {
  std::string data = RandomString(environment_.random(), 12);
  ObjectIdentifier identifier = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB, data));

  const DataChunkPiece piece(identifier, DataSource::DataChunk::Create(data));
  EXPECT_TRUE(CheckPieceValue(piece, identifier, data));
}

TEST_F(ObjectImplTest, LevelDBPiece) {
  scoped_tmpfs::ScopedTmpFS tmpfs;
  auto env = leveldb::MakeFuchsiaEnv(tmpfs.root_fd());

  leveldb::DB* db = nullptr;
  leveldb::Options options;
  options.env = env.get();
  options.create_if_missing = true;
  leveldb::Status status = leveldb::DB::Open(options, "db", &db);
  ASSERT_TRUE(status.ok());
  std::unique_ptr<leveldb::DB> db_ptr(db);

  leveldb::WriteOptions write_options_;
  leveldb::ReadOptions read_options_;

  std::string data = RandomString(environment_.random(), 256);
  ObjectIdentifier identifier = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB, data));

  status = db_ptr->Put(write_options_, "", data);
  ASSERT_TRUE(status.ok());
  std::unique_ptr<leveldb::Iterator> iterator(
      db_ptr->NewIterator(read_options_));
  iterator->Seek("");
  ASSERT_TRUE(iterator->Valid());
  ASSERT_TRUE(iterator->key() == "");

  const LevelDBPiece piece(identifier, std::move(iterator));
  EXPECT_TRUE(CheckPieceValue(piece, identifier, data));
}

TEST_F(ObjectImplTest, PieceReferences) {
  // Create various types of identifiers for the piece children. Small pieces
  // fit in chunks, while bigger ones are split and yield identifiers of index
  // pieces.
  constexpr size_t kInlineSize = kStorageHashSize;
  const ObjectIdentifier inline_chunk = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB,
                          RandomString(environment_.random(), kInlineSize)));
  ASSERT_TRUE(GetObjectDigestInfo(inline_chunk.object_digest()).is_chunk());
  ASSERT_TRUE(GetObjectDigestInfo(inline_chunk.object_digest()).is_inlined());

  const ObjectIdentifier inline_index = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::INDEX, ObjectType::BLOB,
                          RandomString(environment_.random(), kInlineSize)));
  ASSERT_FALSE(GetObjectDigestInfo(inline_index.object_digest()).is_chunk());
  ASSERT_TRUE(GetObjectDigestInfo(inline_index.object_digest()).is_inlined());

  constexpr size_t kNoInlineSize = kStorageHashSize + 1;
  const ObjectIdentifier noinline_chunk = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB,
                          RandomString(environment_.random(), kNoInlineSize)));
  ASSERT_TRUE(GetObjectDigestInfo(noinline_chunk.object_digest()).is_chunk());
  ASSERT_FALSE(
      GetObjectDigestInfo(noinline_chunk.object_digest()).is_inlined());

  const ObjectIdentifier noinline_index = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::INDEX, ObjectType::BLOB,
                          RandomString(environment_.random(), kNoInlineSize)));
  ASSERT_FALSE(GetObjectDigestInfo(noinline_index.object_digest()).is_chunk());
  ASSERT_FALSE(
      GetObjectDigestInfo(noinline_index.object_digest()).is_inlined());

  // Create the parent piece.
  std::unique_ptr<DataSource::DataChunk> data;
  size_t total_size;
  FileIndexSerialization::BuildFileIndex({{inline_chunk, kInlineSize},
                                          {noinline_chunk, kInlineSize},
                                          {inline_index, kNoInlineSize},
                                          {noinline_index, kNoInlineSize}},
                                         &data, &total_size);
  const ObjectIdentifier identifier = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::INDEX, ObjectType::BLOB, data->Get()));
  DataChunkPiece piece(identifier, std::move(data));

  // Check that inline children are not included in the references.
  ObjectReferencesAndPriority references;
  ASSERT_EQ(Status::OK, piece.AppendReferences(&references));
  EXPECT_THAT(references,
              UnorderedElementsAre(
                  Pair(noinline_chunk.object_digest(), KeyPriority::EAGER),
                  Pair(noinline_index.object_digest(), KeyPriority::EAGER)));
}

TEST_F(ObjectImplTest, ChunkObject) {
  std::string data = RandomString(environment_.random(), 12);
  ObjectIdentifier identifier = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB, data));

  ChunkObject object(std::make_unique<InlinePiece>(identifier));
  EXPECT_TRUE(CheckObjectValue(object, identifier, data));
}

TEST_F(ObjectImplTest, VmoObject) {
  std::string data = RandomString(environment_.random(), 256);
  ObjectIdentifier identifier = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB, data));

  fsl::SizedVmo vmo;
  ASSERT_TRUE(fsl::VmoFromString(data, &vmo));

  VmoObject object(identifier, std::move(vmo));
  EXPECT_TRUE(CheckObjectValue(object, identifier, data));
}

TEST_F(ObjectImplTest, ObjectReferences) {
  // Create various types of identifiers for the object children and values.
  constexpr size_t kInlineSize = kStorageHashSize;
  const ObjectIdentifier inline_blob = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB,
                          RandomString(environment_.random(), kInlineSize)));
  ASSERT_TRUE(GetObjectDigestInfo(inline_blob.object_digest()).is_inlined());

  const ObjectIdentifier inline_treenode = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::TREE_NODE,
                          RandomString(environment_.random(), kInlineSize)));
  ASSERT_TRUE(
      GetObjectDigestInfo(inline_treenode.object_digest()).is_inlined());

  constexpr size_t kNoInlineSize = kStorageHashSize + 1;
  const ObjectIdentifier noinline_blob = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB,
                          RandomString(environment_.random(), kNoInlineSize)));
  ASSERT_FALSE(GetObjectDigestInfo(noinline_blob.object_digest()).is_inlined());

  const ObjectIdentifier noinline_treenode = CreateObjectIdentifier(
      ComputeObjectDigest(PieceType::CHUNK, ObjectType::TREE_NODE,
                          RandomString(environment_.random(), kNoInlineSize)));
  ASSERT_FALSE(
      GetObjectDigestInfo(noinline_treenode.object_digest()).is_inlined());

  // Create a TreeNode object.
  const std::string data =
      btree::EncodeNode(/*level=*/0,
                        {
                            Entry{"key01", inline_blob, KeyPriority::EAGER},
                            Entry{"key02", noinline_blob, KeyPriority::EAGER},
                            Entry{"key03", inline_blob, KeyPriority::LAZY},
                            Entry{"key04", noinline_blob, KeyPriority::LAZY},
                        },
                        {
                            {0, inline_treenode},
                            {1, noinline_treenode},
                        });
  const ChunkObject tree_object(std::make_unique<DataChunkPiece>(
      CreateObjectIdentifier(
          ComputeObjectDigest(PieceType::CHUNK, ObjectType::TREE_NODE, data)),
      DataSource::DataChunk::Create(data)));

  // Check that inline children are not included in the references.
  ObjectReferencesAndPriority references;
  ASSERT_EQ(Status::OK, tree_object.AppendReferences(&references));
  EXPECT_THAT(references,
              UnorderedElementsAre(
                  Pair(noinline_blob.object_digest(), KeyPriority::EAGER),
                  Pair(noinline_blob.object_digest(), KeyPriority::LAZY),
                  Pair(noinline_treenode.object_digest(), KeyPriority::EAGER)));

  // Create a blob object with the exact same data and check that it does not
  // return any reference.
  const ChunkObject blob_object(std::make_unique<DataChunkPiece>(
      CreateObjectIdentifier(
          ComputeObjectDigest(PieceType::CHUNK, ObjectType::BLOB, data)),
      DataSource::DataChunk::Create(data)));
  references.clear();
  ASSERT_EQ(Status::OK, blob_object.AppendReferences(&references));
  EXPECT_THAT(references, IsEmpty());

  // Create an invalid tree node object and check that we return an error.
  const ChunkObject invalid_object(std::make_unique<DataChunkPiece>(
      CreateObjectIdentifier(
          ComputeObjectDigest(PieceType::CHUNK, ObjectType::TREE_NODE, "")),
      DataSource::DataChunk::Create("")));
  ASSERT_EQ(Status::FORMAT_ERROR, invalid_object.AppendReferences(&references));
}

}  // namespace
}  // namespace storage
