// Copyright 2020 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/testing/modular/cpp/fidl.h>
#include <lib/modular/testing/cpp/fake_component.h>

#include <sdk/lib/modular/testing/cpp/fake_agent.h>

#include "src/lib/fsl/vmo/strings.h"
#include "src/modular/lib/fidl/clone.h"
#include "src/modular/lib/modular_config/modular_config.h"
#include "src/modular/lib/modular_test_harness/cpp/fake_session_launcher_component.h"
#include "src/modular/lib/modular_test_harness/cpp/fake_session_shell.h"
#include "src/modular/lib/modular_test_harness/cpp/test_harness_fixture.h"
#include "src/modular/lib/pseudo_dir/pseudo_dir_server.h"

namespace {

class BasemgrTest : public modular_testing::TestHarnessFixture {};

// Tests that when multiple session shell are provided the first is picked
TEST_F(BasemgrTest, StartFirstShellWhenMultiple) {
  fuchsia::modular::testing::TestHarnessSpec spec;
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  // Session shells used in list
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();
  auto session_shell2 = modular_testing::FakeSessionShell::CreateWithDefaultOptions();

  // Create session shell list (appended in order)
  builder.InterceptSessionShell(session_shell->BuildInterceptOptions());
  builder.InterceptSessionShell(session_shell2->BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

  // Run until one is started
  RunLoopUntil([&] { return session_shell->is_running() || session_shell2->is_running(); });

  // Assert only first one is started
  EXPECT_TRUE(session_shell->is_running());
  EXPECT_FALSE(session_shell2->is_running());
}

// Tests that basemgr starts the configured session launcher component when basemgr starts.
TEST_F(BasemgrTest, StartsSessionComponent) {
  fuchsia::modular::testing::TestHarnessSpec spec;
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  auto session_launcher_component =
      modular_testing::FakeSessionLauncherComponent::CreateWithDefaultOptions();

  builder.InterceptSessionLauncherComponent(session_launcher_component->BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return session_launcher_component->is_running(); });

  EXPECT_TRUE(session_launcher_component->is_running());
}

// Tests that basemgr starts the configured session launcher component with the given args.
TEST_F(BasemgrTest, StartsSessionComponentWithArgs) {
  static const std::string kTestArg = "--foo";

  fuchsia::modular::testing::TestHarnessSpec spec;
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  fidl::VectorPtr<std::string> startup_args = std::nullopt;
  builder.InterceptSessionLauncherComponent(
      {.url = modular_testing::TestHarnessBuilder::GenerateFakeUrl(),
       .launch_handler = [&startup_args](
                             fuchsia::sys::StartupInfo startup_info,
                             fidl::InterfaceHandle<fuchsia::modular::testing::InterceptedComponent>
                             /* unused */) { startup_args = startup_info.launch_info.arguments; }},
      /*args=*/fit::make_optional<std::vector<std::string>>({kTestArg}));
  builder.BuildAndRun(test_harness());

  // Run until the session launcher component is started.
  RunLoopUntil([&] { return startup_args.has_value(); });

  ASSERT_TRUE(startup_args.has_value());
  ASSERT_EQ(1u, startup_args->size());
  EXPECT_EQ(kTestArg, startup_args->at(0));
}

// Tests that basemgr starts a session with the given configuration when instructed by
// the session launcher component.
TEST_F(BasemgrTest, StartsSessionWithConfig) {
  fuchsia::modular::testing::TestHarnessSpec spec;
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  auto session_launcher_component =
      modular_testing::FakeSessionLauncherComponent::CreateWithDefaultOptions();
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();

  builder.InterceptSessionLauncherComponent(session_launcher_component->BuildInterceptOptions());
  // The session shell is specified in the configuration generated by the session launcher
  // component, so avoid InterceptSessionShell(), which adds it to the configuration in |builder|.
  builder.InterceptComponent(session_shell->BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return session_launcher_component->is_running(); });

  EXPECT_TRUE(!session_shell->is_running());

  // Create the configuration that the session launcher component passes to basemgr.
  fuchsia::modular::session::SessionShellMapEntry entry;
  entry.mutable_config()->mutable_app_config()->set_url(session_shell->url());
  fuchsia::modular::session::ModularConfig config;
  config.mutable_basemgr_config()->mutable_session_shell_map()->push_back(std::move(entry));

  fuchsia::mem::Buffer config_buf;
  ASSERT_TRUE(fsl::VmoFromString(modular::ConfigToJsonString(config), &config_buf));

  // Launch the session.
  session_launcher_component->launcher()->LaunchSessionmgr(std::move(config_buf));

  // The configured session shell should start.
  RunLoopUntil([&] { return session_shell->is_running(); });

  EXPECT_TRUE(session_shell->is_running());
}

// Tests that the session launcher component can also provide services to sessionmgr's children.
TEST_F(BasemgrTest, SessionLauncherCanOfferServices) {
  fuchsia::modular::testing::TestHarnessSpec spec;
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  auto session_launcher_component =
      modular_testing::FakeSessionLauncherComponent::CreateWithDefaultOptions();
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();
  auto agent = modular_testing::FakeAgent::CreateWithDefaultOptions();

  builder.InterceptSessionLauncherComponent(session_launcher_component->BuildInterceptOptions());
  // The following components are specified in the configuration generated by the session launcher.
  builder.InterceptComponent(session_shell->BuildInterceptOptions());
  auto agent_options = agent->BuildInterceptOptions();
  agent_options.sandbox_services.push_back(fuchsia::testing::modular::TestProtocol::Name_);
  builder.InterceptComponent(std::move(agent_options));
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return session_launcher_component->is_running(); });

  EXPECT_TRUE(!session_shell->is_running());

  // Create the configuration that the session launcher component passes to basemgr.
  fuchsia::modular::session::SessionShellMapEntry entry;
  entry.mutable_config()->mutable_app_config()->set_url(session_shell->url());
  fuchsia::modular::session::ModularConfig config;
  config.mutable_basemgr_config()->mutable_session_shell_map()->push_back(std::move(entry));
  config.mutable_sessionmgr_config()->mutable_session_agents()->push_back(agent->url());

  fuchsia::mem::Buffer config_buf;
  ASSERT_TRUE(fsl::VmoFromString(modular::ConfigToJsonString(config), &config_buf));

  // Build a directory to serve services from the session launcher component.
  int connect_count = 0;
  auto dir = std::make_unique<vfs::PseudoDir>();
  dir->AddEntry(
      fuchsia::testing::modular::TestProtocol::Name_,
      std::make_unique<vfs::Service>([&](zx::channel, async_dispatcher_t*) { ++connect_count; }));
  auto dir_server = std::make_unique<modular::PseudoDirServer>(std::move(dir));

  // Construct a ServiceList with the above dir server.
  fuchsia::sys::ServiceList service_list;
  service_list.names.push_back(fuchsia::testing::modular::TestProtocol::Name_);
  service_list.host_directory = dir_server->Serve().Unbind().TakeChannel();

  // Launch the session.
  session_launcher_component->launcher()->LaunchSessionmgrWithServices(std::move(config_buf),
                                                                       std::move(service_list));

  // The configured session shell and agent should start.
  RunLoopUntil([&] { return session_shell->is_running() && agent->is_running(); });

  // Connect to the provided service from the agent.
  auto test_ptr =
      agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>();
  RunLoopUntil([&] { return connect_count > 0; });
  EXPECT_EQ(1, connect_count);

  // Test that the provided services can still be reached if the session is restarted
  // (fxbug.dev/61680).
  session_shell->Exit(1);
  RunLoopUntil([&] { return !session_shell->is_running() && !agent->is_running(); });
  RunLoopUntil([&] { return session_shell->is_running() && agent->is_running(); });
  auto test_ptr2 =
      agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>();
  RunLoopUntil([&] { return connect_count > 1; });
  EXPECT_EQ(2, connect_count);
}

// Tests that basemgr starts a new session with a new configuration, and stops the existing one
// when instructed to launch a new session by the session launcher component.
TEST_F(BasemgrTest, LaunchSessionmgrReplacesExistingSession) {
  // Instructs the session launcher component to launches a session with a configuration with the
  // given session shell URL, and waits until it's launched.
  auto launch_session_with_session_shell =
      [](modular_testing::FakeSessionLauncherComponent& session_launcher_component,
         std::string session_shell_url) {
        fuchsia::modular::session::SessionShellMapEntry entry;
        entry.mutable_config()->mutable_app_config()->set_url(std::move(session_shell_url));
        fuchsia::modular::session::ModularConfig config;
        config.mutable_basemgr_config()->mutable_session_shell_map()->push_back(std::move(entry));

        fuchsia::mem::Buffer config_buf;
        ASSERT_TRUE(fsl::VmoFromString(modular::ConfigToJsonString(config), &config_buf));

        session_launcher_component.launcher()->LaunchSessionmgr(std::move(config_buf));
      };

  fuchsia::modular::testing::TestHarnessSpec spec;
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  auto session_launcher_component =
      modular_testing::FakeSessionLauncherComponent::CreateWithDefaultOptions();
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();
  auto session_shell_2 = modular_testing::FakeSessionShell::CreateWithDefaultOptions();

  builder.InterceptSessionLauncherComponent(session_launcher_component->BuildInterceptOptions());
  builder.InterceptComponent(session_shell->BuildInterceptOptions());
  builder.InterceptComponent(session_shell_2->BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return session_launcher_component->is_running(); });
  EXPECT_TRUE(!session_shell->is_running());

  // Launch the first session.
  launch_session_with_session_shell(*session_launcher_component, session_shell->url());

  // The first session shell should start.
  RunLoopUntil([&] { return session_shell->is_running(); });
  EXPECT_TRUE(session_shell->is_running());

  // Launch the second session.
  launch_session_with_session_shell(*session_launcher_component, session_shell_2->url());

  // The second session shell should start, and the first shell should stop.
  RunLoopUntil([&] { return !session_shell->is_running() && session_shell_2->is_running(); });

  EXPECT_FALSE(session_shell->is_running());
  EXPECT_TRUE(session_shell_2->is_running());
}

// Tests that LaunchSessionmgr closes the channel with an ZX_ERR_INVALID_ARGS epitaph if the
// config buffer is not readable.
TEST_F(BasemgrTest, LaunchSessionmgrFailsGivenUnreadableBuffer) {
  fuchsia::modular::testing::TestHarnessSpec spec;
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  auto session_launcher_component =
      modular_testing::FakeSessionLauncherComponent::CreateWithDefaultOptions();

  builder.InterceptSessionLauncherComponent(session_launcher_component->BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return session_launcher_component->is_running(); });

  // Launch the session with a configuration Buffer that has an incorrect size.
  fuchsia::mem::Buffer config_buf;
  ASSERT_TRUE(fsl::VmoFromString("", &config_buf));
  config_buf.size = 1;

  // Connect to Launcher with a handler that lets us capture the error.
  fuchsia::modular::session::LauncherPtr launcher;
  session_launcher_component->component_context()->svc()->Connect(launcher.NewRequest());

  bool error_handler_called{false};
  zx_status_t error_status{ZX_OK};
  launcher.set_error_handler([&](zx_status_t status) {
    error_handler_called = true;
    error_status = status;
  });

  launcher->LaunchSessionmgr(std::move(config_buf));

  RunLoopUntil([&] { return error_handler_called; });

  EXPECT_EQ(ZX_ERR_INVALID_ARGS, error_status);
}

// Tests that LaunchSessionmgr closes the channel with an ZX_ERR_INVALID_ARGS epitaph if the
// config buffer does not contain valid Modular configuration JSON.
TEST_F(BasemgrTest, LaunchSessionmgrFailsGivenInvalidConfigJson) {
  fuchsia::modular::testing::TestHarnessSpec spec;
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  auto session_launcher_component =
      modular_testing::FakeSessionLauncherComponent::CreateWithDefaultOptions();

  builder.InterceptSessionLauncherComponent(session_launcher_component->BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return session_launcher_component->is_running(); });

  // Launch the session with a configuration that is not valid JSON.
  fuchsia::mem::Buffer config_buf;
  ASSERT_TRUE(fsl::VmoFromString("this is not valid json", &config_buf));

  // Connect to Launcher with a handler that lets us capture the error.
  fuchsia::modular::session::LauncherPtr launcher;
  session_launcher_component->component_context()->svc()->Connect(launcher.NewRequest());

  bool error_handler_called{false};
  zx_status_t error_status{ZX_OK};
  launcher.set_error_handler([&](zx_status_t status) {
    error_handler_called = true;
    error_status = status;
  });

  launcher->LaunchSessionmgr(std::move(config_buf));

  RunLoopUntil([&] { return error_handler_called; });

  EXPECT_EQ(ZX_ERR_INVALID_ARGS, error_status);
}

// Tests that LaunchSessionmgr closes the channel with an ZX_ERR_INVALID_ARGS epitaph if the
// config includes a session launcher component.
TEST_F(BasemgrTest, LaunchSessionmgrFailsGivenConfigWithSessionLauncher) {
  static constexpr auto kTestSessionLauncherUrl =
      "fuchsia-pkg://fuchsia.com/test_session_launcher#meta/test_session_launcher.cmx";

  fuchsia::modular::testing::TestHarnessSpec spec;
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  auto session_launcher_component =
      modular_testing::FakeSessionLauncherComponent::CreateWithDefaultOptions();

  builder.InterceptSessionLauncherComponent(session_launcher_component->BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return session_launcher_component->is_running(); });

  // Launch the session with a valid configuration that has `session_launcher` set.
  fuchsia::modular::session::ModularConfig config;
  config.mutable_basemgr_config()->mutable_session_launcher()->set_url(kTestSessionLauncherUrl);

  fuchsia::mem::Buffer config_buf;
  ASSERT_TRUE(fsl::VmoFromString(modular::ConfigToJsonString(config), &config_buf));

  // Connect to Launcher with a handler that lets us capture the error.
  fuchsia::modular::session::LauncherPtr launcher;
  session_launcher_component->component_context()->svc()->Connect(launcher.NewRequest());

  bool error_handler_called{false};
  zx_status_t error_status{ZX_OK};
  launcher.set_error_handler([&](zx_status_t status) {
    error_handler_called = true;
    error_status = status;
  });

  launcher->LaunchSessionmgr(std::move(config_buf));

  RunLoopUntil([&] { return error_handler_called; });

  EXPECT_EQ(ZX_ERR_INVALID_ARGS, error_status);
}

}  // namespace
