// 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 <fuchsia/device/llcpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/zx/channel.h>

#include <random>
#include <thread>

#include <fbl/unique_fd.h>
#include <gtest/gtest.h>

#include "src/storage/fs_test/fs_test.h"

namespace fs_test {
namespace {

namespace device = ::llcpp::fuchsia::device;

TEST(CorruptTest, CorruptTest) {
  // 768 blocks containing 64 pages of 4 KiB with 8 bytes OOB
  constexpr int kSize = 768 * 64 * (4096 + 8);

  fzl::OwnedVmoMapper vmo;
  ASSERT_EQ(vmo.CreateAndMap(kSize, "corrupt-test-vmo"), ZX_OK);
  memset(vmo.start(), 0xff, kSize);

  TestFilesystemOptions options = TestFilesystemOptions::DefaultMinfs();
  options.device_block_size = 8192;
  options.device_block_count = 0;  // Use VMO size.
  options.use_ram_nand = true;
  options.ram_nand_vmo = zx::unowned_vmo(vmo.vmo());

  // In one thread, repeatedly create a file, write to it, sync and then delete two files.  Then,
  // some random amount of time later, tear down the Ram Nand driver, then rebind and fsck.  The
  // journal should ensure the file system remains consistent.
  {
    auto fs_or = TestFilesystem::Create(options);
    ASSERT_TRUE(fs_or.is_ok()) << fs_or.status_string();
    TestFilesystem fs = std::move(fs_or).value();

    const std::string file1 = fs.mount_path() + "/file1";
    const std::string file2 = fs.mount_path() + "/file2";
    std::thread thread([&]() {
      for (;;) {
        {
          fbl::unique_fd fd(open(file1.c_str(), O_RDWR | O_CREAT, 0644));
          if (!fd || write(fd.get(), "hello", 5) != 5 || ftruncate(fd.get(), 0) != 0 ||
              fsync(fd.get()) != 0 || unlink(file1.c_str()) != 0) {
            break;
          }
        }
        {
          fbl::unique_fd fd(open(file2.c_str(), O_RDWR | O_CREAT, 0644));
          if (!fd || write(fd.get(), "hello", 5) != 5 || ftruncate(fd.get(), 0) != 0 ||
              fsync(fd.get()) != 0 || unlink(file2.c_str()) != 0) {
            break;
          }
        }
      }
    });

    std::random_device random;
    std::uniform_int_distribution distribution(0, 20000);
    const int usec = distribution(random);
    std::cout << "sleeping for " << usec << "us" << std::endl;
    zx_nanosleep(zx_deadline_after(zx::usec(usec).get()));

    // Unbind the NAND driver.
    zx::channel local, remote;
    ASSERT_EQ(zx::channel::create(0, &local, &remote), ZX_OK);
    ASSERT_EQ(fdio_service_connect(fs.GetRamNand()->path(), remote.release()), ZX_OK);
    auto resp = device::Controller::Call::ScheduleUnbind(local.borrow());
    ASSERT_EQ(resp.status(), ZX_OK);
    ASSERT_FALSE(resp->result.is_err());

    thread.join();
  }

  auto fs_or = TestFilesystem::Open(options);
  ASSERT_TRUE(fs_or.is_ok()) << fs_or.status_string();
  TestFilesystem fs = std::move(fs_or).value();
  EXPECT_EQ(fs.Unmount().status_value(), ZX_OK);
  EXPECT_EQ(fs.Fsck().status_value(), ZX_OK);
}

}  // namespace
}  // namespace fs_test
