// Copyright 2021 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 "unit_lib.h"

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

#include "third_party/f2fs/f2fs.h"

namespace f2fs {
namespace unittest_lib {

using block_client::FakeBlockDevice;

void MkfsOnFakeDev(std::unique_ptr<Bcache> *bc, uint64_t blockCount, uint32_t blockSize,
                   bool btrim) {
  auto device = std::make_unique<FakeBlockDevice>(FakeBlockDevice::Config{
      .block_count = blockCount, .block_size = blockSize, .supports_trim = btrim});
  bool readonly_device = false;
  ASSERT_EQ(CreateBcache(std::move(device), &readonly_device, bc), ZX_OK);

  MkfsWorker mkfs(bc->get());
  ASSERT_EQ(mkfs.DoMkfs(), ZX_OK);
}

void MountWithOptions(MountOptions &options, std::unique_ptr<Bcache> *bc,
                      std::unique_ptr<F2fs> *fs) {
  ASSERT_EQ(F2fs::Create(std::move(*bc), options, fs), ZX_OK);
}

void Unmount(std::unique_ptr<F2fs> fs, std::unique_ptr<Bcache> *bc) {
  fs->PutSuper();
  fs->ResetBc(bc);
  fs.reset();
}

void SuddenPowerOff(std::unique_ptr<F2fs> fs, std::unique_ptr<Bcache> *bc) {
  SbInfo &sbi = fs->GetSbInfo();

  fs->GetVCache().Reset();

  // destroy f2fs internal modules
  fs->Nodemgr().DestroyNodeManager();
  fs->Segmgr().DestroySegmentManager();

  delete GetCheckpoint(&sbi);
  fs->ResetBc(bc);
  fs.reset();
}

void CreateRoot(F2fs *fs, fbl::RefPtr<VnodeF2fs> *out) {
  ASSERT_EQ(VnodeF2fs::Vget(fs, fs->RawSb().root_ino, out), ZX_OK);
  ASSERT_EQ((*out)->Open((*out)->ValidateOptions(fs::VnodeConnectionOptions()).value(), nullptr),
            ZX_OK);
}

void Lookup(VnodeF2fs *parent, std::string_view name, fbl::RefPtr<fs::Vnode> *out) {
  fbl::RefPtr<fs::Vnode> vn = nullptr;
  if (zx_status_t status = parent->Lookup(name, &vn); status != ZX_OK) {
    *out = nullptr;
    return;
  }
  ASSERT_TRUE(vn);
  ASSERT_EQ(vn->Open(vn->ValidateOptions(fs::VnodeConnectionOptions()).value(), nullptr), ZX_OK);
  *out = std::move(vn);
}

void CreateChild(Dir *vn, uint32_t mode, std::string_view name) {
  fbl::RefPtr<fs::Vnode> tmp_child;
  ASSERT_EQ(vn->Create(name, mode, &tmp_child), ZX_OK);
  ASSERT_EQ(tmp_child->Close(), ZX_OK);
}

void DeleteChild(Dir *vn, std::string_view name) {
  ASSERT_EQ(vn->Unlink(name, true), ZX_OK);
  // TODO: After EvictInode available, check if nids of the child are correctly freed
}

void CreateChildren(F2fs *fs, std::vector<fbl::RefPtr<VnodeF2fs>> &vnodes,
                    std::vector<uint32_t> &inos, fbl::RefPtr<Dir> &parent, std::string name,
                    uint32_t inode_cnt) {
  for (uint32_t i = 0; i < inode_cnt; i++) {
    fbl::RefPtr<fs::Vnode> test_file;

    name += std::to_string(i);
    ASSERT_EQ(parent->Create(name, S_IFREG, &test_file), ZX_OK);
    fbl::RefPtr<VnodeF2fs> test_file_vn = fbl::RefPtr<VnodeF2fs>::Downcast(std::move(test_file));

    inos.push_back(test_file_vn->Ino());
    vnodes.push_back(std::move(test_file_vn));
  }
}

void DeleteChildren(std::vector<fbl::RefPtr<VnodeF2fs>> &vnodes, fbl::RefPtr<Dir> &parent,
                    uint32_t inode_cnt) {
  uint32_t deleted_file_cnt = 0;
  for (const auto &iter : vnodes) {
    ASSERT_EQ(parent->Unlink(iter->GetName(), false), ZX_OK);
    deleted_file_cnt++;
  }
  ASSERT_EQ(deleted_file_cnt, inode_cnt);
}

void VnodeWithoutParent(F2fs *fs, uint32_t mode, fbl::RefPtr<VnodeF2fs> &vnode) {
  nid_t inode_nid;
  ASSERT_TRUE(fs->Nodemgr().AllocNid(&inode_nid));

  VnodeF2fs::Allocate(fs, inode_nid, S_IFREG, &vnode);
  ASSERT_EQ(vnode->Open(vnode->ValidateOptions(fs::VnodeConnectionOptions()).value(), nullptr),
            ZX_OK);
  vnode->UnlockNewInode();
  fs->Nodemgr().AllocNidDone(vnode->Ino());

  fs->InsertVnode(vnode.get());
  vnode->MarkInodeDirty();
}

void CheckInlineDir(VnodeF2fs *vn) {
  ASSERT_NE(vn->TestFlag(InodeInfoFlag::kInlineDentry), 0);
  ASSERT_EQ(vn->GetSize(), kMaxInlineData);
}

void CheckNonInlineDir(VnodeF2fs *vn) {
  ASSERT_EQ(vn->TestFlag(InodeInfoFlag::kInlineDentry), 0);
  ASSERT_GT(vn->GetSize(), kMaxInlineData);
}

void CheckChildrenFromReaddir(Dir *dir, std::unordered_set<std::string> childs) {
  childs.insert(".");

  fs::VdirCookie cookie;
  uint8_t buf[kPageSize];
  size_t len;

  ASSERT_EQ(dir->Readdir(&cookie, buf, sizeof(buf), &len), ZX_OK);

  uint8_t *buf_ptr = buf;

  while (len > 0 && buf_ptr < buf + kPageSize) {
    auto entry = reinterpret_cast<const vdirent_t *>(buf_ptr);
    size_t entry_size = entry->size + sizeof(vdirent_t);

    auto iter = childs.begin();
    for (; iter != childs.end(); iter++) {
      if (memcmp(entry->name, (*iter).c_str(), (*iter).length()) == 0) {
        break;
      }
    }

    ASSERT_NE(iter, childs.end());
    childs.erase(iter);

    buf_ptr += entry_size;
    len -= entry_size;
  }

  ASSERT_TRUE(childs.empty());
}

void CheckChildrenInBlock(Dir *vn, unsigned int bidx, std::unordered_set<std::string> childs) {
  if (bidx == 0) {
    childs.insert(".");
    childs.insert("..");
  }

  Page *page = nullptr;

  if (childs.empty()) {
    ASSERT_EQ(vn->FindDataPage(bidx, &page), ZX_ERR_NOT_FOUND);
    return;
  }

  ASSERT_EQ(vn->FindDataPage(bidx, &page), ZX_OK);
  DentryBlock *dentry_blk = reinterpret_cast<DentryBlock *>(page);

  uint64_t bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, kNrDentryInBlock, 0);
  while (bit_pos < kNrDentryInBlock) {
    DirEntry *de = &dentry_blk->dentry[bit_pos];
    uint64_t slots = (LeToCpu(de->name_len) + kNameLen - 1) / kNameLen;

    auto iter = childs.begin();
    for (; iter != childs.end(); iter++) {
      if (memcmp(dentry_blk->filename[bit_pos], (*iter).c_str(), (*iter).length()) == 0) {
        break;
      }
    }

    ASSERT_NE(iter, childs.end());
    childs.erase(iter);

    bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, kNrDentryInBlock, bit_pos + slots);
  }

  ASSERT_TRUE(childs.empty());

  F2fsPutPage(page, 0);
}

std::string GetRandomName(unsigned int len) {
  const char *char_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  unsigned int char_list_len = strlen(char_list);
  auto generator = [&]() { return char_list[rand() % char_list_len]; };
  std::string str(len, 0);
  std::generate_n(str.begin(), len, generator);
  return str;
}

void AppendToFile(File *file, const void *data, size_t len) {
  size_t end = 0;
  size_t ret = 0;

  ASSERT_EQ(file->Append(data, len, &end, &ret), ZX_OK);
  ASSERT_EQ(ret, kPageSize);
}

void CheckNodeLevel(F2fs *fs, VnodeF2fs *vn, int level) {
  Page *ipage = nullptr;
  ASSERT_EQ(fs->Nodemgr().GetNodePage(vn->Ino(), &ipage), ZX_OK);
  Inode *inode = &(static_cast<Node *>(PageAddress(ipage))->i);

  int i;
  for (i = 0; i < level; i++)
    ASSERT_NE(inode->i_nid[i], 0U);

  for (; i < kNidsPerInode; i++)
    ASSERT_EQ(inode->i_nid[i], 0U);

  F2fsPutPage(ipage, 0);
}

void CheckNidsFree(F2fs *fs, std::unordered_set<nid_t> &nids) {
  SbInfo &sbi = fs->GetSbInfo();
  NmInfo *nm_i = GetNmInfo(&sbi);

  std::lock_guard lock(nm_i->free_nid_list_lock);
  for (auto nid : nids) {
    bool found = false;
    list_node_t *iter;
    list_for_every(&nm_i->free_nid_list, iter) {
      FreeNid *fnid = containerof(iter, FreeNid, list);
      if (fnid->nid == nid) {
        found = true;
        break;
      }
    }
    ASSERT_TRUE(found);
  }
}

void CheckNidsInuse(F2fs *fs, std::unordered_set<nid_t> &nids) {
  SbInfo &sbi = fs->GetSbInfo();
  NmInfo *nm_i = GetNmInfo(&sbi);

  std::lock_guard lock(nm_i->free_nid_list_lock);
  for (auto nid : nids) {
    bool found = false;
    list_node_t *iter;
    list_for_every(&nm_i->free_nid_list, iter) {
      FreeNid *fnid = containerof(iter, FreeNid, list);
      if (fnid->nid == nid) {
        found = true;
        break;
      }
    }
    ASSERT_FALSE(found);
  }
}

void CheckBlkaddrsFree(F2fs *fs, std::unordered_set<block_t> &blkaddrs) {
  SbInfo &sbi = fs->GetSbInfo();
  for (auto blkaddr : blkaddrs) {
    SegEntry *se = fs->Segmgr().GetSegEntry(GetSegNo(&sbi, blkaddr));
    uint32_t offset = GetSegOffFromSeg0(&sbi, blkaddr) & (sbi.blocks_per_seg - 1);
    ASSERT_EQ(TestValidBitmap(offset, reinterpret_cast<char *>(se->ckpt_valid_map)), 0);
  }
}

void CheckBlkaddrsInuse(F2fs *fs, std::unordered_set<block_t> &blkaddrs) {
  SbInfo &sbi = fs->GetSbInfo();
  for (auto blkaddr : blkaddrs) {
    SegEntry *se = fs->Segmgr().GetSegEntry(GetSegNo(&sbi, blkaddr));
    uint32_t offset = GetSegOffFromSeg0(&sbi, blkaddr) & (sbi.blocks_per_seg - 1);
    ASSERT_NE(TestValidBitmap(offset, reinterpret_cast<char *>(se->ckpt_valid_map)), 0);
  }
}

void CheckDnodeOfData(DnodeOfData *dn, nid_t exp_nid, pgoff_t exp_index, bool is_inode) {
  ASSERT_EQ(dn->nid, exp_nid);
  ASSERT_EQ(dn->ofs_in_node, static_cast<uint64_t>(1));
  ASSERT_EQ(dn->data_blkaddr, static_cast<block_t>(0));

  if (is_inode) {
    ASSERT_TRUE(dn->inode_page_locked);
  } else {
    ASSERT_FALSE(dn->inode_page_locked);
  }
}

template <typename T, typename F>
T *LookupList(list_node_t &entries, uint32_t value, F cond) {
  list_node_t *cur, *next;
  list_for_every_safe(&entries, cur, next) {
    T *e = containerof(cur, T, list);

    if (cond(*e, value)) {
      return e;
    }
  }
  return nullptr;
}

bool IsCachedNat(NmInfo *nm_i, nid_t n) {
  auto is_same_nid = [](NatEntry &e, nid_t nid) { return e.ni.nid == nid; };

  if (LookupList<NatEntry>(nm_i->dirty_nat_entries, n, is_same_nid)) {
    return true;
  }
  if (LookupList<NatEntry>(nm_i->nat_entries, n, is_same_nid)) {
    return true;
  }
  return false;
}

void RemoveTruncatedNode(NmInfo *nm_i, std::vector<nid_t> &nids) {
  auto is_same_nid = [](NatEntry &e, nid_t nid) { return e.ni.nid == nid; };

  for (auto iter = nids.begin(); iter != nids.end();) {
    if (NatEntry *ne = LookupList<NatEntry>(nm_i->dirty_nat_entries, *iter, is_same_nid)) {
      if (NatGetBlkaddr(ne) == kNullAddr) {
        iter = nids.erase(iter);
      } else {
        iter++;
      }
    }
  }
}

}  // namespace unittest_lib
}  // namespace f2fs
