// 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 "lib/vfs/cpp/service.h"

#include <fidl/examples/echo/cpp/fidl.h>
#include <lib/fdio/vfs.h>
#include <lib/fidl/cpp/binding_set.h>

#include "lib/gtest/real_loop_fixture.h"
#include "lib/vfs/cpp/pseudo_dir.h"

class ServiceTest : public gtest::RealLoopFixture,
                    public fidl::examples::echo::Echo {
  void EchoString(fidl::StringPtr value, EchoStringCallback callback) override {
    callback(answer_);
  }

 protected:
  ServiceTest()
      : answer_("my_fake_ans"),
        service_name_("echo_service"),
        second_loop_(&kAsyncLoopConfigNoAttachToThread) {
    auto service = std::make_unique<vfs::Service>(
        bindings_.GetHandler(this, second_loop_.dispatcher()));

    dir_.Serve(
        fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
        dir_ptr_.NewRequest().TakeChannel(), second_loop_.dispatcher());
    dir_.AddEntry(service_name_, std::move(service));
    second_loop_.StartThread("vfs test thread");
  }

  const std::string& answer() const { return answer_; }

  const std::string& service_name() const { return service_name_; }

  void AssertInvalidOpen(uint32_t flag, uint32_t mode,
                         zx_status_t expected_status) {
    SCOPED_TRACE("flag: " + std::to_string(flag) +
                 ", mode: " + std::to_string(mode));
    fuchsia::io::NodePtr node_ptr;
    dir_ptr()->Open(flag | fuchsia::io::OPEN_FLAG_DESCRIBE, mode,
                    service_name(), node_ptr.NewRequest());

    bool on_open_called = false;

    node_ptr.events().OnOpen =
        [&](zx_status_t status, std::unique_ptr<fuchsia::io::NodeInfo> unused) {
          EXPECT_FALSE(on_open_called);  // should be called only once
          on_open_called = true;
          EXPECT_EQ(expected_status, status);
        };

    RunLoopUntil([&]() { return on_open_called; }, zx::msec(1));
  }

  fuchsia::io::DirectoryPtr& dir_ptr() { return dir_ptr_; }

 private:
  std::string answer_;
  std::string service_name_;
  fidl::BindingSet<Echo> bindings_;
  vfs::PseudoDir dir_;
  fuchsia::io::DirectoryPtr dir_ptr_;
  async::Loop second_loop_;
};

TEST_F(ServiceTest, CanOpenAsNodeReferenceAndTestGetAttr) {
  fuchsia::io::NodeSyncPtr ptr;
  dir_ptr()->Open(fuchsia::io::OPEN_FLAG_NODE_REFERENCE, 0, service_name(),
                  ptr.NewRequest());

  zx_status_t s;
  fuchsia::io::NodeAttributes attr;
  ptr->GetAttr(&s, &attr);
  EXPECT_EQ(ZX_OK, s);
  EXPECT_EQ(fuchsia::io::MODE_TYPE_SERVICE,
            attr.mode & fuchsia::io::MODE_TYPE_SERVICE);
}

TEST_F(ServiceTest, CanCloneNodeReference) {
  fuchsia::io::NodeSyncPtr cloned_ptr;
  {
    fuchsia::io::NodeSyncPtr ptr;
    dir_ptr()->Open(fuchsia::io::OPEN_FLAG_NODE_REFERENCE, 0, service_name(),
                    ptr.NewRequest());

    ptr->Clone(0, cloned_ptr.NewRequest());
  }

  zx_status_t s;
  fuchsia::io::NodeAttributes attr;
  cloned_ptr->GetAttr(&s, &attr);
  EXPECT_EQ(ZX_OK, s);
  EXPECT_EQ(fuchsia::io::MODE_TYPE_SERVICE,
            attr.mode & fuchsia::io::MODE_TYPE_SERVICE);
}

TEST_F(ServiceTest, TestDescribe) {
  fuchsia::io::NodeSyncPtr ptr;
  dir_ptr()->Open(fuchsia::io::OPEN_FLAG_NODE_REFERENCE, 0, service_name(),
                  ptr.NewRequest());

  fuchsia::io::NodeInfo info;
  ptr->Describe(&info);
  EXPECT_TRUE(info.is_service());
}

TEST_F(ServiceTest, CanOpenAsAService) {
  uint32_t flags[] = {fuchsia::io::OPEN_RIGHT_READABLE,
                      fuchsia::io::OPEN_RIGHT_WRITABLE};
  uint32_t modes[] = {
      0, fuchsia::io::MODE_TYPE_SERVICE, V_IRWXU, V_IRUSR, V_IWUSR, V_IXUSR};

  for (uint32_t mode : modes) {
    for (uint32_t flag : flags) {
      SCOPED_TRACE("flag: " + std::to_string(flag) +
                   ", mode: " + std::to_string(mode));
      fidl::examples::echo::EchoSyncPtr ptr;
      dir_ptr()->Open(flag, mode, service_name(),
                      fidl::InterfaceRequest<fuchsia::io::Node>(
                          ptr.NewRequest().TakeChannel()));

      fidl::StringPtr ans;
      ptr->EchoString("hello", &ans);
      EXPECT_EQ(answer(), ans);
    }
  }
}

TEST_F(ServiceTest, CannotOpenServiceWithInvalidFlags) {
  uint32_t flags[] = {
      fuchsia::io::OPEN_FLAG_CREATE, fuchsia::io::OPEN_FLAG_CREATE_IF_ABSENT,
      fuchsia::io::OPEN_FLAG_TRUNCATE, fuchsia::io::OPEN_FLAG_APPEND,
      fuchsia::io::OPEN_FLAG_NO_REMOTE};

  for (uint32_t flag : flags) {
    AssertInvalidOpen(flag | fuchsia::io::OPEN_RIGHT_READABLE |
                          fuchsia::io::OPEN_RIGHT_WRITABLE,
                      0, ZX_ERR_NOT_SUPPORTED);
  }
  AssertInvalidOpen(fuchsia::io::OPEN_RIGHT_ADMIN, 0, ZX_ERR_ACCESS_DENIED);
  AssertInvalidOpen(
      fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_FLAG_DIRECTORY, 0,
      ZX_ERR_NOT_DIR);
}

TEST_F(ServiceTest, CannotOpenServiceWithInvalidMode) {
  uint32_t modes[] = {
      fuchsia::io::MODE_TYPE_DIRECTORY, fuchsia::io::MODE_TYPE_BLOCK_DEVICE,
      fuchsia::io::MODE_TYPE_FILE, fuchsia::io::MODE_TYPE_SOCKET};

  for (uint32_t mode : modes) {
    AssertInvalidOpen(fuchsia::io::OPEN_RIGHT_READABLE, mode,
                      ZX_ERR_INVALID_ARGS);
  }
}
