| // Copyright 2020 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/diagnostics/cpp/fidl.h> | |
| #include <fuchsia/examples/inspect/cpp/fidl.h> | |
| #include <lib/async/cpp/executor.h> | |
| #include <lib/fidl/cpp/binding_set.h> | |
| #include <lib/sys/cpp/testing/test_with_environment.h> | |
| // [START include_json] | |
| #include <rapidjson/document.h> | |
| #include <rapidjson/pointer.h> | |
| // [END include_json] | |
| #include <src/lib/fsl/vmo/strings.h> | |
| constexpr char reverser_url[] = | |
| "fuchsia-pkg://fuchsia.com/inspect_cpp_codelab_integration_tests#meta/" | |
| "inspect_cpp_codelab_part_5.cmx"; | |
| constexpr char fizzbuzz_url[] = | |
| "fuchsia-pkg://fuchsia.com/inspect_cpp_codelab_integration_tests#meta/" | |
| "inspect_cpp_codelab_fizzbuzz.cmx"; | |
| class CodelabTest : public sys::testing::TestWithEnvironment { | |
| protected: | |
| // Options for each test. | |
| struct TestOptions { | |
| // If true, inject a FizzBuzz service implementation. | |
| bool include_fizzbuzz_service; | |
| }; | |
| fuchsia::examples::inspect::ReverserPtr StartComponentAndConnect(TestOptions options) { | |
| // Create an environment for the test that simulates the "sys" realm. | |
| // We optionally inject the "FizzBuzz" service if requested. | |
| auto services = CreateServices(); | |
| if (options.include_fizzbuzz_service) { | |
| services->AddServiceWithLaunchInfo({.url = fizzbuzz_url}, | |
| fuchsia::examples::inspect::FizzBuzz::Name_); | |
| } | |
| environment_ = CreateNewEnclosingEnvironment("sys", std::move(services)); | |
| // Start the Reverser component in the nested environment. | |
| fuchsia::io::DirectoryPtr directory_request; | |
| controller_ = environment_->CreateComponent( | |
| {.url = reverser_url, .directory_request = directory_request.NewRequest().TakeChannel()}); | |
| // Connect to Reverser hosted by the new component. | |
| fuchsia::examples::inspect::ReverserPtr ret; | |
| sys::ServiceDirectory component_services(directory_request.Unbind()); | |
| component_services.Connect(ret.NewRequest()); | |
| bool ready = false; | |
| controller_.events().OnDirectoryReady = [&] { ready = true; }; | |
| RunLoopUntil([&] { return ready; }); | |
| return ret; | |
| } | |
| using ContentVector = std::vector<fuchsia::diagnostics::FormattedContent>; | |
| // [START get_inspect] | |
| std::string GetInspectJson() { | |
| fuchsia::diagnostics::ArchiveAccessorPtr archive; | |
| real_services()->Connect(archive.NewRequest()); | |
| while (true) { | |
| ContentVector current_entries; | |
| fuchsia::diagnostics::BatchIteratorPtr iterator; | |
| fuchsia::diagnostics::StreamParameters stream_parameters; | |
| stream_parameters.set_data_type(fuchsia::diagnostics::DataType::INSPECT); | |
| stream_parameters.set_stream_mode(fuchsia::diagnostics::StreamMode::SNAPSHOT); | |
| stream_parameters.set_format(fuchsia::diagnostics::Format::JSON); | |
| { | |
| std::vector<fuchsia::diagnostics::SelectorArgument> args; | |
| args.emplace_back(); | |
| args[0].set_raw_selector("sys/inspect_cpp_codelab_part_5.cmx:root"); | |
| fuchsia::diagnostics::ClientSelectorConfiguration client_selector_config; | |
| client_selector_config.set_selectors(std::move(args)); | |
| stream_parameters.set_client_selector_configuration(std::move(client_selector_config)); | |
| } | |
| archive->StreamDiagnostics(std::move(stream_parameters), iterator.NewRequest()); | |
| bool done = false; | |
| iterator->GetNext([&](auto result) { | |
| auto res = fit::result<ContentVector, fuchsia::diagnostics::ReaderError>(std::move(result)); | |
| if (res.is_ok()) { | |
| current_entries = res.take_value(); | |
| } | |
| done = true; | |
| }); | |
| RunLoopUntil([&] { return done; }); | |
| // Should be at most one component. | |
| ZX_ASSERT(current_entries.size() <= 1); | |
| if (!current_entries.empty()) { | |
| std::string json; | |
| fsl::StringFromVmo(current_entries[0].json(), &json); | |
| // Ensure the component is either OK or UNHEALTHY. | |
| if (json.find("OK") != std::string::npos || json.find("UNHEALTHY") != std::string::npos) { | |
| return json; | |
| } | |
| } | |
| // Retry with delay until the data appears. | |
| usleep(150000); | |
| } | |
| return ""; | |
| } | |
| // [END get_inspect] | |
| private: | |
| std::unique_ptr<sys::testing::EnclosingEnvironment> environment_; | |
| fuchsia::sys::ComponentControllerPtr controller_; | |
| }; | |
| TEST_F(CodelabTest, StartWithFizzBuzz) { | |
| auto ptr = StartComponentAndConnect({.include_fizzbuzz_service = true}); | |
| bool error = false; | |
| ptr.set_error_handler([&](zx_status_t unused) { error = true; }); | |
| bool done = false; | |
| std::string result; | |
| ptr->Reverse("hello", [&](std::string value) { | |
| result = std::move(value); | |
| done = true; | |
| }); | |
| RunLoopUntil([&] { return done || error; }); | |
| ASSERT_FALSE(error); | |
| EXPECT_EQ("olleh", result); | |
| // [START parse_result] | |
| rapidjson::Document document; | |
| document.Parse(GetInspectJson()); | |
| // [END parse_result] | |
| EXPECT_EQ(rapidjson::Value("OK"), | |
| // [START hint_get_value] | |
| rapidjson::GetValueByPointerWithDefault( | |
| document, "/payload/root/fuchsia.inspect.Health/status", "") | |
| // [END hint_get_value] | |
| ); | |
| } | |
| TEST_F(CodelabTest, StartWithoutFizzBuzz) { | |
| auto ptr = StartComponentAndConnect({.include_fizzbuzz_service = false}); | |
| bool error = false; | |
| ptr.set_error_handler([&](zx_status_t unused) { error = true; }); | |
| bool done = false; | |
| std::string result; | |
| ptr->Reverse("hello", [&](std::string value) { | |
| result = std::move(value); | |
| done = true; | |
| }); | |
| RunLoopUntil([&] { return done || error; }); | |
| ASSERT_FALSE(error); | |
| EXPECT_EQ("olleh", result); | |
| rapidjson::Document document; | |
| document.Parse(GetInspectJson()); | |
| EXPECT_EQ(rapidjson::Value("UNHEALTHY"), | |
| rapidjson::GetValueByPointerWithDefault( | |
| document, "/payload/root/fuchsia.inspect.Health/status", "")); | |
| } |