blob: 0781d1c7c511f6727570f56c712f3ed585913ccd [file] [log] [blame]
// Copyright 2019 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/diagnostics/reader/cpp/archive_reader.h>
#include <optional>
#include <rapidjson/document.h>
#include <zxtest/zxtest.h>
#include "lib/inspect/cpp/hierarchy.h"
namespace {
using diagnostics::reader::InspectData;
TEST(InspectDataTest, ComponentNameExtraction) {
{
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"moniker": "root/hub/my_component"})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
InspectData &datum = data[0];
EXPECT_EQ("root/hub/my_component", datum.moniker());
}
{
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"moniker": "abcd"})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
InspectData &datum = data[0];
EXPECT_EQ("abcd", datum.moniker());
}
{
// Can't find path, empty return.
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"not_moniker": "abcd"})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
InspectData &datum = data[0];
EXPECT_EQ("", datum.moniker());
}
}
TEST(InspectDataTest, ContentExtraction) {
{
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"payload": {"value": "hello", "count": 10}})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
InspectData &datum = data[0];
EXPECT_EQ(rapidjson::Value("hello"), datum.GetByPath({"value"}));
EXPECT_EQ(rapidjson::Value(10), datum.GetByPath({"count"}));
EXPECT_EQ(rapidjson::Value(), datum.GetByPath({"value", "1234"}));
}
{
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"payload": {"name/with/slashes": "hello"}})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
InspectData &datum = data[0];
EXPECT_EQ(rapidjson::Value("hello"), datum.GetByPath({"name/with/slashes"}));
}
{
// Content is missing, return nullptr.
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"moniker": "root/hub/my_component"})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
InspectData &datum = data[0];
EXPECT_EQ(rapidjson::Value(), datum.GetByPath({"value"}));
}
}
TEST(InspectDataTest, ArrayValueCtor) {
{
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"([
{"payload": {"value": "hello", "count": 10}},
{"payload": {"value": "world", "count": 40}}
])");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
InspectData &first = data[0];
InspectData &second = data[1];
EXPECT_EQ(rapidjson::Value("hello"), first.GetByPath({"value"}));
EXPECT_EQ(rapidjson::Value(10), first.GetByPath({"count"}));
EXPECT_EQ(rapidjson::Value(), first.GetByPath({"value", "1234"}));
EXPECT_EQ(rapidjson::Value("world"), second.GetByPath({"value"}));
EXPECT_EQ(rapidjson::Value(40), second.GetByPath({"count"}));
EXPECT_EQ(rapidjson::Value(), second.GetByPath({"value", "1234"}));
}
}
TEST(InspectDataTest, EmptyArray) {
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"payload": { "root": { "test_array": []}}})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
EXPECT_EQ(true, data[0].payload().has_value());
EXPECT_EQ("root", data[0].payload().value()->name());
auto *values =
data[0].payload().value()->node().get_property<inspect::IntArrayValue>("test_array");
ASSERT_NOT_NULL(values);
ASSERT_EQ(0ul, values->value().size());
}
TEST(InspectDataTest, ParseJSON) {
{
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
EXPECT_EQ("", data[0].moniker());
EXPECT_EQ(0, data[0].version());
EXPECT_EQ(std::nullopt, data[0].metadata().filename);
EXPECT_EQ(std::nullopt, data[0].metadata().name);
EXPECT_EQ(std::nullopt, data[0].metadata().component_url);
EXPECT_EQ(0, data[0].metadata().timestamp);
EXPECT_EQ(std::nullopt, data[0].metadata().errors);
EXPECT_EQ(std::nullopt, data[0].payload());
}
{
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"metadata":
{
"filename": "fuchsia.inspect.Tree",
"timestamp": 39085389926
},
"moniker": "bootstrap/archivist",
"version": 1})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
EXPECT_EQ("bootstrap/archivist", data[0].moniker());
EXPECT_EQ(1, data[0].version());
EXPECT_EQ("fuchsia.inspect.Tree", data[0].metadata().filename);
EXPECT_EQ(std::nullopt, data[0].metadata().name);
EXPECT_EQ(std::nullopt, data[0].metadata().component_url);
EXPECT_EQ(39085389926, data[0].metadata().timestamp);
EXPECT_EQ(std::nullopt, data[0].metadata().errors);
EXPECT_EQ(std::nullopt, data[0].payload());
}
{
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"metadata":
{
"name": "MyInspectTree",
"timestamp": 39085389926
},
"moniker": "bootstrap/archivist",
"version": 1})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
EXPECT_EQ("bootstrap/archivist", data[0].moniker());
EXPECT_EQ(1, data[0].version());
EXPECT_EQ(std::nullopt, data[0].metadata().filename);
EXPECT_EQ("MyInspectTree", data[0].metadata().name);
EXPECT_EQ(std::nullopt, data[0].metadata().component_url);
EXPECT_EQ(39085389926, data[0].metadata().timestamp);
EXPECT_EQ(std::nullopt, data[0].metadata().errors);
EXPECT_EQ(std::nullopt, data[0].payload());
}
{
std::vector<diagnostics::reader::InspectData> data;
rapidjson::Document doc;
doc.Parse(R"({"metadata":
{
"filename": "fuchsia.inspect.Tree",
"component_url": "fuchsia-pkg://fuchsia.com/archivist#meta/archivist.cm",
"timestamp": 39085389926,
"errors": [{ "message": "e1"},{ "message": "e2"},{ "message": "e3"}]
},
"payload": {
"root": {
"all_archive_accessor_node": {
"archive_accessor_connections_opened": 2,
"archive_accessor_connections_closed": 0,
"batch_iterator_connection1": {
"batch_iterator_get_next_requests": 1,
"batch_iterator_get_next_responses": 0
}
},
"event_stats": {
"test_array": [1, 2, 3, 4, 5, 6, 7, 8 ],
"sources": {
"v2": {},
"v1": {}
}
},
"fuchsia.inspect.Health": {
"start_timestamp_nanos": 3358357188,
"status": "OK"
},
"test": 5000,
"test1": true
}
},
"moniker": "bootstrap/archivist",
"version": 1})");
diagnostics::reader::EmplaceInspect(std::move(doc), &data);
EXPECT_EQ("bootstrap/archivist", data[0].moniker());
EXPECT_EQ(1, data[0].version());
EXPECT_EQ("fuchsia.inspect.Tree", data[0].metadata().filename);
EXPECT_EQ(std::nullopt, data[0].metadata().name);
EXPECT_EQ("fuchsia-pkg://fuchsia.com/archivist#meta/archivist.cm",
data[0].metadata().component_url);
EXPECT_EQ(39085389926, data[0].metadata().timestamp);
EXPECT_EQ(3, data[0].metadata().errors->size());
EXPECT_EQ("e1", data[0].metadata().errors->at(0).message);
EXPECT_EQ("e2", data[0].metadata().errors->at(1).message);
EXPECT_EQ("e3", data[0].metadata().errors->at(2).message);
EXPECT_EQ(true, data[0].payload().has_value());
EXPECT_EQ("root", data[0].payload().value()->name());
auto root = data[0].payload().value();
auto &rootNode = data[0].payload().value()->node();
const auto accessor = root->GetByPath({"all_archive_accessor_node"});
ASSERT_NOT_NULL(accessor);
ASSERT_NOT_NULL(accessor->node().get_property<inspect::IntPropertyValue>(
"archive_accessor_connections_opened"));
EXPECT_EQ(2, accessor->node()
.get_property<inspect::IntPropertyValue>("archive_accessor_connections_opened")
->value());
ASSERT_NOT_NULL(accessor->node().get_property<inspect::IntPropertyValue>(
"archive_accessor_connections_closed"));
EXPECT_EQ(0, accessor->node()
.get_property<inspect::IntPropertyValue>("archive_accessor_connections_closed")
->value());
auto batchInteratorConnection = accessor->GetByPath({"batch_iterator_connection1"});
ASSERT_NOT_NULL(batchInteratorConnection);
ASSERT_NOT_NULL(batchInteratorConnection->node().get_property<inspect::IntPropertyValue>(
"batch_iterator_get_next_requests"));
EXPECT_EQ(1, batchInteratorConnection->node()
.get_property<inspect::IntPropertyValue>("batch_iterator_get_next_requests")
->value());
ASSERT_NOT_NULL(batchInteratorConnection->node().get_property<inspect::IntPropertyValue>(
"batch_iterator_get_next_responses"));
EXPECT_EQ(0, batchInteratorConnection->node()
.get_property<inspect::IntPropertyValue>("batch_iterator_get_next_responses")
->value());
const auto &health = root->GetByPath({"fuchsia.inspect.Health"});
ASSERT_NOT_NULL(health);
EXPECT_EQ(
3358357188,
health->node().get_property<inspect::IntPropertyValue>("start_timestamp_nanos")->value());
EXPECT_EQ("OK", health->node().get_property<inspect::StringPropertyValue>("status")->value());
const auto &event_stats = root->GetByPath({"event_stats"});
ASSERT_NOT_NULL(event_stats);
ASSERT_NOT_NULL(event_stats->node().get_property<inspect::IntArrayValue>("test_array"));
EXPECT_EQ(1,
event_stats->node().get_property<inspect::IntArrayValue>("test_array")->value()[0]);
EXPECT_EQ(2,
event_stats->node().get_property<inspect::IntArrayValue>("test_array")->value()[1]);
EXPECT_EQ(3,
event_stats->node().get_property<inspect::IntArrayValue>("test_array")->value()[2]);
EXPECT_EQ(4,
event_stats->node().get_property<inspect::IntArrayValue>("test_array")->value()[3]);
EXPECT_EQ(5,
event_stats->node().get_property<inspect::IntArrayValue>("test_array")->value()[4]);
EXPECT_EQ(6,
event_stats->node().get_property<inspect::IntArrayValue>("test_array")->value()[5]);
EXPECT_EQ(7,
event_stats->node().get_property<inspect::IntArrayValue>("test_array")->value()[6]);
EXPECT_EQ(8,
event_stats->node().get_property<inspect::IntArrayValue>("test_array")->value()[7]);
const auto &v1 = event_stats->GetByPath({"sources", "v1"});
ASSERT_NOT_NULL(v1);
const auto &v2 = event_stats->GetByPath({"sources", "v2"});
ASSERT_NOT_NULL(v2);
EXPECT_EQ(2, rootNode.properties().size());
ASSERT_NOT_NULL(rootNode.get_property<inspect::IntPropertyValue>("test"));
EXPECT_EQ(5000, rootNode.get_property<inspect::IntPropertyValue>("test")->value());
ASSERT_NOT_NULL(rootNode.get_property<inspect::BoolPropertyValue>("test1"));
EXPECT_EQ(true, rootNode.get_property<inspect::BoolPropertyValue>("test1")->value());
}
}
} // namespace