// 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,
                                &file_tracker_, /*trailer_prefetch_size=*/-1),
                            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::NumberToString(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);

  // 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));
  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);

  for (const auto& entry : entries)
    file_tracker_.Close(entry.get(), SimpleFileTracker::SubFile::FILE_0);
}

}  // namespace disk_cache
