// 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/inspect/contrib/cpp/archive_reader.h>
#include <lib/modular/testing/cpp/fake_component.h>
#include <lib/stdcompat/optional.h>

#include <gmock/gmock.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_config/modular_config_constants.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 {

using ::testing::HasSubstr;

constexpr char kBasemgrSelector[] = "*_inspect/basemgr.cmx:root";
constexpr char kBasemgrComponentName[] = "basemgr.cmx";

class BasemgrTest : public modular_testing::TestHarnessFixture {
 public:
  BasemgrTest() : executor_(dispatcher()) {}

  fit::result<inspect::contrib::DiagnosticsData> GetInspectDiagnosticsData() {
    auto archive = real_services()->Connect<fuchsia::diagnostics::ArchiveAccessor>();

    inspect::contrib::ArchiveReader reader(std::move(archive), {kBasemgrSelector});
    fit::result<std::vector<inspect::contrib::DiagnosticsData>, std::string> result;
    executor_.schedule_task(
        reader.SnapshotInspectUntilPresent({kBasemgrComponentName})
            .then([&](fit::result<std::vector<inspect::contrib::DiagnosticsData>, std::string>&
                          snapshot_result) { result = std::move(snapshot_result); }));
    RunLoopUntil([&] { return result.is_ok() || result.is_error(); });

    if (result.is_error()) {
      EXPECT_FALSE(result.is_error()) << "Error was " << result.error();
      return fit::error();
    }

    if (result.value().size() != 1) {
      EXPECT_EQ(1u, result.value().size()) << "Expected only one component";
      return fit::error();
    }

    return fit::ok(std::move(result.value()[0]));
  }

  async::Executor executor_;
};

// 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=*/cpp17::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);
}

// Tests that basemgr exposes its configuration in Inspect.
TEST_F(BasemgrTest, ExposesConfigInInspect) {
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();

  fuchsia::modular::testing::TestHarnessSpec spec;
  spec.set_environment_suffix("inspect");

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptSessionShell(session_shell->BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

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

  auto inspect_result = GetInspectDiagnosticsData();
  ASSERT_TRUE(inspect_result.is_ok());
  auto inspect_data = inspect_result.take_value();

  // The inspect property should contain configuration that uses |session_shell|.
  const auto& config_value = inspect_data.GetByPath({"root", modular_config::kInspectConfig});
  ASSERT_TRUE(config_value.IsString());
  EXPECT_THAT(config_value.GetString(), HasSubstr(session_shell->url()));
}

}  // namespace
