blob: 88a9ce29dc6ecc2f311de9b754858e1d813921fd [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/inspect/cpp/hierarchy.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/inspect/cpp/reader.h>
#include <sdk/lib/inspect/contrib/cpp/read_visitor.h>
#include <zxtest/zxtest.h>
namespace {
using inspect::Inspector;
using inspect::Node;
using inspect::contrib::VisitProperties;
// This macro creates the following tree inside the given inspector:
// root:
// top_level = 1
// test:
// v1 = -1
// v2 = 12u
// v3 = -12
// hist = [[0, 1) = 0, [1, 2) = 0, [2, 3) = 0, [3, 5) = 0, [5, 9) = 1, [9, max) = 0]
// test2:
// v4 = "Hello"
// other_int = -1
// test3:
// v5 = "Goodbye"
#define CREATE_TEST_TREE(inspector) \
auto top_level = inspector.GetRoot().CreateInt("top_level", 1); \
auto child = inspector.GetRoot().CreateChild("test"); \
auto v1 = child.CreateInt("v1", -10); \
auto v2 = child.CreateUint("v2", 12); \
auto v3 = child.CreateInt("v3", -12); \
auto hist = child.CreateExponentialUintHistogram("hist", 1, 1, 2, 4); \
hist.Insert(8); \
auto child2 = child.CreateChild("test2"); \
auto v4 = child2.CreateString("v4", "Hello"); \
auto other_int = child2.CreateInt("other_int", -1); \
\
auto child3 = child.CreateChild("test3"); \
auto v5 = child3.CreateString("v5", "Goodbye");
TEST(ReaderTest, VisitPropertiesWildcard) {
Inspector inspector;
ASSERT_TRUE(static_cast<bool>(inspector));
CREATE_TEST_TREE(inspector);
auto result = inspect::ReadFromVmo(inspector.DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
fit::result<int64_t> v1_result, v3_result;
bool found_other_match = false;
EXPECT_TRUE(VisitProperties<inspect::IntPropertyValue>(
hierarchy, {"test", inspect::contrib::kPathWildcard},
[&](const std::vector<cpp17::string_view> path, const inspect::IntPropertyValue& value) {
if (path.back() == "v1") {
v1_result = fit::ok(value.value());
} else if (path.back() == "v3") {
v3_result = fit::ok(value.value());
} else {
found_other_match = true;
}
}));
EXPECT_FALSE(found_other_match);
ASSERT_TRUE(v1_result.is_ok());
EXPECT_EQ(-10, v1_result.value());
ASSERT_TRUE(v3_result.is_ok());
EXPECT_EQ(-12, v3_result.value());
}
TEST(ReaderTest, VisitPropertiesExact) {
Inspector inspector;
ASSERT_TRUE(static_cast<bool>(inspector));
CREATE_TEST_TREE(inspector);
auto result = inspect::ReadFromVmo(inspector.DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
fit::result<uint64_t> v2_result;
EXPECT_TRUE(VisitProperties<inspect::UintPropertyValue>(
hierarchy, {"test", "v2"},
[&](const std::vector<cpp17::string_view> path, const inspect::UintPropertyValue& value) {
v2_result = fit::ok(value.value());
}));
ASSERT_TRUE(v2_result.is_ok());
EXPECT_EQ(12, v2_result.value());
}
TEST(ReaderTest, VisitPropertiesHistogram) {
Inspector inspector;
ASSERT_TRUE(static_cast<bool>(inspector));
CREATE_TEST_TREE(inspector);
auto result = inspect::ReadFromVmo(inspector.DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
fit::result<std::vector<inspect::UintArrayValue::HistogramBucket>> hist_result;
EXPECT_TRUE(VisitProperties<inspect::UintArrayValue>(
hierarchy, {"test", "hist"},
[&](const std::vector<cpp17::string_view> path, const inspect::UintArrayValue& value) {
hist_result = fit::ok(value.GetBuckets());
}));
ASSERT_TRUE(hist_result.is_ok());
ASSERT_EQ(6, hist_result.value().size());
EXPECT_EQ(inspect::UintArrayValue::HistogramBucket(0, 1, 0), hist_result.value()[0]);
EXPECT_EQ(inspect::UintArrayValue::HistogramBucket(1, 2, 0), hist_result.value()[1]);
EXPECT_EQ(inspect::UintArrayValue::HistogramBucket(2, 3, 0), hist_result.value()[2]);
EXPECT_EQ(inspect::UintArrayValue::HistogramBucket(3, 5, 0), hist_result.value()[3]);
EXPECT_EQ(inspect::UintArrayValue::HistogramBucket(5, 9, 1), hist_result.value()[4]);
EXPECT_EQ(inspect::UintArrayValue::HistogramBucket(9, ULLONG_MAX, 0), hist_result.value()[5]);
}
TEST(ReaderTest, VisitPropertiesRecursive) {
Inspector inspector;
ASSERT_TRUE(static_cast<bool>(inspector));
CREATE_TEST_TREE(inspector);
auto result = inspect::ReadFromVmo(inspector.DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
fit::result<std::string> v4_result;
fit::result<std::string> v5_result;
bool found_other_match = false;
EXPECT_TRUE(VisitProperties<inspect::StringPropertyValue>(
hierarchy, {"test", inspect::contrib::kPathWildcard, inspect::contrib::kPathRecursive},
[&](const std::vector<cpp17::string_view> path, const inspect::StringPropertyValue& value) {
if (path.back() == "v4") {
v4_result = fit::ok(value.value());
}
if (path.back() == "v5") {
v5_result = fit::ok(value.value());
}
}));
EXPECT_FALSE(found_other_match);
ASSERT_TRUE(v4_result.is_ok());
ASSERT_TRUE(v5_result.is_ok());
EXPECT_STR_EQ("Hello", v4_result.value());
EXPECT_STR_EQ("Goodbye", v5_result.value());
}
TEST(ReaderTest, VisitPropertiesAllRecursive) {
Inspector inspector;
ASSERT_TRUE(static_cast<bool>(inspector));
CREATE_TEST_TREE(inspector);
auto result = inspect::ReadFromVmo(inspector.DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
size_t count_found = 0;
EXPECT_TRUE(VisitProperties<inspect::IntPropertyValue>(
hierarchy, {inspect::contrib::kPathRecursive},
[&](const std::vector<cpp17::string_view> path, const inspect::IntPropertyValue& value) {
count_found++;
}));
EXPECT_EQ(4, count_found);
}
TEST(ReaderTest, VisitPropertiesInvalidRecursiveWildcard) {
Inspector inspector;
ASSERT_TRUE(static_cast<bool>(inspector));
CREATE_TEST_TREE(inspector);
auto result = inspect::ReadFromVmo(inspector.DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
// Recursive wildcard must be at end.
size_t count_found = 0;
EXPECT_FALSE(VisitProperties<inspect::IntPropertyValue>(
hierarchy, {inspect::contrib::kPathRecursive, "v1"},
[&](const std::vector<cpp17::string_view> path, const inspect::IntPropertyValue& value) {
count_found++;
}));
EXPECT_EQ(0, count_found);
// Calling without path should be OK.
EXPECT_FALSE(VisitProperties<inspect::IntPropertyValue>(
hierarchy, {},
[&](const std::vector<cpp17::string_view> path, const inspect::IntPropertyValue& value) {}));
}
} // namespace