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

#include "sandbox.h"

#include <fcntl.h>
#include <fuchsia/net/cpp/fidl.h>
#include <fuchsia/netemul/guest/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl.h>
#include <fuchsia/virtualization/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/vfs.h>
#include <lib/fdio/watcher.h>
#include <lib/fit/promise.h>
#include <lib/fit/sequencer.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/sys/cpp/termination_reason.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>

#include <src/lib/pkg_url/fuchsia_pkg_url.h>
#include <src/virtualization/lib/guest_config/guest_config.h>
#include <src/virtualization/tests/guest_console.h>

#include "src/lib/cmx/cmx.h"
#include "src/lib/fsl/io/fd.h"
#include "src/lib/fxl/strings/concatenate.h"

using namespace fuchsia::netemul;

namespace netemul {

static const char* kDebianGuestUrl = "fuchsia-pkg://fuchsia.com/debian_guest#meta/debian_guest.cmx";
static const char* kEthertapEndpointMountPath = "class/ethernet/";
static const char* kNetworkDeviceEndpointMountPath = "class/network/";
static const char* kGuestManagerUrl =
    "fuchsia-pkg://fuchsia.com/guest_manager#meta/guest_manager.cmx";
static const char* kGuestDiscoveryUrl =
    "fuchsia-pkg://fuchsia.com/guest_discovery_service#meta/"
    "guest_discovery_service.cmx";
static const char* kNetstackIntermediaryUrl =
    "fuchsia-pkg://fuchsia.com/netemul-sandbox#meta/netstack-intermediary.cmx";

#define STATIC_MSG_STRUCT(name, msgv) \
  struct name {                       \
    static const char* msg;           \
  };                                  \
  const char* name::msg = msgv;

STATIC_MSG_STRUCT(kMsgApp, "app");
STATIC_MSG_STRUCT(kMsgTest, "test");

// Sandbox uses two threads to operate:
// a main thread (which it's initialized with)
// + a helper thread.
// The macros below are used to assert that methods on
// the sandbox class are called on the proper thread
#define ASSERT_DISPATCHER(disp) ZX_ASSERT((disp) == async_get_default_dispatcher())
#define ASSERT_MAIN_DISPATCHER ASSERT_DISPATCHER(main_dispatcher_)
#define ASSERT_HELPER_DISPATCHER ASSERT_DISPATCHER(helper_loop_->dispatcher())

Sandbox::Sandbox(SandboxArgs args) : env_config_(std::move(args.config)) {
  auto services = sys::ServiceDirectory::CreateFromNamespace();
  services->Connect(parent_env_.NewRequest());
  services->Connect(loader_.NewRequest());
  parent_env_.set_error_handler(
      [](zx_status_t err) { FX_LOGS(ERROR) << "Lost connection to parent environment"; });
}

Sandbox::~Sandbox() {
  ASSERT_MAIN_DISPATCHER;
  if (helper_loop_) {
    helper_loop_->Quit();
    helper_loop_->JoinThreads();
    // Remove all pending process handlers before shutting
    // down the loop to prevent error callbacks from
    // being fired.
    procs_.clear();
    helper_loop_ = nullptr;
  }
}

void Sandbox::Start(async_dispatcher_t* dispatcher) {
  main_dispatcher_ = dispatcher;
  setup_done_ = false;
  test_spawned_ = false;

  if (!parent_env_ || !loader_) {
    Terminate(SandboxResult::Status::INTERNAL_ERROR, "Missing parent environment or loader");
    return;
  } else if (env_config_.disabled()) {
    Terminate(SandboxResult::Status::SUCCESS, "Test is disabled");
    return;
  }

  helper_loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigNoAttachToCurrentThread);
  if (helper_loop_->StartThread("helper-thread") != ZX_OK) {
    Terminate(SandboxResult::Status::INTERNAL_ERROR, "Can't start config thread");
    return;
  }
  helper_executor_ = std::make_unique<async::Executor>(helper_loop_->dispatcher());

  SandboxEnv::Events global_events;
  global_events.service_terminated = [this](const std::string& service, int64_t exit_code,
                                            TerminationReason reason) {
    if (helper_loop_ && (reason != TerminationReason::EXITED || exit_code != 0)) {
      async::PostTask(helper_loop_->dispatcher(), [this, service]() {
        std::stringstream ss;
        ss << service << " terminated prematurely";
        PostTerminate(SandboxResult::Status::SERVICE_EXITED, ss.str());
      });
    }
  };

  global_events.devfs_terminated = [this]() {
    if (helper_loop_) {
      async::PostTask(helper_loop_->dispatcher(), [this]() {
        PostTerminate(SandboxResult::Status::INTERNAL_ERROR,
                      "Isolated devmgr terminated prematurely");
      });
    }
  };
  global_events.network_tun_terminated = [this]() {
    if (helper_loop_) {
      async::PostTask(helper_loop_->dispatcher(), [this]() {
        PostTerminate(SandboxResult::Status::INTERNAL_ERROR, "network-tun terminated prematurely");
      });
    }
  };

  sandbox_env_ = std::make_shared<SandboxEnv>(sys::ServiceDirectory::CreateFromNamespace(),
                                              std::move(global_events));
  sandbox_env_->set_default_name(env_config_.default_url());
  sandbox_env_->set_devfs_enabled(true);

  if (services_created_callback_) {
    services_created_callback_();
  }

  StartEnvironments();
}

void Sandbox::Terminate(SandboxResult result) {
  // all processes must have been emptied to call callback
  ASSERT_MAIN_DISPATCHER;
  ZX_ASSERT(procs_.empty());

  if (helper_loop_) {
    helper_loop_->Quit();
    helper_loop_->JoinThreads();
    helper_loop_ = nullptr;
  }

  if (!result.is_success() || env_config_.capture() == config::CaptureMode::ALWAYS) {
    // check if any of the network dumps have data, and just dump them to
    // stdout:
    if (net_dumps_ && net_dumps_->HasData()) {
      std::cout << "PCAP dump for all network data ===================" << std::endl;
      net_dumps_->dump().DumpHex(&std::cout);
      std::cout << "================================================" << std::endl;
    }
  }

  if (termination_callback_) {
    termination_callback_(std::move(result));
  }
}

void Sandbox::Terminate(netemul::SandboxResult::Status status, std::string description) {
  Terminate(SandboxResult(status, std::move(description)));
}

void Sandbox::PostTerminate(SandboxResult result) {
  ASSERT_HELPER_DISPATCHER;
  // kill all component controllers before posting termination
  procs_.clear();
  async::PostTask(main_dispatcher_,
                  [this, result = std::move(result)]() mutable { Terminate(std::move(result)); });
}

void Sandbox::PostTerminate(netemul::SandboxResult::Status status, std::string description) {
  PostTerminate(SandboxResult(status, std::move(description)));
}

Sandbox::Promise Sandbox::RunRootConfiguration(ManagedEnvironment::Options root_options) {
  fit::bridge<void, SandboxResult> bridge;
  async::PostTask(main_dispatcher_, [this, completer = std::move(bridge.completer),
                                     root_options = std::move(root_options)]() mutable {
    ASSERT_MAIN_DISPATCHER;
    root_ = ManagedEnvironment::CreateRoot(parent_env_, sandbox_env_, std::move(root_options));
    root_->SetRunningCallback([this, completer = std::move(completer)]() mutable {
      if (root_environment_created_callback_) {
        root_environment_created_callback_(root_.get());
      }
      completer.complete_ok();
    });
  });

  return bridge.consumer.promise().and_then([this]() { return ConfigureRootEnvironment(); });
}

Sandbox::Promise Sandbox::RunGuestConfiguration(ManagedEnvironment::Options guest_options) {
  fit::bridge<void, SandboxResult> bridge;
  async::PostTask(main_dispatcher_, [this, completer = std::move(bridge.completer),
                                     guest_options = std::move(guest_options)]() mutable {
    ASSERT_MAIN_DISPATCHER;
    guest_ = ManagedEnvironment::CreateRoot(parent_env_, sandbox_env_, std::move(guest_options));
    sandbox_env_->guest_env_ = guest_;
    guest_->SetRunningCallback(
        [completer = std::move(completer)]() mutable { completer.complete_ok(); });
  });

  return bridge.consumer.promise().and_then([this]() { return ConfigureGuestEnvironment(); });
}

void Sandbox::StartEnvironments() {
  ASSERT_MAIN_DISPATCHER;

  async::PostTask(helper_loop_->dispatcher(), [this]() {
    if (!ConfigureNetworks()) {
      PostTerminate(SandboxResult(SandboxResult::Status::NETWORK_CONFIG_FAILED));
      return;
    }

    ManagedEnvironment::Options root_options;
    if (!CreateEnvironmentOptions(env_config_.environment(), &root_options)) {
      PostTerminate(SandboxResult::Status::ENVIRONMENT_CONFIG_FAILED,
                    "Root environment can't load options");
      return;
    }

    ManagedEnvironment::Options guest_options;
    if (!CreateGuestOptions(env_config_.guests(), &guest_options)) {
      PostTerminate(SandboxResult::Status::ENVIRONMENT_CONFIG_FAILED, "Invalid guest config");
      return;
    }

    if (env_config_.guests().empty()) {
      fit::schedule_for_consumer(
          helper_executor_.get(),
          RunRootConfiguration(std::move(root_options)).or_else([this](SandboxResult& result) {
            PostTerminate(std::move(result));
          }));
    } else {
      fit::schedule_for_consumer(
          helper_executor_.get(),
          RunGuestConfiguration(std::move(guest_options))
              .and_then([this, root_options = std::move(root_options)]() mutable {
                return RunRootConfiguration(std::move(root_options));
              })
              .or_else([this](SandboxResult& result) { PostTerminate(std::move(result)); }));
    }
  });
}

// configure networks runs in an auxiliary thread, so we can use
// synchronous calls to the fidl service
bool Sandbox::ConfigureNetworks() {
  ASSERT_HELPER_DISPATCHER;
  // start by configuring the networks:

  if (env_config_.networks().empty()) {
    return true;
  }

  network::NetworkContextSyncPtr net_ctx;

  auto req = net_ctx.NewRequest();

  // bind to network context
  async::PostTask(main_dispatcher_, [req = std::move(req), this]() mutable {
    sandbox_env_->network_context().GetHandler()(std::move(req));
  });

  network::NetworkManagerSyncPtr net_manager;
  network::EndpointManagerSyncPtr endp_manager;
  net_ctx->GetNetworkManager(net_manager.NewRequest());
  net_ctx->GetEndpointManager(endp_manager.NewRequest());

  for (const auto& net_cfg : env_config_.networks()) {
    zx_status_t status;
    fidl::InterfaceHandle<network::Network> network_h;
    if (net_manager->CreateNetwork(net_cfg.name(), network::NetworkConfig(), &status, &network_h) !=
            ZX_OK ||
        status != ZX_OK) {
      FX_LOGS(ERROR) << "Create network failed";
      return false;
    }

    auto network = network_h.BindSync();

    if (env_config_.capture() != config::CaptureMode::NONE) {
      if (!net_dumps_) {
        net_dumps_ = std::make_unique<NetWatcher<InMemoryDump>>();
      }
      fidl::InterfacePtr<network::FakeEndpoint> fake_endpoint;
      network->CreateFakeEndpoint(fake_endpoint.NewRequest());
      net_dumps_->Watch(net_cfg.name(), std::move(fake_endpoint));
    }

    for (const auto& endp_cfg : net_cfg.endpoints()) {
      network::EndpointConfig fidl_config;
      fidl::InterfaceHandle<network::Endpoint> endp_h;

      fidl_config.backing = endp_cfg.backing();
      fidl_config.mtu = endp_cfg.mtu();
      if (endp_cfg.mac()) {
        fidl_config.mac = std::make_unique<fuchsia::net::MacAddress>();
        endp_cfg.mac()->Clone(fidl_config.mac.get());
      }

      if (endp_manager->CreateEndpoint(endp_cfg.name(), std::move(fidl_config), &status, &endp_h) !=
              ZX_OK ||
          status != ZX_OK) {
        FX_LOGS(ERROR) << "Create endpoint failed";
        return false;
      }

      auto endp = endp_h.BindSync();

      if (endp_cfg.up()) {
        if (endp->SetLinkUp(true) != ZX_OK) {
          FX_LOGS(ERROR) << "Set endpoint up failed";
          return false;
        }
      }

      // add endpoint to network:
      if (network->AttachEndpoint(endp_cfg.name(), &status) != ZX_OK || status != ZX_OK) {
        FX_LOGS(ERROR) << "Attaching endpoint " << endp_cfg.name() << " to network "
                       << net_cfg.name() << " failed";
        return false;
      }

      // save the endpoint handle:
      network_handles_.emplace_back(endp.Unbind().TakeChannel());
    }

    // save the network handle:
    network_handles_.emplace_back(network.Unbind().TakeChannel());
  }

  return true;
}

// Create environment options runs in an auxiliary thread, so we can use
// synchronous calls to fidl services
bool Sandbox::CreateEnvironmentOptions(const config::Environment& config,
                                       ManagedEnvironment::Options* options) {
  ASSERT_HELPER_DISPATCHER;
  options->set_name(config.name());
  options->set_inherit_parent_launch_services(config.inherit_services());

  std::vector<environment::VirtualDevice>* devices = options->mutable_devices();
  if (!config.devices().empty()) {
    network::EndpointManagerSyncPtr epm;
    async::PostTask(main_dispatcher_, [req = epm.NewRequest(), this]() mutable {
      sandbox_env_->network_context().endpoint_manager().Bind(std::move(req));
    });
    for (const auto& device : config.devices()) {
      auto& nd = devices->emplace_back();

      fidl::InterfaceHandle<network::Endpoint> endp_h;
      auto status = epm->GetEndpoint(device, &endp_h);
      if (status != ZX_OK || !endp_h.is_valid()) {
        FX_LOGS(ERROR) << "Can't find endpoint " << device << " on endpoint manager";
        return false;
      }

      auto endp = endp_h.BindSync();
      if (endp->GetProxy(nd.device.NewRequest()) != ZX_OK) {
        FX_LOGS(ERROR) << "Can't get proxy on endpoint " << device;
        return false;
      }
      network::EndpointConfig ep_config;
      if (endp->GetConfig(&ep_config) != ZX_OK) {
        FX_LOGS(ERROR) << "Can't get endpoint configuration " << device;
      }
      std::string_view base_path(ep_config.backing == network::EndpointBacking::ETHERTAP
                                     ? kEthertapEndpointMountPath
                                     : kNetworkDeviceEndpointMountPath);
      nd.path = fxl::Concatenate({base_path, device});
    }
  }

  std::vector<environment::LaunchService>* services = options->mutable_services();
  for (const auto& svc : config.services()) {
    auto& ns = services->emplace_back();
    ns.name = svc.name();
    ns.url = svc.launch().GetUrlOrDefault(sandbox_env_->default_name());
    ns.arguments = svc.launch().arguments();
  }

  // Logger options
  fuchsia::netemul::environment::LoggerOptions* logger_options = options->mutable_logger_options();
  const config::LoggerOptions& config_logger_options = config.logger_options();
  logger_options->set_enabled(config_logger_options.enabled());
  logger_options->set_klogs_enabled(config_logger_options.klogs_enabled());

  fuchsia::logger::LogFilterOptions* log_filter_options = logger_options->mutable_filter_options();
  const config::LoggerFilterOptions& config_logger_filter_options = config_logger_options.filters();
  log_filter_options->verbosity = config_logger_filter_options.verbosity();
  log_filter_options->tags = config_logger_filter_options.tags();

  return true;
}

bool Sandbox::CreateGuestOptions(const std::vector<config::Guest>& guests,
                                 ManagedEnvironment::Options* options) {
  if (guests.empty()) {
    return true;
  }

  environment::LoggerOptions* logger = options->mutable_logger_options();
  logger->set_enabled(true);
  logger->set_syslog_output(true);

  std::vector<environment::LaunchService>* services = options->mutable_services();
  {
    auto& ls = services->emplace_back();
    ls.name = fuchsia::virtualization::Manager::Name_;
    ls.url = kGuestManagerUrl;
  }
  {
    auto& ls = services->emplace_back();
    ls.name = fuchsia::netemul::guest::GuestDiscovery::Name_;
    ls.url = kGuestDiscoveryUrl;
  }

  std::vector<std::string> netstack_args;
  for (const config::Guest& guest : guests) {
    for (const std::pair<std::string, std::string>& mac_ethertap_mapping : guest.macs()) {
      netstack_args.push_back("--interface=" + mac_ethertap_mapping.first + "=" +
                              mac_ethertap_mapping.second);
    }
  }

  if (!netstack_args.empty()) {
    auto& ls = services->emplace_back();
    ls.name = fuchsia::netstack::Netstack::Name_;
    ls.url = kNetstackIntermediaryUrl;
    ls.arguments = std::move(netstack_args);
  }

  return true;
}

Sandbox::Promise Sandbox::ConfigureRootEnvironment() {
  ASSERT_HELPER_DISPATCHER;
  // connect to environment:
  auto svc = std::make_shared<environment::ManagedEnvironmentSyncPtr>();
  auto req = svc->NewRequest();

  async::PostTask(main_dispatcher_,
                  [this, req = std::move(req)]() mutable { root_->Bind(std::move(req)); });

  return ConfigureEnvironment(std::move(svc), &env_config_.environment(), true);
}

Sandbox::Promise Sandbox::ConfigureGuestEnvironment() {
  ASSERT_HELPER_DISPATCHER;
  auto svc = std::make_shared<environment::ManagedEnvironmentSyncPtr>();
  auto req = svc->NewRequest();

  async::PostTask(main_dispatcher_,
                  [this, req = std::move(req)]() mutable { guest_->Bind(std::move(req)); });

  return StartGuests(std::move(svc), &env_config_);
}

Sandbox::Promise Sandbox::StartChildEnvironment(ConfiguringEnvironmentPtr parent,
                                                const config::Environment* config) {
  ASSERT_HELPER_DISPATCHER;

  return fit::make_promise(
             [this, parent, config]() -> fit::result<ConfiguringEnvironmentPtr, SandboxResult> {
               ManagedEnvironment::Options options;
               if (!CreateEnvironmentOptions(*config, &options)) {
                 return fit::error(SandboxResult(SandboxResult::Status::ENVIRONMENT_CONFIG_FAILED));
               }
               auto child_env = std::make_shared<environment::ManagedEnvironmentSyncPtr>();
               if ((*parent)->CreateChildEnvironment(child_env->NewRequest(), std::move(options)) !=
                   ZX_OK) {
                 return fit::error(SandboxResult(SandboxResult::Status::ENVIRONMENT_CONFIG_FAILED));
               }

               return fit::ok(std::move(child_env));
             })
      .and_then([this, config](ConfiguringEnvironmentPtr& child_env) {
        return ConfigureEnvironment(std::move(child_env), config);
      });
}

Sandbox::Promise Sandbox::LaunchGuestEnvironment(ConfiguringEnvironmentPtr env,
                                                 const config::Guest& guest) {
  ASSERT_HELPER_DISPATCHER;

  return fit::make_promise([this, env, &guest]()
                               -> fit::promise<fuchsia::virtualization::GuestPtr, SandboxResult> {
           // Launch the guest
           fuchsia::virtualization::GuestConfig cfg;
           cfg.set_virtio_gpu(false);

           if (!guest.macs().empty()) {
             for (const std::pair<std::string, std::string>& mac_ethertap_mapping : guest.macs()) {
               fuchsia::virtualization::NetSpec out{};
               uint32_t bytes[6];
               std::sscanf(mac_ethertap_mapping.first.c_str(), "%02x:%02x:%02x:%02x:%02x:%02x",
                           &bytes[0], &bytes[1], &bytes[2], &bytes[3], &bytes[4], &bytes[5]);
               for (size_t i = 0; i != 6; ++i) {
                 out.mac_address.octets[i] = static_cast<uint8_t>(bytes[i]);
               }
               out.enable_bridge = false;
               cfg.mutable_net_devices()->push_back(out);
             }

             // Prevent the guest from receiving a default MAC address from the VirtioNet
             // internals.
             cfg.set_default_net(false);
           }

           fuchsia::virtualization::GuestPtr guest_controller;

           fit::bridge<fuchsia::virtualization::GuestPtr, SandboxResult> bridge;
           realm_->LaunchInstance(
               guest.guest_image_url(), guest.guest_label(), std::move(cfg),
               guest_controller.NewRequest(),
               [completer = std::move(bridge.completer),
                guest_controller = std::move(guest_controller)](uint32_t cid) mutable {
                 completer.complete_ok(std::move(guest_controller));
               });

           return bridge.consumer.promise();
         })
      .and_then([](const fuchsia::virtualization::GuestPtr& guest_controller)
                    -> fit::promise<zx::socket, SandboxResult> {
        fit::bridge<zx::socket, SandboxResult> bridge;
        guest_controller->GetSerial(
            [completer = std::move(bridge.completer)](zx::socket socket) mutable {
              if (!socket.is_valid()) {
                completer.complete_error(SandboxResult(SandboxResult::Status::SETUP_FAILED,
                                                       "Could not create guest socket connection"));
              }
              completer.complete_ok(std::move(socket));
            });

        return bridge.consumer.promise();
      })
      .and_then([&guest](zx::socket& socket) -> PromiseResult {
        // Wait until the guest's serial console becomes usable to ensure that the guest has
        // finished booting.
        GuestConsole serial(std::make_unique<ZxSocket>(std::move(socket)));
        zx_status_t status = serial.Start();

        if (status != ZX_OK) {
          return fit::error(SandboxResult(SandboxResult::Status::SETUP_FAILED,
                                          "Could not start guest serial connection"));
        }

        if (guest.guest_image_url() == kDebianGuestUrl) {
          // Wait for journalctl to show that the guest_discovery_service is listening on the
          // vsock.
          while (true) {
            std::string output;
            zx_status_t status = serial.ExecuteBlocking(
                "journalctl -u guest_interaction_daemon | grep Listening", "$", &output);
            // If the command cannot be executed, break out of the loop so the test can fail.
            if (status != ZX_OK) {
              return fit::error(
                  SandboxResult(SandboxResult::Status::SETUP_FAILED,
                                "Could not communicate with guest over serial connection"));
            }

            // Ensure that the output from the command indicates that guest_interaction_daemon is
            // listening on the vsock.
            if (output.find("Listening") != std::string::npos) {
              break;
            }
          }
        }

        return fit::ok();
      });
}

Sandbox::Promise Sandbox::SendGuestFiles(ConfiguringEnvironmentPtr env,
                                         const config::Guest& guest) {
  ASSERT_HELPER_DISPATCHER;

  return fit::make_promise([env, &guest]() {
    fuchsia::netemul::guest::GuestDiscoveryPtr gds;
    fuchsia::netemul::guest::GuestInteractionPtr gis;

    (*env)->ConnectToService(fuchsia::netemul::guest::GuestDiscovery::Name_,
                             gds.NewRequest().TakeChannel());

    gds->GetGuest(fuchsia::netemul::guest::DEFAULT_REALM, guest.guest_label(), gis.NewRequest());

    std::vector<Sandbox::Promise> transfer_promises;
    for (const auto& file_info : guest.files()) {
      fidl::InterfaceHandle<fuchsia::io::File> put_file;
      zx_status_t open_status =
          fdio_open(("/definition/" + file_info.first).c_str(), ZX_FS_RIGHT_READABLE,
                    put_file.NewRequest().TakeChannel().release());

      if (open_status != ZX_OK) {
        transfer_promises.clear();
        transfer_promises.emplace_back(fit::make_promise([file_info]() {
          return fit::error(SandboxResult(SandboxResult::Status::SETUP_FAILED,
                                          "Could not open " + file_info.first));
        }));
        break;
      }

      fit::bridge<void, SandboxResult> bridge;
      gis->PutFile(
          std::move(put_file), file_info.second,
          [file_info, completer = std::move(bridge.completer)](zx_status_t put_result) mutable {
            if (put_result != ZX_OK) {
              completer.complete_error(SandboxResult(SandboxResult::Status::SETUP_FAILED,
                                                     "Failed to copy " + file_info.first));
            } else {
              completer.complete_ok();
            }
          });
      transfer_promises.emplace_back(bridge.consumer.promise());
    }
    return fit::join_promise_vector(std::move(transfer_promises))
        .then([gis = std::move(gis)](
                  fit::result<std::vector<PromiseResult>>& result) -> PromiseResult {
          auto results = result.take_value();
          for (auto& r : results) {
            if (r.is_error()) {
              return r;
            }
          }
          return fit::ok();
        });
  });
}

Sandbox::Promise Sandbox::StartGuests(ConfiguringEnvironmentPtr env, const config::Config* config) {
  ASSERT_HELPER_DISPATCHER;
  if (!realm_) {
    fuchsia::virtualization::ManagerPtr guest_environment_manager;
    (*env)->ConnectToService(fuchsia::virtualization::Manager::Name_,
                             guest_environment_manager.NewRequest().TakeChannel());
    guest_environment_manager->Create(fuchsia::netemul::guest::DEFAULT_REALM, realm_.NewRequest());
  }

  std::vector<Sandbox::Promise> promises;

  for (const auto& guest : config->guests()) {
    promises.emplace_back(LaunchGuestEnvironment(env, guest).and_then(SendGuestFiles(env, guest)));
  }

  return fit::join_promise_vector(std::move(promises))
      .then([](fit::result<std::vector<PromiseResult>>& result) -> PromiseResult {
        auto results = result.take_value();
        for (auto& r : results) {
          if (r.is_error()) {
            return r;
          }
        }
        return fit::ok();
      });
}

Sandbox::Promise Sandbox::StartEnvironmentSetup(const config::Environment* config,
                                                ConfiguringEnvironmentLauncher launcher) {
  return fit::make_promise([this, config, launcher = std::move(launcher)] {
    auto prom = fit::make_result_promise(PromiseResult(fit::ok())).box();
    for (const auto& setup : config->setup()) {
      prom = prom.and_then([this, setup = &setup, launcher]() {
                   return LaunchSetup(launcher.get(),
                                      setup->GetUrlOrDefault(sandbox_env_->default_name()),
                                      setup->arguments());
                 })
                 .box();
    }
    return prom;
  });
}

Sandbox::Promise Sandbox::StartEnvironmentAppsAndTests(
    const netemul::config::Environment* config,
    netemul::Sandbox::ConfiguringEnvironmentLauncher launcher) {
  return fit::make_promise([this, config, launcher = std::move(launcher)]() -> PromiseResult {
    for (const auto& app : config->apps()) {
      auto& url = app.GetUrlOrDefault(sandbox_env_->default_name());
      if (!LaunchProcess<kMsgApp>(launcher.get(), url, app.arguments(), false)) {
        std::stringstream ss;
        ss << "Failed to launch app " << url;
        return fit::error(SandboxResult(SandboxResult::Status::INTERNAL_ERROR, ss.str()));
      }
    }

    for (const auto& test : config->test()) {
      auto& url = test.GetUrlOrDefault(sandbox_env_->default_name());
      if (!LaunchProcess<kMsgTest>(launcher.get(), url, test.arguments(), true)) {
        std::stringstream ss;
        ss << "Failed to launch test " << url;
        return fit::error(SandboxResult(SandboxResult::Status::INTERNAL_ERROR, ss.str()));
      }
      // save that at least one test was spawned.
      test_spawned_ = true;
    }

    return fit::ok();
  });
}

Sandbox::Promise Sandbox::StartEnvironmentInner(ConfiguringEnvironmentPtr env,
                                                const config::Environment* config) {
  ASSERT_HELPER_DISPATCHER;
  auto launcher = std::make_shared<fuchsia::sys::LauncherSyncPtr>();
  return fit::make_promise([launcher, env]() -> PromiseResult {
           // get launcher
           if ((*env)->GetLauncher(launcher->NewRequest()) != ZX_OK) {
             return fit::error(SandboxResult(SandboxResult::Status::INTERNAL_ERROR,
                                             "Can't get environment launcher"));
           }
           return fit::ok();
         })
      .and_then(StartEnvironmentSetup(config, launcher))
      .and_then(StartEnvironmentAppsAndTests(config, launcher));
}

Sandbox::Promise Sandbox::ConfigureEnvironment(ConfiguringEnvironmentPtr env,
                                               const config::Environment* config, bool root) {
  ASSERT_HELPER_DISPATCHER;

  std::vector<Sandbox::Promise> promises;

  // iterate on children
  for (const auto& child : config->children()) {
    // start each one of the child environments
    promises.emplace_back(StartChildEnvironment(env, &child));
  }

  // start this processes inside this environment
  promises.emplace_back(StartEnvironmentInner(env, config));

  return fit::join_promise_vector(std::move(promises))
      .then([this, root](fit::result<std::vector<PromiseResult>>& result) -> PromiseResult {
        auto results = result.take_value();
        for (auto& r : results) {
          if (r.is_error()) {
            return r;
          }
        }
        if (root) {
          EnableTestObservation();
        }
        return fit::ok();
      });
}

template <typename T>
bool Sandbox::LaunchProcess(fuchsia::sys::LauncherSyncPtr* launcher, const std::string& url,
                            const std::vector<std::string>& arguments, bool is_test) {
  ASSERT_HELPER_DISPATCHER;

  fuchsia::sys::LaunchInfo linfo;
  linfo.url = url;
  linfo.arguments = arguments;

  auto ticket = procs_.size();
  auto& proc = procs_.emplace_back();

  if (is_test) {
    RegisterTest(ticket);
  }

  proc.set_error_handler([this, url](zx_status_t status) {
    std::stringstream ss;
    ss << "Component controller for " << url << " reported error " << zx_status_get_string(status);
    PostTerminate(SandboxResult::Status::COMPONENT_FAILURE, ss.str());
  });

  // we observe test processes return code
  proc.events().OnTerminated = [url, this, is_test, ticket](int64_t code,
                                                            TerminationReason reason) {
    FX_LOGS(INFO) << T::msg << " " << url << " terminated with (" << code
                  << ") reason: " << sys::HumanReadableTerminationReason(reason);
    // remove the error handler:
    procs_[ticket].set_error_handler(nullptr);
    if (is_test) {
      if (reason == TerminationReason::EXITED) {
        if (code != 0) {
          // test failed, early bail
          PostTerminate(SandboxResult::Status::TEST_FAILED, url);
        } else {
          // unregister test ticket
          UnregisterTest(ticket);
        }
      } else {
        std::stringstream ss;
        ss << "Test component " << url
           << " failure: " << sys::HumanReadableTerminationReason(reason);
        PostTerminate(SandboxResult::Status::COMPONENT_FAILURE, ss.str());
      }
    }
  };

  if ((*launcher)->CreateComponent(std::move(linfo), proc.NewRequest()) != ZX_OK) {
    FX_LOGS(ERROR) << "couldn't launch " << T::msg << ": " << url;
    return false;
  }

  return true;
}

Sandbox::Promise Sandbox::LaunchSetup(fuchsia::sys::LauncherSyncPtr* launcher,
                                      const std::string& url,
                                      const std::vector<std::string>& arguments) {
  ASSERT_HELPER_DISPATCHER;

  fit::bridge<void, SandboxResult> bridge;

  fuchsia::sys::LaunchInfo linfo;
  linfo.url = url;
  linfo.arguments = arguments;

  auto ticket = procs_.size();
  auto& proc = procs_.emplace_back();

  if ((*launcher)->CreateComponent(std::move(linfo), proc.NewRequest()) != ZX_OK) {
    std::stringstream ss;
    ss << "Failed to launch setup " << url;
    bridge.completer.complete_error(SandboxResult(SandboxResult::Status::INTERNAL_ERROR, ss.str()));
  } else {
    proc.set_error_handler([this, url](zx_status_t status) {
      std::stringstream ss;
      ss << "Component controller for " << url << " reported error "
         << zx_status_get_string(status);
      PostTerminate(SandboxResult::Status::COMPONENT_FAILURE, ss.str());
    });

    // we observe test processes return code
    proc.events().OnTerminated = [url, this, ticket, completer = std::move(bridge.completer)](
                                     int64_t code, TerminationReason reason) mutable {
      FX_LOGS(INFO) << "Setup " << url << " terminated with (" << code
                    << ") reason: " << sys::HumanReadableTerminationReason(reason);
      // remove the error handler:
      procs_[ticket].set_error_handler(nullptr);
      if (code == 0 && reason == TerminationReason::EXITED) {
        completer.complete_ok();
      } else {
        completer.complete_error(SandboxResult(SandboxResult::Status::SETUP_FAILED, url));
      }
    };
  }

  return bridge.consumer.promise();
}

void Sandbox::EnableTestObservation() {
  ASSERT_HELPER_DISPATCHER;

  setup_done_ = true;

  // if we're not observing any tests,
  // consider it a failure.
  if (!test_spawned_) {
    FX_LOGS(ERROR) << "No tests were specified";
    PostTerminate(SandboxResult::EMPTY_TEST_SET);
    return;
  }

  if (tests_.empty()) {
    // all tests finished successfully
    PostTerminate(SandboxResult::SUCCESS);
    return;
  }

  // if a timeout is specified, start counting it from now:
  if (env_config_.timeout() != zx::duration::infinite()) {
    async::PostDelayedTask(
        helper_loop_->dispatcher(),
        [this]() {
          FX_LOGS(ERROR) << "Test timed out.";
          PostTerminate(SandboxResult::TIMEOUT);
        },
        env_config_.timeout());
  }
}

void Sandbox::RegisterTest(size_t ticket) {
  ASSERT_HELPER_DISPATCHER;

  tests_.insert(ticket);
}

void Sandbox::UnregisterTest(size_t ticket) {
  ASSERT_HELPER_DISPATCHER;

  tests_.erase(ticket);
  if (setup_done_ && tests_.empty()) {
    // all tests finished successfully
    PostTerminate(SandboxResult::SUCCESS);
  }
}

bool SandboxArgs::ParseFromJSON(const rapidjson::Value& facet, json::JSONParser* json_parser) {
  if (!config.ParseFromJSON(facet, json_parser)) {
    FX_LOGS(ERROR) << "netemul facet failed to parse: " << json_parser->error_str();
    return false;
  }
  return true;
}

bool SandboxArgs::ParseFromString(const std::string& config) {
  json::JSONParser json_parser;
  auto facet = json_parser.ParseFromString(config, "fuchsia.netemul facet");
  if (json_parser.HasError()) {
    FX_LOGS(ERROR) << "netemul facet failed to parse: " << json_parser.error_str();
    return false;
  }

  return ParseFromJSON(facet, &json_parser);
}

bool SandboxArgs::ParseFromCmxFileAt(int dir, const std::string& path) {
  component::CmxMetadata cmx;
  json::JSONParser json_parser;
  if (!cmx.ParseFromFileAt(dir, path, &json_parser)) {
    FX_LOGS(ERROR) << "cmx file failed to parse: " << json_parser.error_str();
    return false;
  }

  return ParseFromJSON(cmx.GetFacet(config::Config::Facet), &json_parser);
}

std::ostream& operator<<(std::ostream& os, const SandboxResult& result) {
  switch (result.status_) {
    case SandboxResult::Status::SUCCESS:
      os << "Success";
      break;
    case SandboxResult::Status::NETWORK_CONFIG_FAILED:
      os << "Network configuration failed";
      break;
    case SandboxResult::Status::SERVICE_EXITED:
      os << "Service exited";
      break;
    case SandboxResult::Status::ENVIRONMENT_CONFIG_FAILED:
      os << "Environment configuration failed";
      break;
    case SandboxResult::Status::TEST_FAILED:
      os << "Test failed";
      break;
    case SandboxResult::Status::COMPONENT_FAILURE:
      os << "Component failure";
      break;
    case SandboxResult::Status::SETUP_FAILED:
      os << "Setup failed";
      break;
    case SandboxResult::Status::EMPTY_TEST_SET:
      os << "Test set is empty";
      break;
    case SandboxResult::Status::TIMEOUT:
      os << "Timeout";
      break;
    case SandboxResult::Status::INTERNAL_ERROR:
      os << "Internal Error";
      break;
    case SandboxResult::Status::UNSPECIFIED:
      os << "Unspecified error";
      break;
    default:
      os << "Undefined(" << static_cast<uint32_t>(result.status_) << ")";
  }
  if (!result.description_.empty()) {
    os << ": " << result.description_;
  }
  return os;
}
}  // namespace netemul
