| // Copyright 2018 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/sys/cpp/fidl.h> |
| #include <lib/async/default.h> |
| #include <src/lib/fxl/strings/concatenate.h> |
| #include <src/lib/fxl/strings/join_strings.h> |
| #include <src/lib/fxl/strings/string_printf.h> |
| #include <lib/sys/cpp/file_descriptor.h> |
| #include <lib/sys/cpp/testing/test_with_environment.h> |
| |
| #include "garnet/bin/sysmgr/config.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "src/lib/files/directory.h" |
| #include "src/lib/files/file.h" |
| #include "src/lib/files/glob.h" |
| |
| namespace component { |
| namespace { |
| |
| // This test fixture will provide a way to run components in provided launchers |
| // and check for errors. |
| class HubTest : public sys::testing::TestWithEnvironment { |
| protected: |
| // This would launch component and check that it returns correct |
| // |expected_return_code|. |
| void RunComponent(const fuchsia::sys::LauncherPtr& launcher, |
| const std::string& component_url, |
| const std::vector<std::string>& args, |
| int64_t expected_return_code) { |
| std::FILE* outf = std::tmpfile(); |
| int out_fd = fileno(outf); |
| fuchsia::sys::LaunchInfo launch_info; |
| launch_info.url = component_url; |
| for (auto arg : args) { |
| launch_info.arguments.push_back(arg); |
| } |
| |
| launch_info.out = sys::CloneFileDescriptor(out_fd); |
| |
| fuchsia::sys::ComponentControllerPtr controller; |
| launcher->CreateComponent(std::move(launch_info), controller.NewRequest()); |
| |
| int64_t return_code = INT64_MIN; |
| controller.events().OnTerminated = |
| [&return_code](int64_t code, fuchsia::sys::TerminationReason reason) { |
| return_code = code; |
| }; |
| ASSERT_TRUE( |
| RunLoopUntil([&return_code] { return return_code != INT64_MIN; })); |
| std::string output; |
| ASSERT_TRUE(files::ReadFileDescriptorToString(out_fd, &output)); |
| EXPECT_EQ(expected_return_code, return_code) |
| << "failed for: " << fxl::JoinStrings(args, ", ") |
| << "\noutput: " << output; |
| } |
| }; |
| |
| TEST(ProbeHub, Component) { |
| constexpr char kGlob[] = "/hub/c/*/*/out/debug"; |
| files::Glob glob(kGlob); |
| EXPECT_GE(glob.size(), 1u) << kGlob << " expected to match at least once."; |
| } |
| |
| TEST(ProbeHub, Realm) { |
| constexpr char kGlob[] = "/hub/c/"; |
| files::Glob glob(kGlob); |
| EXPECT_EQ(glob.size(), 1u) << kGlob << " expected to match once."; |
| } |
| |
| TEST(ProbeHub, RealmSvc) { |
| constexpr char kGlob[] = "/hub/svc/fuchsia.sys.Environment"; |
| files::Glob glob(kGlob); |
| EXPECT_EQ(glob.size(), 1u); |
| } |
| |
| TEST_F(HubTest, Services) { |
| // Services for sys. |
| { |
| constexpr char kGlob[] = "/hub/svc"; |
| files::Glob glob(kGlob); |
| EXPECT_EQ(glob.size(), 1u) << kGlob << " expected to match once."; |
| const std::string path = *glob.begin(); |
| |
| // Expected files are built-in services plus sysmgr services. |
| std::vector<std::string> expected_files = { |
| ".", |
| "fuchsia.device.manager.Administrator", |
| "fuchsia.device.manager.DebugDumper", |
| "fuchsia.kernel.DebugBroker", |
| "fuchsia.process.Launcher", |
| "fuchsia.process.Resolver", |
| "fuchsia.scheduler.ProfileProvider", |
| "fuchsia.sys.Environment", |
| "fuchsia.sys.Launcher", |
| "fuchsia.sys.Loader"}; |
| sysmgr::Config config; |
| ASSERT_TRUE(config.ParseFromDirectory("/system/data/sysmgr")); |
| // The following path is deprecated, and because config-data is component |
| // name isolated, it will be impossible to continue to do this in future: |
| ASSERT_TRUE( |
| config.ParseFromDirectory("/pkgfs/packages/config-data/0/data/sysmgr")); |
| const auto service_map = config.TakeServices(); |
| for (const auto& e : service_map) { |
| expected_files.push_back(e.first); |
| } |
| |
| // readdir should list all services. |
| std::vector<std::string> files; |
| ASSERT_TRUE(files::ReadDirContents(path, &files)); |
| EXPECT_THAT(files, ::testing::UnorderedElementsAreArray(expected_files)); |
| |
| // Try looking up an individual service. |
| const std::string service_path = |
| fxl::Concatenate({path, "/", service_map.begin()->first}); |
| EXPECT_TRUE(files::IsFile(service_path)) << service_path; |
| const std::string bogus_path = fxl::Concatenate({path, "/does_not_exist"}); |
| EXPECT_FALSE(files::IsFile(bogus_path)) << bogus_path; |
| } |
| } |
| |
| TEST_F(HubTest, ScopePolicy) { |
| constexpr char kGlobUrl[] = "fuchsia-pkg://fuchsia.com/glob#meta/glob.cmx"; |
| // create nested environment |
| // test that we can see nested env |
| auto nested_env = |
| CreateNewEnclosingEnvironment("hubscopepolicytest", CreateServices()); |
| ASSERT_TRUE(WaitForEnclosingEnvToStart(nested_env.get())); |
| RunComponent(launcher_ptr(), kGlobUrl, {"/hub/r/hubscopepolicytest/"}, 0); |
| |
| // test that we cannot see nested env using its own launcher |
| RunComponent(nested_env->launcher_ptr(), kGlobUrl, |
| {"/hub/r/hubscopepolicytest"}, 1); |
| |
| // test that we can see check_hub_path |
| RunComponent(nested_env->launcher_ptr(), kGlobUrl, {"/hub/c/glob.cmx"}, 0); |
| } |
| |
| TEST_F(HubTest, SystemObjects) { |
| std::string glob_url = "fuchsia-pkg://fuchsia.com/glob#meta/glob.cmx"; |
| |
| auto nested_env = |
| CreateNewEnclosingEnvironment("hubscopepolicytest", CreateServices()); |
| ASSERT_TRUE(WaitForEnclosingEnvToStart(nested_env.get())); |
| RunComponent(launcher_ptr(), glob_url, {"/hub/r/hubscopepolicytest/"}, 0); |
| |
| // test that we can see system objects |
| RunComponent(nested_env->launcher_ptr(), glob_url, |
| {"/hub/c/glob.cmx/*/system_objects"}, 0); |
| } |
| |
| } // namespace |
| } // namespace component |