// Copyright 2020 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/fdio.h>

#include <block-client/cpp/block-device.h>
#include <block-client/cpp/fake-device.h>
#include <gtest/gtest.h>

#include "src/storage/blobfs/blobfs.h"
#include "src/storage/blobfs/mkfs.h"
#include "src/storage/blobfs/mount.h"
#include "src/storage/blobfs/runner.h"
#include "src/storage/blobfs/test/blob_utils.h"
#include "src/storage/blobfs/test/integration/blobfs_fixtures.h"
#include "src/storage/blobfs/test/integration/fdio_test.h"

namespace blobfs {
namespace {

using SyncFdioTest = FdioTest;

uint64_t GetSucceededFlushCalls(block_client::FakeBlockDevice* device) {
  fuchsia_hardware_block_BlockStats stats;
  device->GetStats(true, &stats);
  return stats.flush.success.total_calls;
}

}  // namespace

// Verifies that fdio "fsync" calls actually sync blobfs files to the block device and verifies
// behavior for different lifecycles of creating a file.
TEST_F(SyncFdioTest, Sync) {
  std::unique_ptr<BlobInfo> info = GenerateRandomBlob("", 64);

  memmove(info->path, info->path + 1, strlen(info->path));  // Remove leading slash.
  int file = openat(root_fd(), info->path, O_RDWR | O_CREAT);
  EXPECT_TRUE(file >= 1);

  // We have not written any data to the file. Blobfs requires the file data to be written so the
  // name is the hash of the contents.
  EXPECT_EQ(-1, fsync(file));

  // Write the contents. The file must be truncated before writing to declare its size.
  EXPECT_EQ(0, ftruncate(file, info->size_data));
  EXPECT_EQ(write(file, info->data.get(), info->size_data), static_cast<ssize_t>(info->size_data));

  // Sync the file. This will block until woken up by the file_wake_thread.
  EXPECT_EQ(0, fsync(file));

  // fsync on a file will flush the journal but won't trigger a flush to the device above and beyond
  // those required to flush the journal.  This might change, but presently, flushing the journal
  // will trigger a flush after writing data, but before writing to the journal, another one after
  // between writing to the journal and writing to the final metadata location, and then another one
  // prior to writing a new info-block, so we should see 3 flush calls plus a flush that's triggered
  // when we format, so 4 in total.
  fuchsia_hardware_block_BlockStats stats;
  block_device()->GetStats(true, &stats);
  EXPECT_LE(1u, stats.write.success.total_calls);
  EXPECT_EQ(4u, stats.flush.success.total_calls);

  // Sync the root directory. Syncing a directory will force the block device to flush.
  EXPECT_EQ(0, fsync(root_fd()));
  EXPECT_EQ(1u, GetSucceededFlushCalls(block_device()));
}

// Verifies that fdio "sync" actually flushes a NAND device. This tests the fdio, blobfs, block
// device, and FTL layers.
TEST(SyncNandTest, Sync) {
  // Make a VMO to give to the RAM-NAND.
  const size_t kVmoSize = 100 * (4096 + 8) * 64;
  fzl::OwnedVmoMapper vmo;
  ASSERT_EQ(vmo.CreateAndMap(kVmoSize, "vmo"), ZX_OK);
  memset(vmo.start(), 0xff, kVmoSize);

  auto options = BlobfsDefaultTestParam();
  options.use_ram_nand = true;
  options.ram_nand_vmo = vmo.vmo().borrow();
  options.device_block_count = 0;  // Uses VMO size.
  options.device_block_size = 8192;

  std::unique_ptr<BlobInfo> info = GenerateRandomBlob("", 64);

  memmove(info->path, info->path + 1, strlen(info->path));  // Remove leading slash.
  auto snapshot = std::make_unique<uint8_t[]>(kVmoSize);

  {
    auto fs_or = fs_test::TestFilesystem::Create(options);
    ASSERT_TRUE(fs_or.is_ok()) << "Unable to create file system: " << fs_or.status_string();
    auto fs = std::move(fs_or).value();

    fbl::unique_fd root_fd(open(fs.mount_path().c_str(), O_DIRECTORY));
    fbl::unique_fd file(openat(root_fd.get(), info->path, O_RDWR | O_CREAT));
    ASSERT_TRUE(file.is_valid());

    // Write the contents. The file must be truncated before writing to declare its size.
    ASSERT_EQ(ftruncate(file.get(), info->size_data), 0);
    ASSERT_EQ(write(file.get(), info->data.get(), info->size_data),
              static_cast<ssize_t>(info->size_data));

    // This should block until the sync is complete. fsync-ing the root FD is required to flush
    // everything.
    ASSERT_EQ(fsync(file.get()), 0);
    ASSERT_EQ(fsync(root_fd.get()), 0);

    // Without closing the file or tearing down the existing connection (which may add extra
    // flushes, etc.), create a snapshot of the current. This will emulate a power cycle.
    memcpy(snapshot.get(), vmo.start(), kVmoSize);
  }

  // Restore snapshot and remount.
  memcpy(vmo.start(), snapshot.get(), kVmoSize);
  auto fs_or = fs_test::TestFilesystem::Open(options);
  ASSERT_TRUE(fs_or.is_ok()) << "Unable to open file system: " << fs_or.status_string();
  auto fs = std::move(fs_or).value();

  // The blob file should exist.
  fbl::unique_fd root_fd(open(fs.mount_path().c_str(), O_DIRECTORY));
  fbl::unique_fd file(openat(root_fd.get(), info->path, O_RDONLY));
  ASSERT_TRUE(file.is_valid());

  // The contents should be exactly what we wrote.
  std::unique_ptr<char[]> read_data = std::make_unique<char[]>(info->size_data);
  ASSERT_EQ(read(file.get(), read_data.get(), info->size_data),
            static_cast<ssize_t>(info->size_data));
  EXPECT_EQ(memcmp(info->data.get(), &read_data[0], info->size_data), 0);
}

}  // namespace blobfs
