// Copyright 2019 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/io/cpp/fidl.h>
#include <lib/async/dispatcher.h>
#include <lib/vfs/cpp/lazy_dir.h>
#include <lib/vfs/cpp/pseudo_file.h>
#include <lib/vfs/cpp/testing/dir_test_util.h>
#include <zircon/errors.h>
#include <zircon/status.h>

#include <memory>

#include "src/lib/testing/loop_fixture/real_loop_fixture.h"

namespace {

using vfs_tests::Dirent;

class TestLazyDir : public vfs::LazyDir {
 public:
  struct TestContent {
   public:
    TestContent(std::string name, std::unique_ptr<vfs::internal::Node> node)
        : name_(std::move(name)), node_(std::move(node)) {}
    std::string name_;
    std::unique_ptr<vfs::internal::Node> node_;
  };

  TestLazyDir() : next_id_(GetStartingId()), loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {
    loop_.StartThread("vfs test thread");
  }

  void AddContent(TestContent content) { contents_.emplace(next_id_++, std::move(content)); }

  void ClearContent() {
    contents_.clear();
    next_id_ = GetStartingId();
  }

  fuchsia::io::DirectorySyncPtr ServeForTest(
      fuchsia::io::OpenFlags flags = fuchsia::io::OpenFlags::RIGHT_READABLE) {
    fuchsia::io::DirectorySyncPtr ptr;
    Serve(flags, ptr.NewRequest().TakeChannel(), loop_.dispatcher());
    return ptr;
  }

  async_dispatcher_t* dispatcher() { return loop_.dispatcher(); }

 protected:
  void GetContents(LazyEntryVector* out_vector) const override {
    out_vector->reserve(contents_.size());
    for (const auto& content : contents_) {
      out_vector->push_back({content.first, content.second.name_, fuchsia::io::MODE_TYPE_FILE});
    }
  }

  zx_status_t GetFile(Node** out_node, uint64_t id, std::string name) const override {
    auto search = contents_.find(id);
    if (search != contents_.end()) {
      *out_node = search->second.node_.get();
      return ZX_OK;
    }

    return ZX_ERR_NOT_FOUND;
  }

 private:
  uint64_t next_id_;
  std::map<uint64_t, TestContent> contents_;
  async::Loop loop_;
};

class LazyDirConnection : public vfs_tests::DirConnection {
 protected:
  vfs::internal::Directory* GetDirectoryNode() override { return &dir_; }

  TestLazyDir::TestContent CreateTestFile(std::string name, std::string content) {
    auto file = std::make_unique<vfs::PseudoFile>(
        content.length(),
        [content = std::move(content)](std::vector<uint8_t>* output, size_t max_file_size) {
          output->resize(content.length());
          std::copy(content.begin(), content.end(), output->begin());
          return ZX_OK;
        });
    return TestLazyDir::TestContent(std::move(name), std::move(file));
  }

  TestLazyDir dir_;
};

TEST_F(LazyDirConnection, ReadDirEmpty) {
  auto ptr = dir_.ServeForTest();

  std::vector<Dirent> expected_dirents = {
      Dirent::DirentForDot(),
  };
  AssertReadDirents(ptr, 1024, expected_dirents);
}

TEST_F(LazyDirConnection, ReadSimple) {
  auto ptr = dir_.ServeForTest();

  dir_.AddContent(CreateTestFile("file1", "file1"));

  std::vector<Dirent> expected_dirents = {Dirent::DirentForDot(), Dirent::DirentForFile("file1")};
  AssertReadDirents(ptr, 1024, expected_dirents);
}

TEST_F(LazyDirConnection, DynamicRead) {
  auto ptr = dir_.ServeForTest();

  dir_.AddContent(CreateTestFile("file1", "file1"));
  dir_.AddContent(CreateTestFile("file2", "file2"));

  std::vector<Dirent> expected_dirents = {Dirent::DirentForDot(), Dirent::DirentForFile("file1"),
                                          Dirent::DirentForFile("file2")};
  AssertReadDirents(ptr, 1024, expected_dirents);

  dir_.ClearContent();

  dir_.AddContent(CreateTestFile("file3", "file3"));

  // should not get any dirent before we rewind.
  expected_dirents = {};
  AssertReadDirents(ptr, 1024, expected_dirents);

  AssertRewind(ptr);

  expected_dirents = {Dirent::DirentForDot(), Dirent::DirentForFile("file3")};
  AssertReadDirents(ptr, 1024, expected_dirents);
}

TEST_F(LazyDirConnection, MultipleReads) {
  auto ptr = dir_.ServeForTest();

  dir_.AddContent(CreateTestFile("file1", "file1"));
  dir_.AddContent(CreateTestFile("file2", "file2"));
  dir_.AddContent(CreateTestFile("file3", "file3"));
  dir_.AddContent(CreateTestFile("file4", "file4"));

  std::vector<Dirent> expected_dirents = {Dirent::DirentForDot(), Dirent::DirentForFile("file1"),
                                          Dirent::DirentForFile("file2")};
  AssertReadDirents(ptr, 3 * sizeof(vdirent_t) + 15, expected_dirents);

  expected_dirents = {Dirent::DirentForFile("file3"), Dirent::DirentForFile("file4")};

  AssertReadDirents(ptr, 1024, expected_dirents);
  expected_dirents = {};
  AssertReadDirents(ptr, 1024, expected_dirents);
}

TEST_F(LazyDirConnection, LookupWorks) {
  dir_.AddContent(CreateTestFile("file1", "file1"));
  dir_.AddContent(CreateTestFile("file2", "file2"));
  dir_.AddContent(CreateTestFile("file3", "file3"));
  dir_.AddContent(CreateTestFile("file4", "file4"));
  vfs::internal::Node* n;
  ASSERT_EQ(ZX_OK, dir_.Lookup("file3", &n));
  fuchsia::io::FileSyncPtr file_ptr;
  n->Serve(fuchsia::io::OpenFlags::RIGHT_READABLE, file_ptr.NewRequest().TakeChannel(),
           dir_.dispatcher());

  fuchsia::io::File2_Read_Result result;
  file_ptr->Read(20, &result);
  ASSERT_TRUE(result.is_response()) << zx_status_get_string(result.err());
  std::string str = "file3";
  std::vector<uint8_t> expected_data(str.begin(), str.end());
  ASSERT_EQ(expected_data, result.response().data);
}

TEST_F(LazyDirConnection, LookupReturnsNotFound) {
  dir_.AddContent(CreateTestFile("file1", "file1"));
  dir_.AddContent(CreateTestFile("file2", "file2"));
  dir_.AddContent(CreateTestFile("file3", "file3"));
  dir_.AddContent(CreateTestFile("file4", "file4"));
  vfs::internal::Node* n;
  ASSERT_EQ(ZX_ERR_NOT_FOUND, dir_.Lookup("file5", &n));
}

}  // namespace
