| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "fuchsia_web/common/test/test_realm_support.h" |
| |
| #include <lib/sys/component/cpp/testing/realm_builder.h> |
| |
| #include <algorithm> |
| #include <string> |
| #include <string_view> |
| #include <utility> |
| |
| #include "base/check.h" |
| #include "base/command_line.h" |
| |
| using ::component_testing::ChildRef; |
| using ::component_testing::Dictionary; |
| using ::component_testing::Directory; |
| using ::component_testing::ParentRef; |
| using ::component_testing::Protocol; |
| using ::component_testing::RealmBuilder; |
| using ::component_testing::Route; |
| |
| namespace test { |
| |
| namespace { |
| |
| void AppendCommandLineArgumentsToProgram( |
| fuchsia::component::decl::Program& program, |
| const base::CommandLine& command_line) { |
| // Find the "args" list in the program declaration. |
| fuchsia::data::DictionaryEntry* args_entry = nullptr; |
| auto* entries = program.mutable_info()->mutable_entries(); |
| for (auto& entry : *entries) { |
| if (entry.key == "args") { |
| DCHECK(entry.value->is_str_vec()); |
| args_entry = &entry; |
| break; |
| } |
| } |
| if (!args_entry) { |
| // Create a new "args" list and insert it at the proper location in the |
| // program's entries; entries' keys must be sorted as per |
| // https://fuchsia.dev/reference/fidl/fuchsia.data?hl=en#Dictionary. |
| auto lower_bound = std::ranges::lower_bound( |
| *entries, "args", /*comp=*/{}, |
| [](const fuchsia::data::DictionaryEntry& entry) { return entry.key; }); |
| auto it = entries->emplace(lower_bound); |
| it->key = "args"; |
| it->value = fuchsia::data::DictionaryValue::New(); |
| it->value->set_str_vec({}); |
| args_entry = &*it; |
| } |
| |
| // Append all args following the program name in `command_line` to the |
| // program's args. |
| args_entry->value->str_vec().insert(args_entry->value->str_vec().end(), |
| command_line.argv().begin() + 1, |
| command_line.argv().end()); |
| } |
| |
| } // namespace |
| |
| void AppendCommandLineArguments(RealmBuilder& realm_builder, |
| std::string_view child_name, |
| const base::CommandLine& command_line) { |
| const std::string child_name_str(child_name); |
| auto child_component_decl = realm_builder.GetComponentDecl(child_name_str); |
| AppendCommandLineArgumentsToProgram(*child_component_decl.mutable_program(), |
| command_line); |
| realm_builder.ReplaceComponentDecl(child_name_str, |
| std::move(child_component_decl)); |
| } |
| |
| void AppendCommandLineArgumentsForRealm( |
| ::component_testing::RealmBuilder& realm_builder, |
| const base::CommandLine& command_line) { |
| auto decl = realm_builder.GetRealmDecl(); |
| AppendCommandLineArgumentsToProgram(*decl.mutable_program(), command_line); |
| realm_builder.ReplaceRealmDecl(std::move(decl)); |
| } |
| |
| void AddRouteFromParent(RealmBuilder& realm_builder, |
| std::string_view child_name, |
| std::string_view protocol_name) { |
| ChildRef child_ref{std::string_view(child_name.data(), child_name.size())}; |
| realm_builder.AddRoute(Route{.capabilities = {Protocol{protocol_name}}, |
| .source = ParentRef{}, |
| .targets = {std::move(child_ref)}}); |
| } |
| |
| void AddDictionaryRouteFromParent(RealmBuilder& realm_builder, |
| std::string_view child_name, |
| std::string_view dictionary_name) { |
| ChildRef child_ref{std::string_view(child_name.data(), child_name.size())}; |
| realm_builder.AddRoute(Route{.capabilities = {Dictionary{dictionary_name}}, |
| .source = ParentRef{}, |
| .targets = {std::move(child_ref)}}); |
| } |
| |
| void AddSyslogRoutesFromParent(RealmBuilder& realm_builder, |
| std::string_view child_name) { |
| AddDictionaryRouteFromParent(realm_builder, child_name, "diagnostics"); |
| } |
| |
| void AddVulkanRoutesFromParent(RealmBuilder& realm_builder, |
| std::string_view child_name) { |
| ChildRef child_ref{std::string_view(child_name.data(), child_name.size())}; |
| realm_builder.AddRoute( |
| Route{.capabilities = {Protocol{"fuchsia.sysmem.Allocator"}, |
| Protocol{"fuchsia.sysmem2.Allocator"}, |
| Protocol{"fuchsia.tracing.provider.Registry"}, |
| Protocol{"fuchsia.vulkan.loader.Loader"}}, |
| .source = ParentRef{}, |
| .targets = {std::move(child_ref)}}); |
| } |
| |
| void AddFontService(RealmBuilder& realm_builder, std::string_view child_name) { |
| static constexpr char kFontsService[] = "isolated_fonts"; |
| static constexpr char kFontsUrl[] = |
| "fuchsia-pkg://fuchsia.com/fonts_hermetic_for_test" |
| "#meta/font_provider_hermetic_for_test.cm"; |
| realm_builder.AddChild(kFontsService, kFontsUrl); |
| AddSyslogRoutesFromParent(realm_builder, kFontsService); |
| ChildRef child_ref{std::string_view(child_name.data(), child_name.size())}; |
| realm_builder |
| .AddRoute(Route{.capabilities = |
| { |
| Protocol{"fuchsia.tracing.provider.Registry"}, |
| }, |
| .source = ParentRef{}, |
| .targets = {ChildRef{kFontsService}}}) |
| .AddRoute(Route{.capabilities = {Protocol{"fuchsia.fonts.Provider"}}, |
| .source = ChildRef{kFontsService}, |
| .targets = {std::move(child_ref)}}); |
| } |
| |
| void AddTestUiStack(RealmBuilder& realm_builder, std::string_view child_name) { |
| static constexpr char kTestUiStackService[] = "test_ui_stack"; |
| static constexpr char kTestUiStackUrl[] = |
| "fuchsia-pkg://fuchsia.com/flatland-scene-manager-test-ui-stack#meta/" |
| "test-ui-stack.cm"; |
| realm_builder.AddChild(kTestUiStackService, kTestUiStackUrl); |
| AddRouteFromParent(realm_builder, kTestUiStackService, |
| "fuchsia.scheduler.ProfileProvider"); |
| AddSyslogRoutesFromParent(realm_builder, kTestUiStackService); |
| AddVulkanRoutesFromParent(realm_builder, kTestUiStackService); |
| |
| ChildRef child_ref{std::string_view(child_name.data(), child_name.size())}; |
| realm_builder |
| .AddRoute( |
| Route{.capabilities = {Protocol{"fuchsia.scheduler.ProfileProvider"}}, |
| .source = ParentRef(), |
| .targets = {ChildRef{kTestUiStackService}}}) |
| .AddRoute(Route{.capabilities = |
| { |
| Protocol{"fuchsia.ui.composition.Allocator"}, |
| Protocol{"fuchsia.ui.composition.Flatland"}, |
| }, |
| .source = ChildRef{kTestUiStackService}, |
| .targets = {std::move(child_ref)}}); |
| } |
| |
| } // namespace test |