blob: 5c6ca3ebcd1a866bde8b067e74df38d731dae976 [file] [log] [blame]
// 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", ""));
}