blob: 5a0e7ceed3c8d3fa80243e283c0b89e926e0394a [file] [log] [blame]
// 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 <lib/async/cpp/executor.h>
#include <lib/async/default.h>
#include <lib/inspect/contrib/cpp/archive_reader.h>
#include <lib/sys/cpp/testing/test_with_environment_fixture.h>
#include <regex>
#include <gmock/gmock.h>
#include <rapidjson/pointer.h>
#include "lib/zx/time.h"
namespace component {
namespace {
using sys::testing::EnclosingEnvironment;
using ::testing::Eq;
using ::testing::Pointee;
constexpr char kTestComponent1[] =
"fuchsia-pkg://fuchsia.com/archive_reader_integration_tests#meta/"
"archive_reader_test_app.cmx";
constexpr char kTestComponent2[] =
"fuchsia-pkg://fuchsia.com/archive_reader_integration_tests#meta/"
"archive_reader_test_app_2.cmx";
const char CMX1_EXPECTED_DATA[] = R"JSON({
"data_source": "Inspect",
"metadata": {
"component_url": "fuchsia-pkg://fuchsia.com/archive_reader_integration_tests#meta/archive_reader_test_app.cmx",
"filename": "fuchsia.inspect.Tree",
"timestamp": TIMESTAMP
},
"moniker": "test/archive_reader_test_app.cmx",
"payload": {
"root": {
"option_a": {
"value": 10
},
"option_b": {
"value": 20
},
"version": "v1"
}
},
"version": 1
})JSON";
const char CMX2_EXPECTED_DATA[] = R"JSON({
"data_source": "Inspect",
"metadata": {
"component_url": "fuchsia-pkg://fuchsia.com/archive_reader_integration_tests#meta/archive_reader_test_app_2.cmx",
"filename": "fuchsia.inspect.Tree",
"timestamp": TIMESTAMP
},
"moniker": "test/archive_reader_test_app_2.cmx",
"payload": {
"root": {
"option_a": {
"value": 10
},
"option_b": {
"value": 20
},
"version": "v1"
}
},
"version": 1
})JSON";
class ArchiveReaderTest : public gtest::TestWithEnvironmentFixture {
protected:
ArchiveReaderTest() : executor_(dispatcher()) {
environment_ = CreateNewEnclosingEnvironment("test", CreateServices());
{
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kTestComponent1;
bool ready = false;
environment_->CreateComponent(std::move(launch_info), controller_.NewRequest());
controller_.events().OnDirectoryReady = [&ready] { ready = true; };
RunLoopUntil([&ready] { return ready; });
if (!ready) {
printf("The output directory is not ready for component 1\n");
}
controller_->Detach();
}
{
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kTestComponent2;
bool ready = false;
environment_->CreateComponent(std::move(launch_info), controller_.NewRequest());
controller_.events().OnDirectoryReady = [&ready] { ready = true; };
RunLoopUntil([&ready] { return ready; });
if (!ready) {
printf("The output directory is not ready for component 2\n");
}
controller_->Detach();
}
}
protected:
async::Executor executor_;
private:
std::unique_ptr<EnclosingEnvironment> environment_;
fuchsia::sys::ComponentControllerPtr controller_;
};
using ResultType = fpromise::result<std::vector<inspect::contrib::DiagnosticsData>, std::string>;
constexpr char cmx1[] = "archive_reader_test_app.cmx";
constexpr char cmx2[] = "archive_reader_test_app_2.cmx";
constexpr char cmx1_selector[] = "test/archive_reader_test_app.cmx:root";
constexpr char cmx2_selector[] = "test/archive_reader_test_app_2.cmx:root";
TEST_F(ArchiveReaderTest, ReadHierarchy) {
inspect::contrib::ArchiveReader reader(
real_services()->Connect<fuchsia::diagnostics::ArchiveAccessor>(),
{cmx1_selector, cmx2_selector});
ResultType result;
executor_.schedule_task(reader
.SnapshotInspectUntilPresent(
{"archive_reader_test_app.cmx", "archive_reader_test_app_2.cmx"})
.then([&](ResultType& r) { result = std::move(r); }));
RunLoopUntil([&] { return !!result; });
ASSERT_TRUE(result.is_ok()) << "Error: " << result.error();
auto value = result.take_value();
std::sort(value.begin(), value.end(),
[](auto& a, auto& b) { return a.component_name() < b.component_name(); });
EXPECT_EQ(cmx1, value[0].component_name());
EXPECT_EQ(cmx2, value[1].component_name());
EXPECT_STREQ("v1", value[0].content()["root"]["version"].GetString());
EXPECT_STREQ("v1", value[1].content()["root"]["version"].GetString());
}
TEST_F(ArchiveReaderTest, ReadHierarchyWithAlternativeDispatcher) {
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
fuchsia::diagnostics::ArchiveAccessorPtr archive;
real_services()->Connect(archive.NewRequest(loop.dispatcher()));
async::Executor local_executor(loop.dispatcher());
inspect::contrib::ArchiveReader reader(std::move(archive), {cmx1_selector, cmx2_selector});
ResultType result;
local_executor.schedule_task(reader
.SnapshotInspectUntilPresent({"archive_reader_test_app.cmx",
"archive_reader_test_app_2.cmx"})
.then([&](ResultType& r) { result = std::move(r); }));
// Use the alternate loop.
while (true) {
loop.Run(zx::deadline_after(zx::msec(10)));
if (!!result) {
break;
}
}
ASSERT_TRUE(result.is_ok()) << "Error: " << result.error();
auto value = result.take_value();
std::sort(value.begin(), value.end(),
[](auto& a, auto& b) { return a.component_name() < b.component_name(); });
EXPECT_EQ(cmx1, value[0].component_name());
EXPECT_EQ(cmx2, value[1].component_name());
EXPECT_STREQ("v1", value[0].content()["root"]["version"].GetString());
EXPECT_STREQ("v1", value[1].content()["root"]["version"].GetString());
}
TEST_F(ArchiveReaderTest, Sort) {
inspect::contrib::ArchiveReader reader(
real_services()->Connect<fuchsia::diagnostics::ArchiveAccessor>(),
{cmx1_selector, cmx2_selector});
ResultType result;
executor_.schedule_task(reader
.SnapshotInspectUntilPresent(
{"archive_reader_test_app.cmx", "archive_reader_test_app_2.cmx"})
.then([&](ResultType& r) { result = std::move(r); }));
RunLoopUntil([&] { return !!result; });
ASSERT_TRUE(result.is_ok()) << "Error: " << result.error();
auto value = result.take_value();
ASSERT_EQ(2lu, value.size());
std::sort(value.begin(), value.end(),
[](auto& a, auto& b) { return a.component_name() < b.component_name(); });
value[0].Sort();
value[1].Sort();
std::regex reg("\"timestamp\": \\d+");
EXPECT_EQ(CMX1_EXPECTED_DATA,
regex_replace(value[0].PrettyJson(), reg, "\"timestamp\": TIMESTAMP"));
EXPECT_EQ(CMX2_EXPECTED_DATA,
regex_replace(value[1].PrettyJson(), reg, "\"timestamp\": TIMESTAMP"));
}
} // namespace
} // namespace component