// Copyright 2018 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.

#ifndef LIB_SYS_CPP_TESTING_ENCLOSING_ENVIRONMENT_H_
#define LIB_SYS_CPP_TESTING_ENCLOSING_ENVIRONMENT_H_

#include <fuchsia/io/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/fidl/cpp/interface_handle.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/fit/function.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/sys/cpp/testing/launcher_impl.h>
#include <lib/vfs/cpp/pseudo_dir.h>
#include <lib/vfs/cpp/service.h>

#include <memory>
#include <string>
#include <unordered_map>

namespace sys {
namespace testing {

class EnclosingEnvironment;

// EnvironmentServices acts as a container of services to EnclosingEnvironment.
//
// By default, EnvironmentServices supplies only the parent environment's loader
// service. Additional services can be provided through |AddService| and
// friends. Typically, this is used to inject fake services for tests, or to
// pass through services from the parent environment.
//
// Every EnclosingEnvironment takes EnvironmentServices as an argument to
// instantiation. Services should not be added after the EnclosingEnvironment is
// created.
class EnvironmentServices {
 public:
  using ServiceTerminatedCallback = fit::function<void(
      const std::string&, int64_t, fuchsia::sys::TerminationReason)>;

  struct ParentOverrides final {
    ParentOverrides();

    ParentOverrides(const ParentOverrides&) = delete;
    ParentOverrides& operator=(const ParentOverrides&) = delete;
    ParentOverrides(ParentOverrides&&);

    std::shared_ptr<vfs::Service> loader_service_;
    std::shared_ptr<vfs::Service> debug_data_service_;
  };

  EnvironmentServices(const EnvironmentServices&) = delete;
  EnvironmentServices& operator=(const EnvironmentServices&) = delete;
  EnvironmentServices(EnvironmentServices&&) = delete;

  // Creates services with some of parent's service.
  static std::unique_ptr<EnvironmentServices> Create(
      const fuchsia::sys::EnvironmentPtr& parent_env,
      async_dispatcher_t* dispatcher = nullptr);

  // Creates services with custom parent overrides.
  static std::unique_ptr<EnvironmentServices> CreateWithParentOverrides(
      const fuchsia::sys::EnvironmentPtr& parent_env,
      ParentOverrides parent_overrides,
      async_dispatcher_t* dispatcher = nullptr);

  // Adds the specified interface to the set of services.
  //
  // Adds a supported service with the given |service_name|, using the given
  // |interface_request_handler|, which should remain valid for the lifetime
  // of this object.
  //
  // A typical usage may be:
  //
  //   AddService(foobar_bindings_.GetHandler(this));
  //
  template <typename Interface>
  zx_status_t AddService(fidl::InterfaceRequestHandler<Interface> handler,
                         const std::string& service_name = Interface::Name_) {
    svc_names_.push_back(service_name);
    return svc_.AddEntry(
        service_name,
        std::make_unique<vfs::Service>(
            [handler = std::move(handler)](zx::channel channel,
                                           async_dispatcher_t* dispatcher) {
              handler(fidl::InterfaceRequest<Interface>(std::move(channel)));
            }));
  }

  // Adds the specified service to the set of services.
  zx_status_t AddSharedService(const std::shared_ptr<vfs::Service>& service,
                               const std::string& service_name);

  // Adds the specified service to the set of services.
  zx_status_t AddService(std::unique_ptr<vfs::Service> service,
                         const std::string& service_name);

  // Adds the specified service to the set of services.
  //
  // Adds a supported service with the given |service_name|, using the given
  // |launch_info|, it only starts the component when the service is
  // requested.
  // Note: Only url and arguments fields of provided launch_info are used, if
  // you need to use other fields, use the Handler signature.
  zx_status_t AddServiceWithLaunchInfo(fuchsia::sys::LaunchInfo launch_info,
                                       const std::string& service_name);

  // Adds the specified service to the set of services.
  //
  // Adds a supported service with the given |service_name|, using the given
  // handler to generate launch info, it only starts the component when the
  // service is requested.
  // The provided singleton_id argument is used to keep track of singleton
  // instances, generally you want to use the URL that'll be used for launch
  // info.
  zx_status_t AddServiceWithLaunchInfo(
      std::string singleton_id,
      fit::function<fuchsia::sys::LaunchInfo()> handler,
      const std::string& service_name);

  // Allows child components to access parent service with name
  // |service_name|.
  //
  // This will only work if parent environment actually provides said service
  // and the service is in the test component's service whitelist.
  zx_status_t AllowParentService(const std::string& service_name);

  // Serve service directory using |flags| and returns a new |InterfaceHandle|;
  // Will cause exception if serving fails.
  fidl::InterfaceHandle<fuchsia::io::Directory> ServeServiceDir(
      uint32_t flags = fuchsia::io::OPEN_RIGHT_READABLE |
                       fuchsia::io::OPEN_RIGHT_WRITABLE);

  // Serves service directory using passed |request| and returns status.
  zx_status_t ServeServiceDir(
      fidl::InterfaceRequest<fuchsia::io::Directory> request,
      uint32_t flags = fuchsia::io::OPEN_RIGHT_READABLE |
                       fuchsia::io::OPEN_RIGHT_WRITABLE);

  // Serves service directory using passed |request| and returns status.
  zx_status_t ServeServiceDir(
      zx::channel request, uint32_t flags = fuchsia::io::OPEN_RIGHT_READABLE |
                                            fuchsia::io::OPEN_RIGHT_WRITABLE);

  // Sets a callback to be triggered whenever a singleton service launched
  // by |AddServiceWithLaunchInfo| terminates. The callback provides the
  // singleton identifier (typically fuchsia-pkg URL) and the termination
  // information.
  void SetServiceTerminatedCallback(ServiceTerminatedCallback callback) {
    service_terminated_callback_ = std::move(callback);
  }

 private:
  friend class EnclosingEnvironment;
  EnvironmentServices(const fuchsia::sys::EnvironmentPtr& parent_env,
                      ParentOverrides parent_overrides,
                      async_dispatcher_t* dispatcher = nullptr);

  void set_enclosing_env(EnclosingEnvironment* e) { enclosing_env_ = e; }

  vfs::PseudoDir svc_;
  fidl::VectorPtr<std::string> svc_names_;
  std::shared_ptr<sys::ServiceDirectory> parent_svc_;
  // Pointer to containing environment. Not owned.
  EnclosingEnvironment* enclosing_env_ = nullptr;
  async_dispatcher_t* dispatcher_;
  ServiceTerminatedCallback service_terminated_callback_;

  // Keep track of all singleton services, indexed by url.
  std::unordered_map<std::string, std::shared_ptr<sys::ServiceDirectory>>
      singleton_services_;
};

// EnclosingEnvironment wraps a new isolated environment for test |parent_env|
// and provides a way to use that environment for integration testing.
//
// It provides a way to add custom fake services using handlers and singleton
// components. By default components under this environment have no access to
// any of system services. You need to add your own services by using
// |AddService| or |AddServiceWithLaunchInfo| methods.
//
// It also provides a way to access parent services if needed.
class EnclosingEnvironment {
 public:
  // Creates environment with the given services.
  //
  // |label| is human readable environment name, it can be seen in /hub, for eg
  // /hub/r/sys/<koid>/r/<label>/<koid>
  //
  // |services| are the services the environment will provide. See
  // |EnvironmentServices| for details.
  static std::unique_ptr<EnclosingEnvironment> Create(
      const std::string& label, const fuchsia::sys::EnvironmentPtr& parent_env,
      std::unique_ptr<EnvironmentServices> services,
      const fuchsia::sys::EnvironmentOptions& options = {});

  ~EnclosingEnvironment();

  fuchsia::sys::LauncherPtr launcher_ptr() {
    fuchsia::sys::LauncherPtr launcher;
    launcher_.AddBinding(launcher.NewRequest());
    return launcher;
  }

  // Returns true if underlying environment is running.
  bool is_running() const { return running_; }

  // Kills the underlying environment.
  void Kill(fit::function<void()> callback = nullptr);

  // Creates a real component from |launch_info| in underlying environment.
  //
  // That component will only have access to the services added and
  // any allowed parent service.
  void CreateComponent(
      fuchsia::sys::LaunchInfo launch_info,
      fidl::InterfaceRequest<fuchsia::sys::ComponentController> request);

  // Creates a real component from |launch_info| in underlying environment and
  // returns controller ptr.
  //
  // That component will only have access to the services added and
  // any allowed parent service.
  fuchsia::sys::ComponentControllerPtr CreateComponent(
      fuchsia::sys::LaunchInfo launch_info);

  // Creates a real component in underlying environment for a url and returns
  // controller ptr.
  //
  // That component will only have access to the services added and
  // any allowed parent service.
  fuchsia::sys::ComponentControllerPtr CreateComponentFromUrl(
      std::string component_url);

  // Creates a nested enclosing environment on top of underlying environment.
  std::unique_ptr<EnclosingEnvironment> CreateNestedEnclosingEnvironment(
      const std::string& label);

  // Creates a nested enclosing environment on top of underlying environment
  // with custom loader service.
  std::unique_ptr<EnclosingEnvironment>
  CreateNestedEnclosingEnvironmentWithLoader(
      const std::string& label, std::shared_ptr<vfs::Service> loader_service);

  // Connects to service provided by this environment.
  void ConnectToService(fidl::StringPtr service_name, zx::channel channel) {
    service_provider_->Connect(service_name, std::move(channel));
  }

  // Connects to service provided by this environment.
  template <typename Interface>
  void ConnectToService(fidl::InterfaceRequest<Interface> request,
                        const std::string& service_name = Interface::Name_) {
    ConnectToService(service_name, request.TakeChannel());
  }

  // Connects to service provided by this environment.
  template <typename Interface>
  fidl::InterfacePtr<Interface> ConnectToService(
      const std::string& service_name = Interface::Name_) {
    fidl::InterfacePtr<Interface> ptr;
    ConnectToService(service_name, ptr.NewRequest().TakeChannel());
    return ptr;
  }

  // Sets a listener for changes in the running status
  void SetRunningChangedCallback(fit::function<void(bool)> cb) {
    running_changed_callback_ = std::move(cb);
  }

 private:
  EnclosingEnvironment(const std::string& label,
                       const fuchsia::sys::EnvironmentPtr& parent_env,
                       std::unique_ptr<EnvironmentServices> services,
                       const fuchsia::sys::EnvironmentOptions& options);

  void SetRunning(bool running);

  bool running_ = false;
  const std::string label_;
  fuchsia::sys::EnvironmentControllerPtr env_controller_;
  std::shared_ptr<sys::ServiceDirectory> service_provider_;
  LauncherImpl launcher_;
  std::unique_ptr<EnvironmentServices> services_;
  fit::function<void(bool)> running_changed_callback_;
};

}  // namespace testing
}  // namespace sys

#endif  // LIB_SYS_CPP_TESTING_ENCLOSING_ENVIRONMENT_H_
