// Copyright 2016 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/modular/testing/cpp/fidl.h>
#include <fuchsia/testing/modular/cpp/fidl.h>
#include <lib/fidl/cpp/optional.h>
#include <lib/modular/testing/cpp/fake_agent.h>

#include <gmock/gmock.h>
#include <src/modular/lib/modular_config/modular_config_constants.h>

#include "src/lib/fsl/vmo/strings.h"
#include "src/modular/bin/sessionmgr/testing/annotations_matchers.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"

#define TEST_NAME(SUFFIX) \
  std::string(::testing::UnitTest::GetInstance()->current_test_info()->name()) + "_" #SUFFIX;

using fuchsia::modular::StoryInfo2;
using fuchsia::modular::StoryState;
using fuchsia::modular::StoryVisibilityState;
using fuchsia::modular::ViewIdentifier;
using testing::ByRef;
using testing::Pointee;
using testing::UnorderedElementsAre;

namespace {

class SessionShellTest : public modular_testing::TestHarnessFixture {
 protected:
  SessionShellTest()
      : fake_session_shell_(modular_testing::FakeSessionShell::CreateWithDefaultOptions()),
        fake_module_(modular_testing::FakeModule::CreateWithDefaultOptions()) {}
  // Shared boilerplate for configuring the test harness to intercept the
  // session shell, setting up the session shell mock object, running the test
  // harness, and waiting for the session shell to be successfully intercepted.
  // Note that this method blocks the thread until the session shell has started
  // up.
  //
  // Not done in SetUp() or the constructor to let the test reader know that
  // this is happening. Also, certain tests may want to change this flow.
  void RunHarnessAndInterceptSessionShell() {
    modular_testing::TestHarnessBuilder builder;
    builder.InterceptSessionShell(fake_session_shell_->BuildInterceptOptions());
    builder.InterceptComponent(fake_module_->BuildInterceptOptions());
    builder.BuildAndRun(test_harness());

    // Wait for our session shell to start.
    RunLoopUntil([&] { return fake_session_shell_->is_running(); });
  }

  void RunFakeModule(const std::string& story_name) {
    // Connect to PuppetMaster.
    fuchsia::modular::testing::ModularService svc;
    fuchsia::modular::PuppetMasterPtr puppet_master;
    svc.set_puppet_master(puppet_master.NewRequest());
    test_harness()->ConnectToModularService(std::move(svc));

    // Add the module to the story.
    fuchsia::modular::Intent intent;
    intent.handler = fake_module_->url();
    intent.action = "action";

    modular_testing::AddModToStory(test_harness(), story_name, "modname", std::move(intent));

    // Wait for the story and mod to start.
    RunLoopUntil([&] { return fake_module_->is_running(); });
  }

  std::unique_ptr<modular_testing::FakeSessionShell> fake_session_shell_;
  std::unique_ptr<modular_testing::FakeModule> fake_module_;
};

class TestComponent : public modular_testing::FakeComponent {
 public:
  // |on_created| is called when the component is launched. |on_destroyed| is called when the
  // component is terminated.
  TestComponent(fit::function<void()> on_created, fit::function<void()> on_destroyed)
      : FakeComponent({.url = modular_testing::TestHarnessBuilder::GenerateFakeUrl(),
                       .sandbox_services = {"fuchsia.modular.SessionShellContext"}}),
        on_created_(std::move(on_created)),
        on_destroyed_(std::move(on_destroyed)) {}

 protected:
  void OnCreate(fuchsia::sys::StartupInfo startup_info) override { on_created_(); }

  void OnDestroy() override { on_destroyed_(); }

  fit::function<void()> on_created_;
  fit::function<void()> on_destroyed_;
};

TEST_F(SessionShellTest, RestartShell) {
  modular_testing::TestHarnessBuilder builder;

  // Overriding OnDestroy() and OnCreate() to ensure that there isn't a race condition when
  // verifying that the session_shell restarts properly.
  bool stopped = false;
  bool started = false;

  TestComponent session_shell([&] { started = true; }, [&] { stopped = true; });
  builder.InterceptSessionShell(session_shell.BuildInterceptOptions());
  builder.BuildAndRun(test_harness());

  EXPECT_FALSE(session_shell.is_running());
  RunLoopUntil([&] { return session_shell.is_running(); });

  started = false;

  fuchsia::modular::SessionShellContextPtr session_shell_context;
  session_shell.component_context()->svc()->Connect(session_shell_context.NewRequest());
  session_shell_context->Restart();

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

  // Tests that the session shell is restarted after a call to SessionShellContext::Restart.
  RunLoopUntil([&] { return started; });
}

TEST_F(SessionShellTest, GetStoryInfoNonexistentStory) {
  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  bool tried_get_story_info = false;
  story_provider->GetStoryInfo2("X",
                                [&tried_get_story_info](fuchsia::modular::StoryInfo2 story_info) {
                                  EXPECT_TRUE(story_info.IsEmpty());
                                  tried_get_story_info = true;
                                });

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

TEST_F(SessionShellTest, GetStoriesEmpty) {
  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  bool called_get_stories = false;
  story_provider->GetStories2(
      nullptr, [&called_get_stories](const std::vector<fuchsia::modular::StoryInfo2>& stories) {
        EXPECT_THAT(stories, testing::IsEmpty());
        called_get_stories = true;
      });

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

TEST_F(SessionShellTest, StartAndStopStoryWithExtraInfoMod) {
  static constexpr char kStoryId[] = "my_story";

  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  // Have the mock session_shell record the sequence of story states it sees,
  // and confirm that it only sees the correct story id.
  std::vector<StoryState> sequence_of_story_states;
  modular_testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2([&sequence_of_story_states](StoryInfo2 story_info, StoryState story_state,
                                                      StoryVisibilityState _) {
    ASSERT_TRUE(story_info.has_id());
    EXPECT_EQ(story_info.id(), kStoryId);
    sequence_of_story_states.push_back(story_state);
  });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);

  // Start the story.
  RunFakeModule(kStoryId);

  // Stop the story. Check that the story went through the correct sequence
  // of states (see StoryState FIDL file for valid state transitions). Since we
  // started it, ran it, and stopped it, the sequence is STOPPED -> RUNNING ->
  // STOPPING -> STOPPED.
  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(kStoryId, story_controller.NewRequest());

  bool stop_called = false;
  story_controller->Stop([&stop_called] { stop_called = true; });
  RunLoopUntil([&] { return stop_called; });

  // 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; });
  EXPECT_THAT(sequence_of_story_states,
              testing::ElementsAre(StoryState::STOPPED, StoryState::RUNNING, StoryState::STOPPING,
                                   StoryState::STOPPED));
}

TEST_F(SessionShellTest, StoryInfoBeforeAndAfterDelete) {
  static constexpr char kStoryId[] = "my_story";

  RunHarnessAndInterceptSessionShell();

  // Connect to PuppetMaster.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  // Start the story.
  RunFakeModule(kStoryId);

  // Verify that the newly created story returns something for
  // GetStoryInfo().
  bool get_story_info_called = false;
  story_provider->GetStoryInfo2(kStoryId,
                                [&get_story_info_called](fuchsia::modular::StoryInfo2 story_info) {
                                  ASSERT_TRUE(story_info.has_id());
                                  EXPECT_EQ(story_info.id(), kStoryId);
                                  get_story_info_called = true;
                                });
  RunLoopUntil([&] { return get_story_info_called; });

  // Delete the story and confirm that the story info is null now.
  bool delete_called = false;
  puppet_master->DeleteStory(kStoryId, [&delete_called, story_provider] {
    story_provider->GetStoryInfo2(kStoryId, [](fuchsia::modular::StoryInfo2 story_info) {
      EXPECT_TRUE(story_info.IsEmpty());
    });
    delete_called = true;
  });
  RunLoopUntil([&] { return delete_called; });
}

TEST_F(SessionShellTest, DISABLED_AttachesAndDetachesView) {
  static constexpr char kStoryId[] = "my_story";

  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  // Have the mock session_shell record the sequence of story states it sees,
  // and confirm that it only sees the correct story id.
  std::vector<StoryState> sequence_of_story_states;
  modular_testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2([&sequence_of_story_states](StoryInfo2 story_info, StoryState story_state,
                                                      StoryVisibilityState _) {
    EXPECT_TRUE(story_info.has_id());
    EXPECT_EQ(story_info.id(), kStoryId);
    sequence_of_story_states.push_back(story_state);
  });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);

  bool called_attach_view = false;
  fake_session_shell_->set_on_attach_view(
      [&called_attach_view](const ViewIdentifier& /*unused*/) { called_attach_view = true; });

  bool called_detach_view = false;
  fake_session_shell_->set_on_detach_view(
      [&called_detach_view](const ViewIdentifier& /*unused*/) { called_detach_view = true; });

  // Start the story and confirm that AttachView() was called.
  RunFakeModule(kStoryId);

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

  // Stop the story. Confirm that:
  //  a. DetachView() was called.
  //  b. The story went through the correct sequence
  // of states (see StoryState FIDL file for valid state transitions). Since we
  // started it, ran it, and stopped it, the sequence is STOPPED -> RUNNING ->
  // STOPPING -> STOPPED.
  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(kStoryId, story_controller.NewRequest());

  bool stop_called = false;
  story_controller->Stop([&stop_called] { stop_called = true; });
  RunLoopUntil([&] { return stop_called; });

  // 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; });
  EXPECT_TRUE(called_detach_view);
  EXPECT_THAT(sequence_of_story_states,
              testing::ElementsAre(StoryState::STOPPED, StoryState::RUNNING, StoryState::STOPPING,
                                   StoryState::STOPPED));
}

TEST_F(SessionShellTest, DISABLED_StoryStopDoesntWaitOnDetachView) {
  static constexpr char kStoryId[] = "my_story";

  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  // Have the mock session_shell record the sequence of story states it sees,
  // and confirm that it only sees the correct story id.
  std::vector<StoryState> sequence_of_story_states;
  modular_testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2([&sequence_of_story_states](StoryInfo2 story_info, StoryState story_state,
                                                      StoryVisibilityState _) {
    EXPECT_TRUE(story_info.has_id());
    EXPECT_EQ(story_info.id(), kStoryId);
    sequence_of_story_states.push_back(story_state);
  });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);

  bool called_attach_view = false;
  fake_session_shell_->set_on_attach_view(
      [&called_attach_view](const ViewIdentifier& /*unused*/) { called_attach_view = true; });

  // Start the story and confirm that AttachView() was called.
  RunFakeModule(kStoryId);

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

  // Stop the story. Confirm that:
  //  a. The story stopped, even though it didn't see the DetachView() response
  //   (it was artificially delayed for 1hr).
  //  b. The story went through the correct sequence of states (see StoryState
  //   FIDL file for valid state transitions). Since we started it, ran it, and
  //   stopped it, the sequence is STOPPED -> RUNNING -> STOPPING -> STOPPED.
  fake_session_shell_->set_detach_delay(zx::sec(60 * 60));

  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(kStoryId, story_controller.NewRequest());

  bool stop_called = false;
  story_controller->Stop([&stop_called] { stop_called = true; });
  RunLoopUntil([&] { return stop_called; });

  // 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; });
  EXPECT_THAT(sequence_of_story_states,
              testing::ElementsAre(StoryState::STOPPED, StoryState::RUNNING, StoryState::STOPPING,
                                   StoryState::STOPPED));
}

TEST_F(SessionShellTest, GetStoryInfo2HasId) {
  static constexpr char kStoryId[] = "my_story";

  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  // Start the story.
  RunFakeModule(kStoryId);

  // Verify that the newly created story returns something for
  // GetStoryInfo2().
  bool get_story_info_called = false;
  story_provider->GetStoryInfo2(kStoryId,
                                [&get_story_info_called](fuchsia::modular::StoryInfo2 story_info) {
                                  ASSERT_FALSE(story_info.IsEmpty());
                                  EXPECT_TRUE(story_info.has_id());
                                  EXPECT_EQ(story_info.id(), kStoryId);
                                  get_story_info_called = true;
                                });
  RunLoopUntil([&] { return get_story_info_called; });
}

TEST_F(SessionShellTest, GetStories2ReturnsStoryInfo) {
  static constexpr char kStoryId[] = "my_story";

  RunHarnessAndInterceptSessionShell();

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();
  ASSERT_TRUE(story_provider != nullptr);

  // Start the story.
  RunFakeModule(kStoryId);

  // Verify that GetStories2 returns the StoryInfo2 for the newly created story
  bool get_stories_called = false;
  story_provider->GetStories2(
      /*watcher=*/nullptr,
      [&get_stories_called](std::vector<fuchsia::modular::StoryInfo2> story_infos) {
        ASSERT_FALSE(story_infos.empty());
        const auto& story_info = story_infos.at(0);
        ASSERT_FALSE(story_info.IsEmpty());
        EXPECT_TRUE(story_info.has_id());
        EXPECT_EQ(story_info.id(), kStoryId);
        get_stories_called = true;
      });
  RunLoopUntil([&] { return get_stories_called; });
}

TEST_F(SessionShellTest, StoryProviderWatcher) {
  static constexpr auto kStoryId = "my_story";

  RunHarnessAndInterceptSessionShell();

  // Connect to PuppetMaster.
  fuchsia::modular::PuppetMasterPtr puppet_master;
  fuchsia::modular::testing::ModularService svc;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();
  ASSERT_NE(nullptr, story_provider);

  // Once the story is created, OnChange2 should be called with a StoryInfo2 that has the story ID.
  modular_testing::SimpleStoryProviderWatcher watcher;
  std::vector<StoryInfo2> on_change_calls;
  watcher.set_on_change_2(
      [&](StoryInfo2 story_info, StoryState /* unused */, StoryVisibilityState /* unused */) {
        on_change_calls.push_back(std::move(story_info));
      });
  std::vector<std::string> on_delete_calls;
  watcher.set_on_delete([&](const std::string& story_id) { on_delete_calls.push_back(story_id); });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);

  // Start the story.
  RunFakeModule(kStoryId);

  RunLoopUntil([&] { return !on_change_calls.empty(); });
  EXPECT_TRUE(on_change_calls.at(0).has_id());
  EXPECT_EQ(kStoryId, on_change_calls.at(0).id());

  // Delete the story twice. Expect that we are notified only once.
  EXPECT_TRUE(on_delete_calls.empty());
  int delete_story_count = 0;
  puppet_master->DeleteStory(kStoryId, [&delete_story_count] { delete_story_count++; });
  puppet_master->DeleteStory(kStoryId, [&delete_story_count] { delete_story_count++; });
  RunLoopUntil([&] { return delete_story_count == 2; });
  EXPECT_EQ(2, delete_story_count);

  // In order to ensure that both DeleteStory() operations have completed,
  // perform another operation that is enqueued after them and wait for it
  // to return.
  bool get_stories_done = false;
  story_provider->GetStories2(nullptr, [&](auto /*ignored*/) { get_stories_done = true; });
  RunLoopUntil([&] { return get_stories_done; });

  RunLoopUntil([&] { return !on_delete_calls.empty(); });
  EXPECT_EQ(1u, on_delete_calls.size());
}

TEST_F(SessionShellTest, StoryControllerAnnotate) {
  const auto story_name = TEST_NAME(story);

  RunHarnessAndInterceptSessionShell();
  RunFakeModule(story_name);

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();

  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(story_name, story_controller.NewRequest());

  // Create some annotations, one for each variant of AnnotationValue.
  auto text_annotation_value = fuchsia::modular::AnnotationValue{};
  text_annotation_value.set_text("text_value");
  auto text_annotation = fuchsia::modular::Annotation{
      .key = "text_key", .value = fidl::MakeOptional(fidl::Clone(text_annotation_value))};

  auto bytes_annotation_value = fuchsia::modular::AnnotationValue{};
  bytes_annotation_value.set_bytes({0x01, 0x02, 0x03, 0x04});
  auto bytes_annotation = fuchsia::modular::Annotation{
      .key = "bytes_key", .value = fidl::MakeOptional(fidl::Clone(bytes_annotation_value))};

  fuchsia::mem::Buffer buffer{};
  std::string buffer_value = "buffer_value";
  ASSERT_TRUE(fsl::VmoFromString(buffer_value, &buffer));
  auto buffer_annotation_value = fuchsia::modular::AnnotationValue{};
  buffer_annotation_value.set_buffer(std::move(buffer));
  auto buffer_annotation = fuchsia::modular::Annotation{
      .key = "buffer_key", .value = fidl::MakeOptional(fidl::Clone(buffer_annotation_value))};

  std::vector<fuchsia::modular::Annotation> annotations;
  annotations.push_back(fidl::Clone(text_annotation));
  annotations.push_back(fidl::Clone(bytes_annotation));
  annotations.push_back(fidl::Clone(buffer_annotation));

  // Annotate the story.
  bool done_annotating{false};
  story_controller->Annotate(std::move(annotations),
                             [&](fuchsia::modular::StoryController_Annotate_Result result) {
                               EXPECT_FALSE(result.is_err());
                               done_annotating = true;
                             });
  RunLoopUntil([&] { return done_annotating; });

  // GetStoryInfo should contain the annotations.
  fuchsia::modular::StoryInfo2 story_info;
  bool done_getting_story_info = false;

  story_provider->GetStoryInfo2(story_name, [&](fuchsia::modular::StoryInfo2 data) {
    done_getting_story_info = true;
    story_info = std::move(data);
  });
  RunLoopUntil([&] { return done_getting_story_info; });

  EXPECT_FALSE(story_info.IsEmpty());
  EXPECT_TRUE(story_info.has_annotations());

  EXPECT_EQ(3u, story_info.annotations().size());

  EXPECT_THAT(
      story_info.mutable_annotations(),
      Pointee(UnorderedElementsAre(modular::annotations::AnnotationEq(ByRef(text_annotation)),
                                   modular::annotations::AnnotationEq(ByRef(bytes_annotation)),
                                   modular::annotations::AnnotationEq(ByRef(buffer_annotation)))));
}

// Verifies that Annotate merges new annotations, preserving existing ones.
TEST_F(SessionShellTest, StoryControllerAnnotateMerge) {
  const auto story_name = TEST_NAME(story);

  RunHarnessAndInterceptSessionShell();
  RunFakeModule(story_name);

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();

  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(story_name, story_controller.NewRequest());

  // Create the initial set of annotations.
  auto first_annotation_value = fuchsia::modular::AnnotationValue{};
  first_annotation_value.set_text("first_value");
  auto first_annotation = fuchsia::modular::Annotation{
      .key = "first_key", .value = fidl::MakeOptional(fidl::Clone(first_annotation_value))};

  std::vector<fuchsia::modular::Annotation> annotations;
  annotations.push_back(fidl::Clone(first_annotation));

  // Annotate the story.
  bool done{false};
  story_controller->Annotate(std::move(annotations),
                             [&](fuchsia::modular::StoryController_Annotate_Result result) {
                               EXPECT_FALSE(result.is_err());
                               done = true;
                             });
  RunLoopUntil([&] { return done; });

  // GetStoryData should contain the first annotation.
  done = false;
  story_provider->GetStoryInfo2(story_name, [&](fuchsia::modular::StoryInfo2 story_info) {
    EXPECT_FALSE(story_info.IsEmpty());
    EXPECT_TRUE(story_info.has_annotations());

    EXPECT_EQ(1u, story_info.annotations().size());

    EXPECT_EQ(story_info.annotations().at(0).key, first_annotation.key);
    EXPECT_EQ(story_info.annotations().at(0).value->text(), first_annotation_value.text());

    done = true;
  });
  RunLoopUntil([&] { return done; });

  // Create another set of annotations that should be merged into the initial one.
  auto second_annotation_value = fuchsia::modular::AnnotationValue{};
  second_annotation_value.set_text("second_value");
  auto second_annotation = fuchsia::modular::Annotation{
      .key = "second_key", .value = fidl::MakeOptional(fidl::Clone(second_annotation_value))};

  std::vector<fuchsia::modular::Annotation> annotations_2;
  annotations_2.push_back(fidl::Clone(second_annotation));

  // Annotate the story with the second set of annotations.
  done = false;
  story_controller->Annotate(std::move(annotations_2),
                             [&](fuchsia::modular::StoryController_Annotate_Result result) {
                               EXPECT_FALSE(result.is_err());
                               done = true;
                             });
  RunLoopUntil([&] { return done; });

  // GetStoryData should now return annotations from both the first and second set.
  done = false;
  story_provider->GetStoryInfo2(story_name, [&](fuchsia::modular::StoryInfo2 story_info) {
    EXPECT_FALSE(story_info.IsEmpty());

    EXPECT_EQ(2u, story_info.annotations().size());

    EXPECT_THAT(story_info.mutable_annotations(),
                Pointee(UnorderedElementsAre(
                    modular::annotations::AnnotationEq(ByRef(first_annotation)),
                    modular::annotations::AnnotationEq(ByRef(second_annotation)))));

    done = true;
  });
  RunLoopUntil([&] { return done; });
}

// Verifies that StoryController.Annotate returns an error when one of the annotations
// has a buffer value that exceeds MAX_ANNOTATION_VALUE_BUFFER_LENGTH_BYTES.
TEST_F(SessionShellTest, StoryControllerAnnotateBufferValueTooBig) {
  const auto story_name = TEST_NAME(story);

  RunHarnessAndInterceptSessionShell();
  RunFakeModule(story_name);

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();

  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(story_name, story_controller.NewRequest());

  // Create an annotation with a large buffer value.
  fuchsia::mem::Buffer buffer{};
  std::string buffer_value(fuchsia::modular::MAX_ANNOTATION_VALUE_BUFFER_LENGTH_BYTES + 1, 'x');
  ASSERT_TRUE(fsl::VmoFromString(buffer_value, &buffer));

  auto annotation_value = fuchsia::modular::AnnotationValue{};
  annotation_value.set_buffer(std::move(buffer));
  auto annotation = fuchsia::modular::Annotation{
      .key = "buffer_key", .value = fidl::MakeOptional(std::move(annotation_value))};

  std::vector<fuchsia::modular::Annotation> annotations;
  annotations.push_back(std::move(annotation));

  // Annotate the story.
  bool done{false};
  story_controller->Annotate(
      std::move(annotations), [&](fuchsia::modular::StoryController_Annotate_Result result) {
        EXPECT_TRUE(result.is_err());
        EXPECT_EQ(fuchsia::modular::AnnotationError::VALUE_TOO_BIG, result.err());
        done = true;
      });
  RunLoopUntil([&] { return done; });
}

// Verifies that StoryPuppetMaster.Annotate returns an error when one of the annotations
// has a buffer value that exceeds MAX_ANNOTATION_VALUE_BUFFER_LENGTH_BYTES.
TEST_F(SessionShellTest, StoryPuppetMasterAnnotateBufferValueTooBig) {
  const auto story_name = TEST_NAME(story);

  RunHarnessAndInterceptSessionShell();
  RunFakeModule(story_name);

  // Connect to StoryPuppetMaster.
  fuchsia::modular::testing::ModularService svc;
  fuchsia::modular::PuppetMasterPtr puppet_master;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryPuppetMasterPtr story_puppet_master;
  puppet_master->ControlStory(story_name, story_puppet_master.NewRequest());

  // Create an annotation with a large buffer value.
  fuchsia::mem::Buffer buffer{};
  std::string buffer_value(fuchsia::modular::MAX_ANNOTATION_VALUE_BUFFER_LENGTH_BYTES + 1, 'x');
  ASSERT_TRUE(fsl::VmoFromString(buffer_value, &buffer));

  auto annotation_value = fuchsia::modular::AnnotationValue{};
  annotation_value.set_buffer(std::move(buffer));
  auto annotation = fuchsia::modular::Annotation{
      .key = "buffer_key", .value = fidl::MakeOptional(std::move(annotation_value))};

  std::vector<fuchsia::modular::Annotation> annotations;
  annotations.push_back(std::move(annotation));

  // Annotate the story.
  bool done{false};
  story_puppet_master->Annotate(
      std::move(annotations), [&](fuchsia::modular::StoryPuppetMaster_Annotate_Result result) {
        EXPECT_TRUE(result.is_err());
        EXPECT_EQ(fuchsia::modular::AnnotationError::VALUE_TOO_BIG, result.err());
        done = true;
      });
  RunLoopUntil([&] { return done; });
}

// Verifies that Annotate returns an error when adding new annotations to exceeds
// MAX_ANNOTATIONS_PER_STORY.
TEST_F(SessionShellTest, StoryControllerAnnotateTooMany) {
  const auto story_name = TEST_NAME(story);

  RunHarnessAndInterceptSessionShell();
  RunFakeModule(story_name);

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();

  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(story_name, story_controller.NewRequest());

  // A single Annotate call should not accept more annotations than allowed on a single story.
  ASSERT_GE(fuchsia::modular::MAX_ANNOTATIONS_PER_STORY,
            fuchsia::modular::MAX_ANNOTATIONS_PER_UPDATE);

  // Annotate the story repeatedly, in batches of MAX_ANNOTATIONS_PER_UPDATE items, in order
  // to reach, but not exceed the MAX_ANNOTATIONS_PER_STORY limit.
  for (unsigned int num_annotate_calls = 0;
       num_annotate_calls <
       fuchsia::modular::MAX_ANNOTATIONS_PER_STORY / fuchsia::modular::MAX_ANNOTATIONS_PER_UPDATE;
       ++num_annotate_calls) {
    std::vector<fuchsia::modular::Annotation> annotations;

    // Create MAX_ANNOTATIONS_PER_UPDATE annotations for each call to Annotate.
    for (unsigned int num_annotations = 0;
         num_annotations < fuchsia::modular::MAX_ANNOTATIONS_PER_UPDATE; ++num_annotations) {
      auto annotation_value = fuchsia::modular::AnnotationValue{};
      annotation_value.set_text("test_annotation_value");
      auto annotation =
          fuchsia::modular::Annotation{.key = "annotation_" + std::to_string(num_annotate_calls) +
                                              "_" + std::to_string(num_annotations),
                                       .value = fidl::MakeOptional(std::move(annotation_value))};
      annotations.push_back(std::move(annotation));
    }

    // Annotate the story.
    bool done{false};
    story_controller->Annotate(
        std::move(annotations), [&](fuchsia::modular::StoryController_Annotate_Result result) {
          EXPECT_FALSE(result.is_err())
              << "Annotate call #" << num_annotate_calls << " returned an error when trying to add "
              << std::to_string(fuchsia::modular::MAX_ANNOTATIONS_PER_UPDATE)
              << " annotations to the story.";
          done = true;
        });
    RunLoopUntil([&] { return done; });
  }

  // Create some more annotations for a total of (MAX_ANNOTATIONS_PER_STORY + 1) on the story.
  std::vector<fuchsia::modular::Annotation> annotations;

  for (unsigned int num_annotations = 0;
       num_annotations < (fuchsia::modular::MAX_ANNOTATIONS_PER_STORY %
                          fuchsia::modular::MAX_ANNOTATIONS_PER_UPDATE) +
                             1;
       ++num_annotations) {
    auto annotation_value = fuchsia::modular::AnnotationValue{};
    annotation_value.set_text("test_annotation_value");
    auto annotation =
        fuchsia::modular::Annotation{.key = "excess_annotation_" + std::to_string(num_annotations),
                                     .value = fidl::MakeOptional(std::move(annotation_value))};
    annotations.push_back(std::move(annotation));
  }

  // Annotate the story.
  bool done{false};
  story_controller->Annotate(
      std::move(annotations), [&](fuchsia::modular::StoryController_Annotate_Result result) {
        EXPECT_TRUE(result.is_err());
        EXPECT_EQ(fuchsia::modular::AnnotationError::TOO_MANY_ANNOTATIONS, result.err());
        done = true;
      });
  RunLoopUntil([&] { return done; });
}

// Verifies that a call to StoryController.Annotate results in a StoryProviderWatcher.OnChange2
// being called with the updated annotations.
TEST_F(SessionShellTest, StoryControllerAnnotateNotifiesWatcher) {
  const auto story_name = TEST_NAME(story);

  RunHarnessAndInterceptSessionShell();
  RunFakeModule(story_name);

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();

  fuchsia::modular::StoryControllerPtr story_controller;
  story_provider->GetController(story_name, story_controller.NewRequest());

  // Watch the story for new annotations.
  auto num_on_change_2_calls = 0;
  auto num_annotations = 0;
  modular_testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2(
      [&num_on_change_2_calls, &num_annotations](StoryInfo2 story_info, StoryState /*unused*/,
                                                 StoryVisibilityState /*unused*/) {
        num_on_change_2_calls++;
        num_annotations = story_info.mutable_annotations()->size();
      });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);

  // Create a set of annotations, containing a single annotation.
  auto first_annotation_value = fuchsia::modular::AnnotationValue{};
  first_annotation_value.set_text("first_value");
  auto first_annotation = fuchsia::modular::Annotation{
      .key = "first_key", .value = fidl::MakeOptional(fidl::Clone(first_annotation_value))};

  std::vector<fuchsia::modular::Annotation> annotations;
  annotations.push_back(fidl::Clone(first_annotation));

  // Annotate the story.
  bool done{false};
  story_controller->Annotate(std::move(annotations),
                             [&](fuchsia::modular::StoryController_Annotate_Result result) {
                               EXPECT_FALSE(result.is_err());
                               done = true;
                             });
  RunLoopUntil([&] { return done; });

  RunLoopUntil([&] { return num_on_change_2_calls > 0; });
  EXPECT_EQ(1, num_annotations);
}

// Verifies that a call to StoryPuppetMaster.Annotate results in a StoryProviderWatcher.OnChange2
// being called with the updated annotations.
TEST_F(SessionShellTest, StoryPuppetMasterAnnotateNotifiesWatcher) {
  const auto story_name = TEST_NAME(story);

  RunHarnessAndInterceptSessionShell();
  RunFakeModule(story_name);

  fuchsia::modular::StoryProvider* story_provider = fake_session_shell_->story_provider();

  // Connect to StoryPuppetMaster.
  fuchsia::modular::testing::ModularService svc;
  fuchsia::modular::PuppetMasterPtr puppet_master;
  svc.set_puppet_master(puppet_master.NewRequest());
  test_harness()->ConnectToModularService(std::move(svc));

  fuchsia::modular::StoryPuppetMasterPtr story_puppet_master;
  puppet_master->ControlStory(story_name, story_puppet_master.NewRequest());

  // Watch the story for new annotations.
  auto num_on_change_2_calls = 0;
  auto num_annotations = 0;
  modular_testing::SimpleStoryProviderWatcher watcher;
  watcher.set_on_change_2(
      [&num_on_change_2_calls, &num_annotations](StoryInfo2 story_info, StoryState /*unused*/,
                                                 StoryVisibilityState /*unused*/) {
        num_on_change_2_calls++;
        num_annotations = story_info.mutable_annotations()->size();
      });
  watcher.Watch(story_provider, /*on_get_stories=*/nullptr);

  // Create a set of annotations, containing a single annotation.
  auto first_annotation_value = fuchsia::modular::AnnotationValue{};
  first_annotation_value.set_text("first_value");
  auto first_annotation = fuchsia::modular::Annotation{
      .key = "first_key", .value = fidl::MakeOptional(fidl::Clone(first_annotation_value))};

  std::vector<fuchsia::modular::Annotation> annotations;
  annotations.push_back(fidl::Clone(first_annotation));

  // Annotate the story.
  bool done{false};
  story_puppet_master->Annotate(std::move(annotations),
                                [&](fuchsia::modular::StoryPuppetMaster_Annotate_Result result) {
                                  EXPECT_FALSE(result.is_err());
                                  done = true;
                                });
  RunLoopUntil([&] { return done; });

  RunLoopUntil([&] { return num_on_change_2_calls > 0; });
  EXPECT_EQ(1, num_annotations);
}

class ServicePublishingSessionShell : public modular_testing::FakeSessionShell {
 public:
  explicit ServicePublishingSessionShell(modular_testing::FakeComponent::Args args)
      : FakeSessionShell(std::move(args)) {}

  static std::unique_ptr<ServicePublishingSessionShell> CreateWithDefaultOptions() {
    return std::make_unique<ServicePublishingSessionShell>(modular_testing::FakeComponent::Args{
        .url = modular_testing::TestHarnessBuilder::GenerateFakeUrl(),
        .sandbox_services = FakeSessionShell::GetDefaultSandboxServices()});
  }

  int fake_service_connect_count() const { return fake_service_connect_count_; }

 protected:
  void OnCreate(fuchsia::sys::StartupInfo startup_info) override {
    FakeSessionShell::OnCreate(std::move(startup_info));
    component_context()->outgoing()->AddPublicService(
        fit::function<void(fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol>)>(
            [this](fidl::InterfaceRequest<fuchsia::testing::modular::TestProtocol> request) {
              ++fake_service_connect_count_;
              service_channels_.push_back(request.TakeChannel());
            }));
  }

  std::vector<zx::channel> service_channels_;
  int fake_service_connect_count_ = 0;
};

// Show that the session shell can publish a service that is accessible to agents
// via the agent_service_index.
TEST_F(SessionShellTest, SessionShellCanPublishServicesToAgents) {
  auto session_shell = ServicePublishingSessionShell::CreateWithDefaultOptions();
  auto agent = modular_testing::FakeAgent::CreateWithDefaultOptions();

  fuchsia::modular::testing::TestHarnessSpec spec;
  std::vector<fuchsia::modular::session::AgentServiceIndexEntry> agent_service_index;
  fuchsia::modular::session::AgentServiceIndexEntry agent_service;
  agent_service.set_service_name(fuchsia::testing::modular::TestProtocol::Name_);
  agent_service.set_agent_url(session_shell->url());
  agent_service_index.emplace_back(std::move(agent_service));

  spec.mutable_sessionmgr_config()->set_agent_service_index(std::move(agent_service_index));
  spec.mutable_sessionmgr_config()->set_session_agents({agent->url()});

  modular_testing::TestHarnessBuilder builder(std::move(spec));
  builder.InterceptSessionShell(session_shell->BuildInterceptOptions());
  auto agent_intercept_options = agent->BuildInterceptOptions();
  agent_intercept_options.sandbox_services.push_back(
      fuchsia::testing::modular::TestProtocol::Name_);
  builder.InterceptComponent(std::move(agent_intercept_options));
  builder.BuildAndRun(test_harness());

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

  auto service_ptr =
      agent->component_context()->svc()->Connect<fuchsia::testing::modular::TestProtocol>();
  service_ptr.set_error_handler(
      [](zx_status_t status) { FX_PLOGS(FATAL, status) << "channel should not have closed"; });

  RunLoopUntil([&] { return session_shell->fake_service_connect_count() > 0; });
  EXPECT_EQ(1, session_shell->fake_service_connect_count());
  service_ptr.set_error_handler(nullptr);
}

}  // namespace
