// Copyright 2022 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/fdio/namespace.h>
#include <lib/sys/cpp/testing/test_with_environment_fixture.h>
#include <lib/zx/channel.h>
#include <lib/zx/process.h>
#include <zircon/process.h>
#include <zircon/rights.h>
#include <zircon/syscalls/object.h>

#include "src/lib/fxl/memory/weak_ptr.h"
#include "src/sys/appmgr/realm.h"

using fuchsia::sys::ServiceList;
using fuchsia::sys::ServiceListPtr;

namespace component {
namespace {

class NamespaceGuard {
 public:
  explicit NamespaceGuard(fxl::RefPtr<Namespace> ns) : ns_(std::move(ns)) {}
  NamespaceGuard(std::nullptr_t) : ns_(nullptr) {}
  ~NamespaceGuard() { Kill(); }
  Namespace* operator->() const { return ns_.get(); }

  fxl::RefPtr<Namespace>& ns() { return ns_; }

  void Kill() {
    if (ns_) {
      ns_->FlushAndShutdown(ns_);
    }
    ns_ = nullptr;
  }

 private:
  fxl::RefPtr<Namespace> ns_;
};

class RealmTest : public gtest::TestWithEnvironmentFixture {
 protected:
  RealmTest() {}
  NamespaceGuard MakeNamespace(ServiceListPtr additional_services,
                               NamespaceGuard parent = nullptr) {
    if (parent.ns().get() == nullptr) {
      return NamespaceGuard(
          fxl::MakeRefCounted<Namespace>(nullptr, std::move(additional_services), nullptr));
    }
    return NamespaceGuard(Namespace::CreateChildNamespace(parent.ns(), nullptr,
                                                          std::move(additional_services), nullptr));
  }

  zx_status_t AddService(const std::string& name) {
    auto cb = [this, name](zx::channel channel, async_dispatcher_t* dispatcher) {
      ++connection_ctr_[name];
    };
    return directory_.AddEntry(name, std::make_unique<vfs::Service>(cb));
  }

  vfs::PseudoDir directory_;
  std::map<std::string, int> connection_ctr_;
};

// This test checks that if the process can not be created that structures are cleaned up.
TEST_F(RealmTest, ProcessCreationFailure) {
  // Create a namespace to be used for the component.
  ServiceListPtr service_list(new ServiceList);
  static constexpr char kService1[] = "fuchsia.test.TestService1";
  static constexpr char kService2[] = "fuchsia.test.TestService2";
  service_list->names.push_back(kService1);
  service_list->names.push_back(kService2);
  AddService(kService1);
  AddService(kService2);

  auto ns = MakeNamespace(std::move(service_list));
  fdio_ns_t* fdio_ns;
  fdio_ns_create(&fdio_ns);

  zx::channel ch0, ch1;
  auto status = zx::channel::create(0, &ch0, &ch1);
  ASSERT_EQ(status, ZX_OK);

  static constexpr char kNSService1[] = "/svc/fuchsia.ns.TestService";
  fdio_ns_bind(fdio_ns, kNSService1, ch1.get());

  fdio_flat_namespace_t* flat_ns;
  fdio_ns_export(fdio_ns, &flat_ns);

  zx_handle_t job = zx_job_default();
  zx_handle_t child;
  status = zx_job_create(job, 0, &child);
  ASSERT_EQ(status, ZX_OK);

  zx_handle_t child_dupe;
  status = zx_handle_duplicate(child, ZX_RIGHT_SAME_RIGHTS, &child_dupe);
  ASSERT_EQ(status, ZX_OK);

  zx::job child_job = zx::job(child);
  zx::channel exception_channel;
  child_job.create_exception_channel(0, &exception_channel);

  // Create a child process object, but don't actually create a process.
  zx::process child_process = zx::process();
  ASSERT_FALSE(child_process);

  // Pass in some placeholder values, since the process is invalidd, nothing
  // here will actually be used.
  Realm* no_realm = nullptr;
  std::string args = "";
  fuchsia::sys::ComponentControllerPtr component_controller;
  ComponentRequestWrapper component_req =
      ComponentRequestWrapper(component_controller.NewRequest());
  std::string url = "";
  ExportedDirChannels channels = ExportedDirChannels();
  fit::function<void(std::weak_ptr<ComponentControllerImpl> component)> callback =
      [](std::weak_ptr<ComponentControllerImpl> component) {};
  zx::channel pkg_hnd;

  ASSERT_EQ(ns.ns()->status(), Namespace::Status::RUNNING);

  zx_info_job_t job_info;
  size_t info_actual, info_available;
  status = zx_object_get_info(child_dupe, ZX_INFO_JOB, &job_info, sizeof(zx_info_job_t),
                              &info_actual, &info_available);
  ASSERT_EQ(status, ZX_OK);
  ASSERT_EQ(false, job_info.exited);

  // Execute an immediate wait on all the flat namespace handles to check they
  // are valid.
  for (size_t i = 0; i < flat_ns->count; i++) {
    zx_signals_t observed;
    status = zx_object_wait_one(flat_ns->handle[i], ZX_CHANNEL_PEER_CLOSED, ZX_TIME_INFINITE_PAST,
                                &observed);
    ASSERT_NE(ZX_ERR_BAD_HANDLE, status);
  }

  Realm::InstallRuntime(no_realm, std::move(child_job), std::move(child_process), ns.ns(), flat_ns,
                        args, std::move(component_req), url, std::move(channels),
                        std::move(callback), std::move(pkg_hnd), std::move(exception_channel));

  // Check that all the things we expect to be torn down are torn down.

  // The job should have exited.
  status = zx_object_get_info(child_dupe, ZX_INFO_JOB, &job_info, sizeof(zx_info_job_t),
                              &info_actual, &info_available);
  ASSERT_EQ(status, ZX_OK);
  ASSERT_EQ(true, job_info.exited);

  // Execute a wait that will return immediately and expect all theh handles to
  // be be invalid since they should have been closed.
  for (size_t i = 0; i < flat_ns->count; i++) {
    zx_signals_t observed;
    status = zx_object_wait_one(flat_ns->handle[i], ZX_CHANNEL_PEER_CLOSED, ZX_TIME_INFINITE_PAST,
                                &observed);
    ASSERT_EQ(ZX_ERR_BAD_HANDLE, status);
  }

  // The namespace should not be marked running.
  ASSERT_NE(ns.ns()->status(), Namespace::Status::RUNNING);

  fdio_ns_free_flat_ns(flat_ns);
  fdio_ns_destroy(fdio_ns);
}

}  // namespace
}  // namespace component
