| // 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/modular/testing/cpp/fidl.h> |
| #include <lib/modular/testing/cpp/fake_component.h> |
| |
| #include <tuple> |
| |
| #include <gmock/gmock.h> |
| |
| #include "src/lib/fsl/vmo/strings.h" |
| #include "src/modular/lib/modular_test_harness/cpp/fake_session_shell.h" |
| #include "src/modular/lib/modular_test_harness/cpp/fake_story_shell.h" |
| #include "src/modular/lib/modular_test_harness/cpp/test_harness_fixture.h" |
| |
| using testing::ElementsAre; |
| |
| namespace { |
| |
| class StoryShellTest : public modular_testing::TestHarnessFixture { |
| protected: |
| StoryShellTest() |
| : session_shell_(modular_testing::FakeSessionShell::CreateWithDefaultOptions()), |
| story_shell_({.url = modular_testing::TestHarnessBuilder::GenerateFakeUrl(), |
| .sandbox_services = {"fuchsia.modular.StoryShellContext"}}) {} |
| |
| void StartSession() { |
| modular_testing::TestHarnessBuilder builder; |
| builder.InterceptSessionShell(session_shell_->BuildInterceptOptions()); |
| builder.InterceptStoryShell(story_shell_.BuildInterceptOptions()); |
| |
| fake_module_url_ = modular_testing::TestHarnessBuilder::GenerateFakeUrl("module"); |
| builder.InterceptComponent( |
| {.url = fake_module_url_, |
| .launch_handler = |
| [this](fuchsia::sys::StartupInfo startup_info, |
| fidl::InterfaceHandle<fuchsia::modular::testing::InterceptedComponent> |
| intercepted_component) { |
| intercepted_modules_.push_back( |
| {std::move(startup_info), std::move(intercepted_component)}); |
| }}); |
| builder.BuildAndRun(test_harness()); |
| |
| fuchsia::modular::testing::ModularService request; |
| request.set_puppet_master(puppet_master_.NewRequest()); |
| test_harness()->ConnectToModularService(std::move(request)); |
| |
| // Wait for our session shell to start. |
| RunLoopUntil([this] { return session_shell_->is_running(); }); |
| } |
| |
| void AddModToStory(std::string story_name, std::string mod_name, |
| std::string parent_mod_name = "") { |
| fuchsia::modular::StoryPuppetMasterPtr story_puppet_master; |
| puppet_master_->ControlStory(story_name, story_puppet_master.NewRequest()); |
| |
| fuchsia::modular::AddMod add_mod; |
| add_mod.mod_name_transitional = mod_name; |
| add_mod.intent.handler = fake_module_url_; |
| if (!parent_mod_name.empty()) { |
| add_mod.surface_parent_mod_name = {parent_mod_name}; |
| } |
| |
| std::vector<fuchsia::modular::StoryCommand> commands(1); |
| commands.at(0).set_add_mod(std::move(add_mod)); |
| |
| story_puppet_master->Enqueue(std::move(commands)); |
| bool created = false; |
| story_puppet_master->Execute([&](fuchsia::modular::ExecuteResult result) { created = true; }); |
| |
| // Wait for the story to be created. |
| RunLoopUntil([&] { return created; }); |
| } |
| |
| void RestartStory(std::string story_name) { |
| fuchsia::modular::StoryControllerPtr story_controller; |
| session_shell_->story_provider()->GetController(story_name, story_controller.NewRequest()); |
| |
| bool restarted = false; |
| story_controller->Stop([&] { |
| story_controller->RequestStart(); |
| restarted = true; |
| }); |
| RunLoopUntil([&] { return restarted; }); |
| } |
| |
| fuchsia::modular::PuppetMasterPtr puppet_master_; |
| std::unique_ptr<modular_testing::FakeSessionShell> session_shell_; |
| modular_testing::FakeStoryShell story_shell_; |
| std::string fake_module_url_; |
| |
| // Stories must have modules in them so the stories created above |
| // contain fake intercepted modules. This list holds onto them so that |
| // they can be successfully launched and don't die immediately. |
| std::vector<std::tuple<fuchsia::sys::StartupInfo, |
| fidl::InterfaceHandle<fuchsia::modular::testing::InterceptedComponent>>> |
| intercepted_modules_; |
| }; |
| |
| TEST_F(StoryShellTest, GetsModuleMetadata) { |
| StartSession(); |
| |
| std::vector<std::string> surface_ids_added; |
| story_shell_.set_on_add_surface([&](fuchsia::modular::ViewConnection view_connection, |
| fuchsia::modular::SurfaceInfo surface_info) { |
| surface_ids_added.push_back(view_connection.surface_id); |
| }); |
| |
| AddModToStory("story1", "mod1"); |
| AddModToStory("story1", "mod2", {"mod1"} /* surface relation parent */); |
| // Wait for the story shell to be notified of the new modules. |
| RunLoopUntil([&] { return surface_ids_added.size() == 2; }); |
| EXPECT_THAT(surface_ids_added, ElementsAre("mod1", "mod1:mod2")); |
| |
| // Stop the story shell and restart it. Expect to see the same mods notified |
| // to the story shell in the same order. |
| surface_ids_added.clear(); |
| RestartStory("story1"); |
| RunLoopUntil([&] { return surface_ids_added.size() == 2; }); |
| EXPECT_THAT(surface_ids_added, ElementsAre("mod1", "mod1:mod2")); |
| } |
| |
| } // namespace |