// Copyright 2019 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/element/cpp/fidl.h>
#include <fuchsia/hardware/power/statecontrol/cpp/fidl.h>
#include <fuchsia/hardware/power/statecontrol/cpp/fidl_test_base.h>
#include <fuchsia/intl/cpp/fidl.h>
#include <fuchsia/modular/internal/cpp/fidl.h>
#include <fuchsia/modular/testing/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/modular/testing/cpp/fake_agent.h>
#include <lib/syslog/cpp/macros.h>

#include <gmock/gmock.h>

#include "src/lib/files/glob.h"
#include "src/lib/fsl/vmo/strings.h"
#include "src/modular/bin/sessionmgr/annotations.h"
#include "src/modular/bin/sessionmgr/testing/annotations_matchers.h"
#include "src/modular/lib/modular_test_harness/cpp/fake_graphical_presenter.h"
#include "src/modular/lib/modular_test_harness/cpp/fake_module.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"

namespace {

constexpr char kTestStoryId[] = "test_story";

using element::annotations::AnnotationEq;
using ::testing::ByRef;
using ::testing::ElementsAre;

class SessionmgrIntegrationTest : public modular_testing::TestHarnessFixture {
 public:
  SessionmgrIntegrationTest()
      : fake_graphical_presenter_(
            modular_testing::FakeGraphicalPresenter::CreateWithDefaultOptions()),
        fake_module_(modular_testing::FakeModule::CreateWithDefaultOptions()) {}

  void LaunchTestHarness() {
    modular_testing::TestHarnessBuilder builder;
    builder.InterceptSessionShell(fake_graphical_presenter_->BuildInterceptOptions());
    builder.InterceptComponent(fake_module_->BuildInterceptOptions());
    builder.UseSessionShellForStoryShellFactory();

    bool graphical_presenter_connected = false;
    fake_graphical_presenter_->set_on_graphical_presenter_connected([&]() {
      graphical_presenter_connected = true;
      fake_graphical_presenter_->set_on_graphical_presenter_error([&](zx_status_t status) {});
    });
    fake_graphical_presenter_->set_on_graphical_presenter_error([&](zx_status_t status) {
      FX_PLOGS(FATAL, status) << "Failed to connect to FakeGraphicalPresenter";
    });

    // Create the test harness and verify the session shell is up
    builder.BuildAndRun(test_harness());

    EXPECT_FALSE(fake_graphical_presenter_->is_running());
    RunLoopUntil([&] { return fake_graphical_presenter_->is_running(); });
    RunLoopUntil([&] { return graphical_presenter_connected; });
  }

  fuchsia::modular::PuppetMasterPtr ConnectToPuppetMaster() {
    fuchsia::modular::PuppetMasterPtr puppet_master;
    fuchsia::modular::testing::ModularService svc;
    svc.set_puppet_master(puppet_master.NewRequest());
    test_harness()->ConnectToModularService(std::move(svc));
    return puppet_master;
  }

  fuchsia::modular::StoryPuppetMasterPtr ControlStory() {
    auto puppet_master = ConnectToPuppetMaster();
    fuchsia::modular::StoryPuppetMasterPtr story_puppet_master;
    puppet_master->ControlStory(kTestStoryId, story_puppet_master.NewRequest());
    return story_puppet_master;
  }

  // Watches for changes to story states on the session shell's StoryProvider and appends new
  // states to |sequence_of_story_states|.
  //
  // Expects that only the story with ID |kTestStoryId| is changed. This story does not have to
  // exist prior to calling WatchStoryStates.
  [[nodiscard]] std::unique_ptr<modular_testing::SimpleStoryProviderWatcher> WatchStoryStates(
      std::vector<fuchsia::modular::StoryState>* sequence_of_story_states) const {
    fuchsia::modular::StoryProvider* story_provider = fake_graphical_presenter_->story_provider();
    EXPECT_TRUE(story_provider != nullptr);

    // Have the StoryProviderWatcher record the sequence of story states it sees.
    auto watcher = std::make_unique<modular_testing::SimpleStoryProviderWatcher>();
    watcher->set_on_change_2([sequence_of_story_states](fuchsia::modular::StoryInfo2 story_info,
                                                        fuchsia::modular::StoryState story_state,
                                                        fuchsia::modular::StoryVisibilityState _) {
      EXPECT_TRUE(story_info.has_id());
      EXPECT_EQ(story_info.id(), kTestStoryId);
      sequence_of_story_states->push_back(story_state);
    });
    watcher->Watch(story_provider, /*on_get_stories=*/nullptr);

    return watcher;
  }

  void LaunchMod(
      fuchsia::modular::StoryPuppetMasterPtr* story_puppet_master,
      fit::function<void(fuchsia::modular::ExecuteResult result)> callback = [](auto result) {
      }) const {
    fuchsia::modular::Intent intent;
    intent.handler = fake_module_->url();
    intent.action = "action";

    fuchsia::modular::AddMod add_mod;
    add_mod.mod_name_transitional = "modname";
    add_mod.intent = std::move(intent);

    fuchsia::modular::StoryCommand cmd;
    cmd.set_add_mod(std::move(add_mod));

    std::vector<fuchsia::modular::StoryCommand> cmds;
    cmds.push_back(std::move(cmd));

    // Add the module to the story
    (*story_puppet_master)->Enqueue(std::move(cmds));
    (*story_puppet_master)->Execute(std::move(callback));
  }

  void StopStory() {
    fuchsia::modular::StoryControllerPtr story_controller;
    fake_graphical_presenter_->story_provider()->GetController(kTestStoryId,
                                                               story_controller.NewRequest());
    bool stop_called = false;
    story_controller->Stop([&] { stop_called = true; });
    RunLoopUntil([&] { return stop_called; });
  }

  std::unique_ptr<modular_testing::FakeGraphicalPresenter> fake_graphical_presenter_;
  std::unique_ptr<modular_testing::FakeModule> fake_module_;
  std::unique_ptr<modular_testing::FakeAgent> fake_agent_;
};

class SessionmgrIntegrationTestWithoutDefaultHarness : public sys::testing::TestWithEnvironment {};

class IntlPropertyProviderImpl : public fuchsia::intl::PropertyProvider {
 public:
  int call_count() { return call_count_; }

 private:
  void GetProfile(fuchsia::intl::PropertyProvider::GetProfileCallback callback) override {
    call_count_++;
    fuchsia::intl::Profile profile;
    callback(std::move(profile));
  }

  int call_count_ = 0;
};

class MockAdmin : public fuchsia::hardware::power::statecontrol::testing::Admin_TestBase {
 public:
  bool reboot_called() { return reboot_called_; }

 private:
  void Reboot(fuchsia::hardware::power::statecontrol::RebootReason reason,
              RebootCallback callback) override {
    ASSERT_FALSE(reboot_called_);
    reboot_called_ = true;
    ASSERT_EQ(fuchsia::hardware::power::statecontrol::RebootReason::SESSION_FAILURE, reason);
    callback(fuchsia::hardware::power::statecontrol::Admin_Reboot_Result::WithResponse(
        fuchsia::hardware::power::statecontrol::Admin_Reboot_Response(ZX_OK)));
  }

  // |TestBase|
  void NotImplemented_(const std::string& name) override {
    FX_NOTIMPLEMENTED() << name << " is not implemented";
  }

  bool reboot_called_ = false;
};

// A |FakeComponent| that invokes a callback when terminating
class FakeComponentWithOnTerminate : public modular_testing::FakeComponent {
 public:
  explicit FakeComponentWithOnTerminate(FakeComponent::Args args)
      : FakeComponent(std::move(args)) {}
  ~FakeComponentWithOnTerminate() override = default;

  void set_on_terminate(fit::function<void()> on_terminate) {
    on_terminate_ = std::move(on_terminate);
  }

 protected:
  // |fuchsia::modular::Lifecycle|
  void Terminate() override {
    on_terminate_();
    modular_testing::FakeComponent::Terminate();
  }

 private:
  fit::function<void()> on_terminate_ = []() {};
};

// Create a service in the test harness that is also not provided by the session environment. Verify
// story mods get the test service from the harness.
TEST_F(SessionmgrIntegrationTest, StoryModsGetServicesFromGlobalEnvironment) {
  modular_testing::TestHarnessBuilder builder;
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();
  builder.InterceptSessionShell(session_shell->BuildInterceptOptions());

  // Add a fake fuchsia::intl::PropertyProvider to the test harness' environment.
  IntlPropertyProviderImpl fake_intl_property_provider;
  fidl::BindingSet<fuchsia::intl::PropertyProvider> intl_property_provider_bindings;
  builder.AddService(intl_property_provider_bindings.GetHandler(&fake_intl_property_provider));

  // Register a fake component to be launched as a story mod
  auto fake_module_url = modular_testing::TestHarnessBuilder::GenerateFakeUrl("fake_module");
  modular_testing::FakeModule fake_module{
      {.url = fake_module_url, .sandbox_services = {"fuchsia.intl.PropertyProvider"}}};
  builder.InterceptComponent(fake_module.BuildInterceptOptions());

  // Create the test harness and verify the session shell is up
  builder.BuildAndRun(test_harness());
  ASSERT_FALSE(session_shell->is_running());
  RunLoopUntil([&] { return session_shell->is_running(); });

  // Add at least one module to the story. This should launch the fake_module.
  fuchsia::modular::Intent intent;
  intent.handler = fake_module_url;
  intent.action = "action";
  modular_testing::AddModToStory(test_harness(), "fake_story", "fake_modname", std::move(intent));

  ASSERT_FALSE(fake_module.is_running());
  RunLoopUntil([&] { return fake_module.is_running(); });

  // Request a fuchsia::intl::PropertyProvider from the story mod's component_context().
  // It should get the service from the test harness, confirming that the service
  // is accessible.
  fuchsia::intl::PropertyProviderPtr module_intl_property_provider;
  auto got_module_intl_property_provider =
      fake_module.component_context()->svc()->Connect<fuchsia::intl::PropertyProvider>(
          module_intl_property_provider.NewRequest());
  EXPECT_EQ(got_module_intl_property_provider, ZX_OK);
  bool got_profile_from_module_callback = false;
  zx_status_t get_profile_from_module_status = ZX_OK;
  module_intl_property_provider->GetProfile(
      [&](fuchsia::intl::Profile new_profile) { got_profile_from_module_callback = true; });
  module_intl_property_provider.set_error_handler(
      [&](zx_status_t status) { get_profile_from_module_status = status; });
  RunLoopUntil(
      [&] { return got_profile_from_module_callback || get_profile_from_module_status != ZX_OK; });
  ASSERT_EQ(get_profile_from_module_status, ZX_OK);
  ASSERT_EQ(fake_intl_property_provider.call_count(), 1);

  // The test_harness version of the service is available also if requested outside of
  // the session scope.
  fuchsia::intl::PropertyProviderPtr intl_property_provider;
  test_harness()->ConnectToEnvironmentService(fuchsia::intl::PropertyProvider::Name_,
                                              intl_property_provider.NewRequest().TakeChannel());

  bool got_profile_callback = false;
  zx_status_t got_profile_error = ZX_OK;
  intl_property_provider.set_error_handler([&](zx_status_t status) { got_profile_error = status; });
  intl_property_provider->GetProfile(
      [&](fuchsia::intl::Profile new_profile) { got_profile_callback = true; });
  RunLoopUntil([&] { return got_profile_callback || got_profile_error != ZX_OK; });
  ASSERT_EQ(got_profile_error, ZX_OK);
  ASSERT_EQ(fake_intl_property_provider.call_count(), 2);
}

TEST_F(SessionmgrIntegrationTest, PresentViewIsCalled) {
  LaunchTestHarness();

  // Add Event Listeners
  bool called_present_view = false;
  fake_graphical_presenter_->set_on_present_view(
      [&](fuchsia::element::ViewSpec view_spec,
          fidl::InterfaceHandle<fuchsia::element::AnnotationController> annotation_controller) {
        called_present_view = true;
      });

  bool called_dismiss = false;
  fake_graphical_presenter_->set_on_dismiss([&] {
    called_dismiss = true;
    fake_graphical_presenter_->CloseAllViewControllers();
  });

  std::vector<fuchsia::modular::StoryState> sequence_of_story_states;
  auto watcher = WatchStoryStates(&sequence_of_story_states);

  auto story_puppet_master = ControlStory();
  LaunchMod(&story_puppet_master);

  // Since this test is using a GraphicalPresenter PresentView should be called.
  RunLoopUntil([&] { return called_present_view; });

  StopStory();

  // Run the loop until there are the expected number of state changes;
  // having called Stop() is not enough to guarantee seeing all updates.
  RunLoopUntil([&] { return sequence_of_story_states.size() == 4; });

  // Confirm that:
  //  a. Dismiss was called.
  //  b. The story went through the correct sequence of states (see StoryState FIDL file for valid
  // state transitions). Since the test started it, ran it, and stopped it, the sequence is:
  // STOPPED -> RUNNING -> STOPPING -> STOPPED.
  ASSERT_TRUE(called_dismiss);
  ASSERT_THAT(sequence_of_story_states,
              testing::ElementsAre(
                  fuchsia::modular::StoryState::STOPPED, fuchsia::modular::StoryState::RUNNING,
                  fuchsia::modular::StoryState::STOPPING, fuchsia::modular::StoryState::STOPPED));
}

TEST_F(SessionmgrIntegrationTest, AnnotationsAreReflectedInAnnotationController) {
  LaunchTestHarness();

  constexpr char kTestAnnotationKey[] = "test_key";
  constexpr char kTestAnnotationValue[] = "test_value";
  constexpr char kTestAnnotationUpdateValue[] = "test_update_value";

  // Add Event Listeners
  bool called_present_view = false;
  fidl::InterfaceHandle<fuchsia::element::AnnotationController> annotation_controller_handle;
  fake_graphical_presenter_->set_on_present_view(
      [&](fuchsia::element::ViewSpec view_spec,
          fidl::InterfaceHandle<fuchsia::element::AnnotationController> annotation_controller) {
        called_present_view = true;
        ASSERT_TRUE(view_spec.has_annotations());

        auto expected_annotation = fuchsia::element::Annotation{
            .key = modular::annotations::ToElementAnnotationKey(kTestAnnotationKey),
            .value = fuchsia::element::AnnotationValue::WithText(kTestAnnotationValue)};
        ASSERT_THAT(view_spec.annotations(), ElementsAre(AnnotationEq(ByRef(expected_annotation))));

        annotation_controller_handle = std::move(annotation_controller);
      });

  // Create the story and add annotations
  std::vector<fuchsia::modular::StoryState> sequence_of_story_states;
  auto watcher = WatchStoryStates(&sequence_of_story_states);

  auto story_puppet_master = ControlStory();

  std::vector<fuchsia::modular::Annotation> annotations;
  annotations.push_back(fuchsia::modular::Annotation{
      .key = kTestAnnotationKey,
      .value = std::make_unique<fuchsia::modular::AnnotationValue>(
          fuchsia::modular::AnnotationValue::WithText(kTestAnnotationValue))});
  story_puppet_master->Annotate(std::move(annotations),
                                [&](fuchsia::modular::StoryPuppetMaster_Annotate_Result result) {
                                  ASSERT_FALSE(result.is_err());
                                });

  LaunchMod(&story_puppet_master);

  // Wait for PresentView to be called
  RunLoopUntil([&] { return called_present_view; });

  // Update Annotations
  std::vector<fuchsia::modular::Annotation> annotation_update;
  annotation_update.push_back(fuchsia::modular::Annotation{
      .key = kTestAnnotationKey,
      .value = std::make_unique<fuchsia::modular::AnnotationValue>(
          fuchsia::modular::AnnotationValue::WithText(kTestAnnotationUpdateValue))});
  bool updated_annotations{false};
  story_puppet_master->Annotate(std::move(annotation_update),
                                [&](fuchsia::modular::StoryPuppetMaster_Annotate_Result result) {
                                  ASSERT_FALSE(result.is_err());
                                  updated_annotations = true;
                                });
  RunLoopUntil([&]() { return updated_annotations; });

  // Get the annotations using the AnnotationController passed to PresentView
  auto annotation_controller = annotation_controller_handle.Bind();
  bool got_annotations{false};
  std::vector<fuchsia::element::Annotation> annotations_to_check;
  annotation_controller->GetAnnotations(
      [&](fuchsia::element::AnnotationController_GetAnnotations_Result result) {
        EXPECT_FALSE(result.is_err());
        annotations_to_check = std::move(result.response().annotations);
        got_annotations = true;
      });
  RunLoopUntil([&] { return got_annotations; });

  auto expected_annotation = fuchsia::element::Annotation{
      .key = modular::annotations::ToElementAnnotationKey(kTestAnnotationKey),
      .value = fuchsia::element::AnnotationValue::WithText(kTestAnnotationUpdateValue)};
  EXPECT_THAT(annotations_to_check, ElementsAre(AnnotationEq(ByRef(expected_annotation))));
  StopStory();
}

TEST_F(SessionmgrIntegrationTest, DeleteStoryWhenViewControllerIsClosed) {
  static constexpr char kTestStoryId1[] = "test_story_1";
  static constexpr char kTestStoryId2[] = "test_story_2";

  modular_testing::TestHarnessBuilder builder;
  auto fake_graphical_presenter =
      modular_testing::FakeGraphicalPresenter::CreateWithDefaultOptions();

  bool called_present_view = false;
  fake_graphical_presenter->set_on_present_view(
      [&](fuchsia::element::ViewSpec view_spec,
          fidl::InterfaceHandle<fuchsia::element::AnnotationController> annotation_controller) {
        called_present_view = true;
      });

  builder.InterceptSessionShell(fake_graphical_presenter->BuildInterceptOptions());
  builder.UseSessionShellForStoryShellFactory();

  bool graphical_presenter_connected = false;
  fake_graphical_presenter->set_on_graphical_presenter_connected(
      [&]() { graphical_presenter_connected = true; });
  fake_graphical_presenter->set_on_graphical_presenter_error([&](zx_status_t status) {
    FX_PLOGS(FATAL, status) << "Failed to connect to FakeGraphicalPresenter";
  });

  // Register two fake components to be launched as a story mods
  auto fake_module_1 = modular_testing::FakeModule::CreateWithDefaultOptions();
  builder.InterceptComponent(fake_module_1->BuildInterceptOptions());

  auto fake_module_2 = modular_testing::FakeModule::CreateWithDefaultOptions();
  builder.InterceptComponent(fake_module_2->BuildInterceptOptions());

  // Create the test harness and verify the session shell is up
  builder.BuildAndRun(test_harness());

  ASSERT_FALSE(fake_graphical_presenter->is_running());
  RunLoopUntil([&] { return fake_graphical_presenter->is_running(); });
  RunLoopUntil([&] { return graphical_presenter_connected; });

  std::vector<fuchsia::modular::StoryState> sequence_of_story_states;
  modular_testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2([&sequence_of_story_states](fuchsia::modular::StoryInfo2 story_info,
                                                      fuchsia::modular::StoryState story_state,
                                                      fuchsia::modular::StoryVisibilityState _) {
    sequence_of_story_states.push_back(story_state);
  });
  watcher.Watch(fake_graphical_presenter->story_provider(), /*on_get_stories=*/nullptr);

  // Add a modules to two different stories
  fuchsia::modular::Intent intent;
  intent.handler = fake_module_1->url();
  intent.action = "action";
  constexpr char kTestModuleName[] = "fake_module";
  modular_testing::AddModToStory(test_harness(), kTestStoryId1, kTestModuleName, std::move(intent));

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

  fuchsia::modular::Intent intent_2;
  intent_2.handler = fake_module_2->url();
  intent_2.action = "action";
  constexpr char kTestModuleName2[] = "fake_module_2";
  modular_testing::AddModToStory(test_harness(), kTestStoryId2, kTestModuleName2,
                                 std::move(intent_2));

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

  // Since this test is using a GraphicalPresenter PresentView should be called
  RunLoopUntil([&] { return called_present_view; });

  // Close the view controller and wait for the module to stop.
  fake_graphical_presenter->CloseFirstViewController();
  RunLoopUntil([&] { return !fake_module_1->is_running(); });

  // Run the loop until there are the expected number of state changes;
  // having called Stop() is not enough to guarantee seeing all updates.
  RunLoopUntil([&] { return sequence_of_story_states.size() == 6; });

  // Confirm that the story went through the correct sequence of states.
  // Since the test started it, ran it, and stopped it, the sequence is:
  // STOPPED -> RUNNING -> STOPPING -> STOPPED.
  ASSERT_THAT(sequence_of_story_states,
              testing::ElementsAre(
                  fuchsia::modular::StoryState::STOPPED, fuchsia::modular::StoryState::RUNNING,
                  fuchsia::modular::StoryState::STOPPED, fuchsia::modular::StoryState::RUNNING,
                  fuchsia::modular::StoryState::STOPPING, fuchsia::modular::StoryState::STOPPED));

  // Ensure that only the first module was stopped.
  ASSERT_TRUE(fake_module_2->is_running());
}

// Launch a session shell an ensure that it receives argv configured for it in the Modular Config.
TEST_F(SessionmgrIntegrationTest, SessionShellReceivesComponentArgsFromConfig) {
  const std::string session_shell_url = "fuchsia-pkg://fuchsia.com/fake_shell/#fake_shell.cmx";

  fuchsia::modular::testing::TestHarnessSpec spec;

  fuchsia::modular::session::SessionShellMapEntry entry;
  entry.mutable_config()->mutable_app_config()->set_url(session_shell_url);
  spec.mutable_basemgr_config()->mutable_session_shell_map()->push_back(std::move(entry));
  spec.mutable_basemgr_config()->set_use_session_shell_for_story_shell_factory(true);

  fuchsia::modular::testing::InterceptSpec intercept_spec;
  intercept_spec.set_component_url(session_shell_url);
  spec.mutable_components_to_intercept()->push_back(std::move(intercept_spec));

  fuchsia::modular::session::AppConfig component_arg;
  component_arg.set_url(session_shell_url);
  component_arg.mutable_args()->push_back("foo");
  spec.mutable_sessionmgr_config()->mutable_component_args()->push_back(std::move(component_arg));

  bool session_shell_running = false;
  test_harness().events().OnNewComponent =
      [&](fuchsia::sys::StartupInfo startup_info,
          fidl::InterfaceHandle<fuchsia::modular::testing::InterceptedComponent> component) {
        ASSERT_EQ(startup_info.launch_info.url, session_shell_url);
        ASSERT_TRUE(!!startup_info.launch_info.arguments);
        EXPECT_THAT(startup_info.launch_info.arguments.value(), ::testing::ElementsAre("foo"));
        session_shell_running = true;
      };

  test_harness()->Run(std::move(spec));
  RunLoopUntil([&] { return session_shell_running; });
}

TEST_F(SessionmgrIntegrationTest, RebootCalledIfSessionmgrCrashNumberReachesRetryLimit) {
  MockAdmin mock_admin;
  fidl::BindingSet<fuchsia::hardware::power::statecontrol::Admin> admin_bindings;

  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();
  modular_testing::TestHarnessBuilder builder;
  builder.InterceptSessionShell(session_shell->BuildInterceptOptions());
  builder.AddService(admin_bindings.GetHandler(&mock_admin));
  builder.BuildAndRun(test_harness());

  // kill session_shell
  for (int i = 0; i < 4; i++) {
    RunLoopUntil([&] { return session_shell->is_running(); });
    session_shell->Exit(0);
    RunLoopUntil([&] { return !session_shell->is_running(); });
  }
  // Validate suspend is invoked

  RunLoopUntil([&] { return mock_admin.reboot_called(); });
  EXPECT_TRUE(mock_admin.reboot_called());
}

TEST_F(SessionmgrIntegrationTest, RestartSession) {
  // Setup environment with a suffix to enable globbing for basemgr's debug service
  fuchsia::modular::testing::TestHarnessSpec spec;
  spec.set_environment_suffix("test");
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  // Setup a MockAdmin to check if sessionmgr restarts too many times. If the MockAdmin calls
  // suspend, then sessionmgr has reached its retry limit and we've failed to succesfully restart
  // the session.
  MockAdmin mock_admin;
  fidl::BindingSet<fuchsia::hardware::power::statecontrol::Admin> admin_bindings;

  // Use a session shell to determine if a session has been started.
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();
  builder.InterceptSessionShell(session_shell->BuildInterceptOptions());
  builder.AddService(admin_bindings.GetHandler(&mock_admin));
  builder.BuildAndRun(test_harness());
  FX_LOGS(INFO) << "Waiting for session shell to startup.";
  RunLoopUntil([&] { return session_shell->is_running(); });

  // Connect to basemgr to call RestartSession
  constexpr char kBasemgrGlobPath[] = "/hub/r/mth_*_test/*/c/basemgr.cmx/*/out/debug/basemgr";
  files::Glob glob(kBasemgrGlobPath);
  ASSERT_EQ(1u, glob.size());
  const std::string path = *glob.begin();
  fuchsia::modular::internal::BasemgrDebugPtr basemgr;
  fdio_service_connect(path.c_str(), basemgr.NewRequest().TakeChannel().release());

  // Restart the session 4 times and show that device suspend is NOT invoked.
  for (int i = 0; i < 4; i++) {
    bool session_restarted = false;
    basemgr->RestartSession([&] { session_restarted = true; });
    FX_LOGS(INFO) << "Waiting for session shell to shutdown. Iteration: " << i;
    RunLoopUntil([&] { return !session_shell->is_running(); });
    FX_LOGS(INFO) << "Waiting for confirmation from RestartSession().";
    RunLoopUntil([&] { return session_restarted; });
    ASSERT_FALSE(mock_admin.reboot_called()) << "Suspend called on iteration #" << i;
    FX_LOGS(INFO) << "Waiting for session shell to start after restart.";
    RunLoopUntil([&] { return session_shell->is_running(); });
  }
  ASSERT_FALSE(mock_admin.reboot_called());
}

TEST_F(SessionmgrIntegrationTest, RestartSessionAgentOnCrash) {
  std::string fake_agent_url =
      modular_testing::TestHarnessBuilder::GenerateFakeUrl("test_agent_to_restart");

  int launch_count = 0;

  fuchsia::modular::testing::TestHarnessSpec spec;
  spec.mutable_sessionmgr_config()->set_session_agents({fake_agent_url});
  modular_testing::TestHarnessBuilder builder(std::move(spec));

  builder.InterceptComponent({
      .url = fake_agent_url,
      .sandbox_services =
          {
              fuchsia::modular::ComponentContext::Name_,
          },
      .launch_handler =
          [&](fuchsia::sys::StartupInfo startup_info,
              fidl::InterfaceHandle<fuchsia::modular::testing::InterceptedComponent>
                  intercepted_component) mutable {
            launch_count++;
            fake_agent_ =
                std::make_unique<modular_testing::FakeAgent>(modular_testing::FakeComponent::Args{
                    .url = fake_agent_url,
                });
            fake_agent_->BuildInterceptOptions().launch_handler(std::move(startup_info),
                                                                std::move(intercepted_component));
          },
  });
  builder.BuildAndRun(test_harness());

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

  ASSERT_EQ(1, launch_count);

  fake_agent_->Exit(1, fuchsia::sys::TerminationReason::UNKNOWN);
  auto old_agent = std::move(fake_agent_);
  fake_agent_.reset();

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

  ASSERT_EQ(2, launch_count);
}

TEST_F(SessionmgrIntegrationTest, RestartSessionOnSessionAgentCrash) {
  static const auto kFakeAgentUrl =
      modular_testing::TestHarnessBuilder::GenerateFakeUrl("test_agent");

  // Configure sessiomgr to restart the session when the agent terminates.
  fuchsia::modular::testing::TestHarnessSpec spec;
  spec.mutable_sessionmgr_config()->set_session_agents({kFakeAgentUrl});
  spec.mutable_sessionmgr_config()->set_restart_session_on_agent_crash({kFakeAgentUrl});

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();
  builder.InterceptSessionShell(session_shell->BuildInterceptOptions());
  fake_agent_ = std::make_unique<modular_testing::FakeAgent>(modular_testing::FakeComponent::Args{
      .url = kFakeAgentUrl,
      .sandbox_services = modular_testing::FakeAgent::GetDefaultSandboxServices()});
  builder.InterceptComponent(fake_agent_->BuildInterceptOptions());

  builder.BuildAndRun(test_harness());

  // Wait for the session to start.
  RunLoopUntil([&] { return session_shell->is_running() && fake_agent_->is_running(); });

  // Terminate the agent.
  fake_agent_->Exit(1, fuchsia::sys::TerminationReason::UNKNOWN);
  RunLoopUntil([&] { return !fake_agent_->is_running(); });

  // The session and agent should have restarted.
  RunLoopUntil([&] { return !session_shell->is_running(); });
  RunLoopUntil([&] { return session_shell->is_running() && fake_agent_->is_running(); });
}

// Tests that agents have access to PuppetMaster during teardown.
// This test creates its own TestHarnessLauncher so it can tear it down before the test ends.
TEST_F(SessionmgrIntegrationTestWithoutDefaultHarness, PuppetMasterInAgentTerminate) {
  static const auto kFakeAgentUrl =
      modular_testing::TestHarnessBuilder::GenerateFakeUrl("test_agent");

  auto fake_agent_ =
      std::make_unique<FakeComponentWithOnTerminate>(modular_testing::FakeComponent::Args{
          .url = kFakeAgentUrl,
          .sandbox_services = {fuchsia::modular::ComponentContext::Name_,
                               fuchsia::modular::PuppetMaster::Name_}});
  auto session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions();

  fuchsia::modular::PuppetMasterPtr puppet_master;

  bool is_agent_terminate_called{false};
  bool is_puppet_master_closed{false};

  {
    modular_testing::TestHarnessLauncher test_harness_launcher(
        real_services()->Connect<fuchsia::sys::Launcher>());

    fuchsia::modular::testing::TestHarnessSpec spec;
    spec.mutable_sessionmgr_config()->set_session_agents({kFakeAgentUrl});

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

    // Wait for the session to start.
    RunLoopUntil([&] { return session_shell->is_running() && fake_agent_->is_running(); });

    puppet_master.set_error_handler([&](zx_status_t /*unused*/) {
      // The agent should have terminated before PuppetMaster is closed.
      EXPECT_TRUE(is_agent_terminate_called);
      is_puppet_master_closed = true;
    });

    // Connect to the PuppetMaster provided to the agent.
    fake_agent_->component_context()->svc()->Connect(puppet_master.NewRequest());

    fake_agent_->set_on_terminate([&]() {
      // PuppetMaster should not have closed before the agent is torn down.
      EXPECT_FALSE(is_puppet_master_closed);
      is_agent_terminate_called = true;
    });

    test_harness_launcher.StopTestHarness();

    // Wait until the agent terminates
    RunLoopUntil([&] { return !fake_agent_->is_running(); });

    RunLoopUntil([&] { return is_agent_terminate_called && is_puppet_master_closed; });

    // The test harness component is torn down once |test_harness_launcher| goes out of scope.
  }
}

// Tests that creating a story before StoryProviderImpl connects to a presentation protocol
// results in the PresentView call being pended and called again once connected.
TEST_F(SessionmgrIntegrationTest, PresentViewBeforePresentationProtocolConnected) {
  modular_testing::TestHarnessBuilder builder;
  auto fake_graphical_presenter =
      modular_testing::FakeGraphicalPresenter::CreateWithDefaultOptions();

  fake_graphical_presenter->set_on_create([&](fit::function<void()> done) {
    // Create the story before the FakeGraphicalPresenter component starts serving its outgoing
    // directory. This ensures that StoryProviderImpl has not yet selected a presentation protocol.
    auto story_puppet_master = ControlStory();
    LaunchMod(&story_puppet_master);
    done();
  });

  bool called_present_view = false;
  fake_graphical_presenter->set_on_present_view(
      [&](fuchsia::element::ViewSpec view_spec,
          fidl::InterfaceHandle<fuchsia::element::AnnotationController> annotation_controller) {
        called_present_view = true;
      });

  bool graphical_presenter_connected = false;
  fake_graphical_presenter->set_on_graphical_presenter_connected(
      [&]() { graphical_presenter_connected = true; });

  fake_graphical_presenter->set_on_graphical_presenter_error([&](zx_status_t status) {
    FX_PLOGS(FATAL, status) << "Failed to connect to FakeGraphicalPresenter";
  });

  builder.InterceptSessionShell(fake_graphical_presenter->BuildInterceptOptions());
  builder.UseSessionShellForStoryShellFactory();

  // Create the test harness and verify the session shell is up
  builder.BuildAndRun(test_harness());

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

  // StoryProviderImpl should have selected GraphicalPresenter called PresentView.
  RunLoopUntil([&] { return graphical_presenter_connected; });
  RunLoopUntil([&] { return called_present_view; });
}

// Tests that creating and deleting a story before the presentation protocol is chosen as a
// result of the session component exposing its outgoing directory does not cause sessionmgr
// to try to present a pended view for a nonexistent story.
TEST_F(SessionmgrIntegrationTest, PresentViewDeletedStory) {
  modular_testing::TestHarnessBuilder builder;
  fake_graphical_presenter_ = modular_testing::FakeGraphicalPresenter::CreateWithDefaultOptions();

  fit::function<void()> serve_outgoing;
  fake_graphical_presenter_->set_on_create(
      [&](fit::function<void()> done) { serve_outgoing = std::move(done); });

  fake_graphical_presenter_->set_on_present_view(
      [&](fuchsia::element::ViewSpec view_spec,
          fidl::InterfaceHandle<fuchsia::element::AnnotationController> annotation_controller) {
        FX_LOGS(FATAL) << "PresentView should not be called for a view from a deleted story.";
      });

  bool graphical_presenter_connected = false;
  fake_graphical_presenter_->set_on_graphical_presenter_connected(
      [&]() { graphical_presenter_connected = true; });

  builder.InterceptSessionShell(fake_graphical_presenter_->BuildInterceptOptions());
  builder.InterceptComponent(fake_module_->BuildInterceptOptions());
  builder.UseSessionShellForStoryShellFactory();

  // Create the test harness and verify the session shell is up
  builder.BuildAndRun(test_harness());

  RunLoopUntil([&] { return !!serve_outgoing; });

  auto story_puppet_master = ControlStory();

  // Create the story before the FakeGraphicalPresenter component starts serving its outgoing
  // directory. This ensures that StoryProviderImpl has not yet selected a presentation protocol.
  bool created_story{false};
  LaunchMod(&story_puppet_master, [&](const fuchsia::modular::ExecuteResult& result) mutable {
    EXPECT_EQ(fuchsia::modular::ExecuteStatus::OK, result.status);
    created_story = true;
  });
  RunLoopUntil([&] { return created_story; });

  bool deleted_story{false};
  auto puppet_master = ConnectToPuppetMaster();
  puppet_master->DeleteStory(kTestStoryId, [&] { deleted_story = true; });
  RunLoopUntil([&] { return deleted_story; });

  serve_outgoing();

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

}  // namespace
