// Copyright (c) 2017 The Chromium 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 <memory>
#include <string>

#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "net/base/cache_type.h"
#include "net/disk_cache/disk_cache_test_base.h"
#include "net/disk_cache/simple/simple_file_tracker.h"
#include "net/disk_cache/simple/simple_histogram_enums.h"
#include "net/disk_cache/simple/simple_synchronous_entry.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace disk_cache {

class SimpleFileTrackerTest : public DiskCacheTest {
 public:
  void DeleteSyncEntry(SimpleSynchronousEntry* entry) { delete entry; }

  // We limit open files to 4 for the fixture, as this is large enough
  // that simple tests don't have to worry about naming files normally,
  // but small enough to test with easily.
  static const int kFileLimit = 4;

 protected:
  SimpleFileTrackerTest() : file_tracker_(kFileLimit) {}

  // A bit of messiness since we rely on friendship of the fixture to be able to
  // create/delete SimpleSynchronousEntry objects.
  class SyncEntryDeleter {
   public:
    SyncEntryDeleter(SimpleFileTrackerTest* fixture) : fixture_(fixture) {}
    void operator()(SimpleSynchronousEntry* entry) {
      fixture_->DeleteSyncEntry(entry);
    }

   private:
    SimpleFileTrackerTest* fixture_;
  };

  using SyncEntryPointer =
      std::unique_ptr<SimpleSynchronousEntry, SyncEntryDeleter>;

  SyncEntryPointer MakeSyncEntry(uint64_t hash) {
    return SyncEntryPointer(
        new SimpleSynchronousEntry(net::DISK_CACHE, cache_path_, "dummy", hash,
                                   /* had_index=*/true, &file_tracker_),
        SyncEntryDeleter(this));
  }

  void UpdateEntryFileKey(SimpleSynchronousEntry* sync_entry,
                          SimpleFileTracker::EntryFileKey file_key) {
    sync_entry->entry_file_key_ = file_key;
  }

  SimpleFileTracker file_tracker_;
};

TEST_F(SimpleFileTrackerTest, Basic) {
  SyncEntryPointer entry = MakeSyncEntry(1);

  // Just transfer some files to the tracker, and then do some I/O on getting
  // them back.
  base::FilePath path_0 = cache_path_.AppendASCII("file_0");
  base::FilePath path_1 = cache_path_.AppendASCII("file_1");

  std::unique_ptr<base::File> file_0 = std::make_unique<base::File>(
      path_0, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  std::unique_ptr<base::File> file_1 = std::make_unique<base::File>(
      path_1, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  ASSERT_TRUE(file_0->IsValid());
  ASSERT_TRUE(file_1->IsValid());

  file_tracker_.Register(entry.get(), SimpleFileTracker::SubFile::FILE_0,
                         std::move(file_0));
  file_tracker_.Register(entry.get(), SimpleFileTracker::SubFile::FILE_1,
                         std::move(file_1));

  base::StringPiece msg_0 = "Hello";
  base::StringPiece msg_1 = "Worldish Place";

  {
    SimpleFileTracker::FileHandle borrow_0 =
        file_tracker_.Acquire(entry.get(), SimpleFileTracker::SubFile::FILE_0);
    SimpleFileTracker::FileHandle borrow_1 =
        file_tracker_.Acquire(entry.get(), SimpleFileTracker::SubFile::FILE_1);

    EXPECT_EQ(static_cast<int>(msg_0.size()),
              borrow_0->Write(0, msg_0.data(), msg_0.size()));
    EXPECT_EQ(static_cast<int>(msg_1.size()),
              borrow_1->Write(0, msg_1.data(), msg_1.size()));

    // For stream 0 do release/close, for stream 1 do close/release --- where
    // release happens when borrow_{0,1} go out of scope
    file_tracker_.Close(entry.get(), SimpleFileTracker::SubFile::FILE_1);
  }
  file_tracker_.Close(entry.get(), SimpleFileTracker::SubFile::FILE_0);

  // Verify contents.
  std::string verify_0, verify_1;
  EXPECT_TRUE(ReadFileToString(path_0, &verify_0));
  EXPECT_TRUE(ReadFileToString(path_1, &verify_1));
  EXPECT_EQ(msg_0, verify_0);
  EXPECT_EQ(msg_1, verify_1);
  EXPECT_TRUE(file_tracker_.IsEmptyForTesting());
}

TEST_F(SimpleFileTrackerTest, Collision) {
  // Two entries with same key.
  SyncEntryPointer entry = MakeSyncEntry(1);
  SyncEntryPointer entry2 = MakeSyncEntry(1);

  base::FilePath path = cache_path_.AppendASCII("file");
  base::FilePath path2 = cache_path_.AppendASCII("file2");

  std::unique_ptr<base::File> file = std::make_unique<base::File>(
      path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  std::unique_ptr<base::File> file2 = std::make_unique<base::File>(
      path2, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  ASSERT_TRUE(file->IsValid());
  ASSERT_TRUE(file2->IsValid());

  file_tracker_.Register(entry.get(), SimpleFileTracker::SubFile::FILE_0,
                         std::move(file));
  file_tracker_.Register(entry2.get(), SimpleFileTracker::SubFile::FILE_0,
                         std::move(file2));

  base::StringPiece msg = "Alpha";
  base::StringPiece msg2 = "Beta";

  {
    SimpleFileTracker::FileHandle borrow =
        file_tracker_.Acquire(entry.get(), SimpleFileTracker::SubFile::FILE_0);
    SimpleFileTracker::FileHandle borrow2 =
        file_tracker_.Acquire(entry2.get(), SimpleFileTracker::SubFile::FILE_0);

    EXPECT_EQ(static_cast<int>(msg.size()),
              borrow->Write(0, msg.data(), msg.size()));
    EXPECT_EQ(static_cast<int>(msg2.size()),
              borrow2->Write(0, msg2.data(), msg2.size()));
  }
  file_tracker_.Close(entry.get(), SimpleFileTracker::SubFile::FILE_0);
  file_tracker_.Close(entry2.get(), SimpleFileTracker::SubFile::FILE_0);

  // Verify contents.
  std::string verify, verify2;
  EXPECT_TRUE(ReadFileToString(path, &verify));
  EXPECT_TRUE(ReadFileToString(path2, &verify2));
  EXPECT_EQ(msg, verify);
  EXPECT_EQ(msg2, verify2);
  EXPECT_TRUE(file_tracker_.IsEmptyForTesting());
}

TEST_F(SimpleFileTrackerTest, Reopen) {
  // We may sometimes go Register -> Close -> Register, with info still
  // alive.
  SyncEntryPointer entry = MakeSyncEntry(1);

  base::FilePath path_0 = cache_path_.AppendASCII("file_0");
  base::FilePath path_1 = cache_path_.AppendASCII("file_1");

  std::unique_ptr<base::File> file_0 = std::make_unique<base::File>(
      path_0, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  std::unique_ptr<base::File> file_1 = std::make_unique<base::File>(
      path_1, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  ASSERT_TRUE(file_0->IsValid());
  ASSERT_TRUE(file_1->IsValid());

  file_tracker_.Register(entry.get(), SimpleFileTracker::SubFile::FILE_0,
                         std::move(file_0));
  file_tracker_.Register(entry.get(), SimpleFileTracker::SubFile::FILE_1,
                         std::move(file_1));

  file_tracker_.Close(entry.get(), SimpleFileTracker::SubFile::FILE_1);
  std::unique_ptr<base::File> file_1b = std::make_unique<base::File>(
      path_1, base::File::FLAG_OPEN | base::File::FLAG_WRITE);
  ASSERT_TRUE(file_1b->IsValid());
  file_tracker_.Register(entry.get(), SimpleFileTracker::SubFile::FILE_1,
                         std::move(file_1b));
  file_tracker_.Close(entry.get(), SimpleFileTracker::SubFile::FILE_0);
  file_tracker_.Close(entry.get(), SimpleFileTracker::SubFile::FILE_1);
  EXPECT_TRUE(file_tracker_.IsEmptyForTesting());
}

TEST_F(SimpleFileTrackerTest, PointerStability) {
  // Make sure the FileHandle lent out doesn't get screwed up as we update
  // the state (and potentially move the underlying base::File object around).
  const int kEntries = 8;
  SyncEntryPointer entries[kEntries] = {
      MakeSyncEntry(1), MakeSyncEntry(1), MakeSyncEntry(1), MakeSyncEntry(1),
      MakeSyncEntry(1), MakeSyncEntry(1), MakeSyncEntry(1), MakeSyncEntry(1),
  };
  std::unique_ptr<base::File> file_0 = std::make_unique<base::File>(
      cache_path_.AppendASCII("0"),
      base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  ASSERT_TRUE(file_0->IsValid());
  file_tracker_.Register(entries[0].get(), SimpleFileTracker::SubFile::FILE_0,
                         std::move(file_0));

  base::StringPiece msg = "Message to write";
  {
    SimpleFileTracker::FileHandle borrow = file_tracker_.Acquire(
        entries[0].get(), SimpleFileTracker::SubFile::FILE_0);
    for (int i = 1; i < kEntries; ++i) {
      std::unique_ptr<base::File> file_n = std::make_unique<base::File>(
          cache_path_.AppendASCII(base::IntToString(i)),
          base::File::FLAG_CREATE | base::File::FLAG_WRITE);
      ASSERT_TRUE(file_n->IsValid());
      file_tracker_.Register(entries[i].get(),
                             SimpleFileTracker::SubFile::FILE_0,
                             std::move(file_n));
    }

    EXPECT_EQ(static_cast<int>(msg.size()),
              borrow->Write(0, msg.data(), msg.size()));
  }

  for (int i = 0; i < kEntries; ++i)
    file_tracker_.Close(entries[i].get(), SimpleFileTracker::SubFile::FILE_0);

  // Verify the file.
  std::string verify;
  EXPECT_TRUE(ReadFileToString(cache_path_.AppendASCII("0"), &verify));
  EXPECT_EQ(msg, verify);
  EXPECT_TRUE(file_tracker_.IsEmptyForTesting());
}

TEST_F(SimpleFileTrackerTest, Doom) {
  SyncEntryPointer entry1 = MakeSyncEntry(1);
  base::FilePath path1 = cache_path_.AppendASCII("file1");
  std::unique_ptr<base::File> file1 = std::make_unique<base::File>(
      path1, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  ASSERT_TRUE(file1->IsValid());

  file_tracker_.Register(entry1.get(), SimpleFileTracker::SubFile::FILE_0,
                         std::move(file1));
  SimpleFileTracker::EntryFileKey key1 = entry1->entry_file_key();
  file_tracker_.Doom(entry1.get(), &key1);
  EXPECT_NE(0u, key1.doom_generation);

  // Other entry with same key.
  SyncEntryPointer entry2 = MakeSyncEntry(1);
  base::FilePath path2 = cache_path_.AppendASCII("file2");
  std::unique_ptr<base::File> file2 = std::make_unique<base::File>(
      path2, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  ASSERT_TRUE(file2->IsValid());

  file_tracker_.Register(entry2.get(), SimpleFileTracker::SubFile::FILE_0,
                         std::move(file2));
  SimpleFileTracker::EntryFileKey key2 = entry2->entry_file_key();
  file_tracker_.Doom(entry2.get(), &key2);
  EXPECT_NE(0u, key2.doom_generation);
  EXPECT_NE(key1.doom_generation, key2.doom_generation);

  file_tracker_.Close(entry1.get(), SimpleFileTracker::SubFile::FILE_0);
  file_tracker_.Close(entry2.get(), SimpleFileTracker::SubFile::FILE_0);
}

TEST_F(SimpleFileTrackerTest, OverLimit) {
  base::HistogramTester histogram_tester;

  const int kEntries = 10;  // want more than FD limit in fixture.
  std::vector<SyncEntryPointer> entries;
  std::vector<base::FilePath> names;
  for (int i = 0; i < kEntries; ++i) {
    SyncEntryPointer entry = MakeSyncEntry(i);
    base::FilePath name =
        entry->GetFilenameForSubfile(SimpleFileTracker::SubFile::FILE_0);
    std::unique_ptr<base::File> file = std::make_unique<base::File>(
        name, base::File::FLAG_CREATE | base::File::FLAG_WRITE |
                  base::File::FLAG_READ);
    ASSERT_TRUE(file->IsValid());
    file_tracker_.Register(entry.get(), SimpleFileTracker::SubFile::FILE_0,
                           std::move(file));
    entries.push_back(std::move(entry));
    names.push_back(name);
  }

  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_CLOSE_FILE,
                                     kEntries - kFileLimit);
  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_REOPEN_FILE, 0);
  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_FAIL_REOPEN_FILE, 0);

  // Grab the last one; we will hold it open till the end of the test. It's
  // still open, so no change in stats after.
  SimpleFileTracker::FileHandle borrow_last = file_tracker_.Acquire(
      entries[kEntries - 1].get(), SimpleFileTracker::SubFile::FILE_0);
  EXPECT_EQ(1, borrow_last->Write(0, "L", 1));

  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_CLOSE_FILE,
                                     kEntries - kFileLimit);
  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_REOPEN_FILE, 0);
  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_FAIL_REOPEN_FILE, 0);

  // Delete file for [2], to cause error on its re-open.
  EXPECT_TRUE(base::DeleteFile(names[2], false)) << names[2];

  // Reacquire all the other files.
  for (int i = 0; i < kEntries - 1; ++i) {
    SimpleFileTracker::FileHandle borrow = file_tracker_.Acquire(
        entries[i].get(), SimpleFileTracker::SubFile::FILE_0);
    if (i != 2) {
      EXPECT_TRUE(borrow.IsOK());
      char c = static_cast<char>(i);
      EXPECT_EQ(1, borrow->Write(0, &c, 1));
    } else {
      EXPECT_FALSE(borrow.IsOK());
    }
  }

  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_CLOSE_FILE,
                                     kEntries - kFileLimit + kEntries - 2);
  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_REOPEN_FILE,
                                     kEntries - 2);
  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_FAIL_REOPEN_FILE, 1);

#if !defined(STARBOARD)
  // Doom file for [1].
  SimpleFileTracker::EntryFileKey key = entries[1]->entry_file_key();
  file_tracker_.Doom(entries[1].get(), &key);
  base::FilePath old_path = names[1];
  UpdateEntryFileKey(entries[1].get(), key);
  base::FilePath new_path =
      entries[1]->GetFilenameForSubfile(SimpleFileTracker::SubFile::FILE_0);
  EXPECT_TRUE(base::StartsWith(new_path.BaseName().MaybeAsASCII(), "todelete_",
                               base::CompareCase::SENSITIVE));
  // Moving file is not supported by Starboard.
  EXPECT_TRUE(base::Move(old_path, new_path));

  // Now re-acquire everything again; this time reading.
  for (int i = 0; i < kEntries - 1; ++i) {
    SimpleFileTracker::FileHandle borrow = file_tracker_.Acquire(
        entries[i].get(), SimpleFileTracker::SubFile::FILE_0);
    char read;
    char expected = static_cast<char>(i);
    if (i != 2) {
      EXPECT_TRUE(borrow.IsOK());
      EXPECT_EQ(1, borrow->Read(0, &read, 1));
      EXPECT_EQ(expected, read);
    } else {
      EXPECT_FALSE(borrow.IsOK());
    }
  }

  histogram_tester.ExpectBucketCount(
      "SimpleCache.FileDescriptorLimiterAction",
      disk_cache::FD_LIMIT_CLOSE_FILE,
      kEntries - kFileLimit + 2 * (kEntries - 2));
  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_REOPEN_FILE,
                                     2 * (kEntries - 2));
  histogram_tester.ExpectBucketCount("SimpleCache.FileDescriptorLimiterAction",
                                     disk_cache::FD_LIMIT_FAIL_REOPEN_FILE, 2);

  // Read from the last one, too. Should still be fine.
  char read;
  EXPECT_EQ(1, borrow_last->Read(0, &read, 1));
  EXPECT_EQ('L', read);

#endif  // !defined(STARBOARD)
  for (const auto& entry : entries)
    file_tracker_.Close(entry.get(), SimpleFileTracker::SubFile::FILE_0);
};

}  // namespace disk_cache
