blob: d51f5ca339da70cfaac679eb71377c488ae5c8ed [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/fit/single_threaded_executor.h>
#include <lib/inspect/cpp/hierarchy.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/inspect/cpp/reader.h>
#include <type_traits>
#include <zxtest/zxtest.h>
using inspect::Inspector;
using inspect::Node;
namespace {
TEST(Inspect, CreateDeleteActive) {
Node node;
{
auto inspector = std::make_unique<Inspector>();
EXPECT_TRUE(inspector->DuplicateVmo().get() != ZX_HANDLE_INVALID);
EXPECT_TRUE(bool(*inspector));
node = inspector->GetRoot().CreateChild("node");
Node child = node.CreateChild("child");
EXPECT_TRUE(bool(child));
}
EXPECT_TRUE(bool(node));
Node child = node.CreateChild("child");
EXPECT_TRUE(bool(child));
}
TEST(Inspect, CreateChildren) {
auto inspector = std::make_unique<Inspector>();
Node child = inspector->GetRoot().CreateChild("child");
EXPECT_TRUE(bool(child));
auto result = inspect::ReadFromVmo(inspector->DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
ASSERT_EQ(1u, hierarchy.children().size());
EXPECT_EQ("child", hierarchy.children()[0].name());
}
TEST(Inspect, CreateCopyVmo) {
auto inspector = std::make_unique<Inspector>();
// Store a string.
std::string s = "abcd";
auto property = inspector->GetRoot().CreateString("string", s);
auto result = inspect::ReadFromVmo(inspector->CopyVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
EXPECT_EQ(s, hierarchy.node().properties()[0].Get<inspect::StringPropertyValue>().value());
}
TEST(Inspect, GetLinks) {
Inspector inspector;
inspector.GetRoot().CreateLazyNode(
"lazy",
[] {
Inspector insp;
insp.GetRoot().CreateInt("val", 10, &insp);
return fit::make_ok_promise(insp);
},
&inspector);
auto children = inspector.GetChildNames();
ASSERT_EQ(1u, children.size());
EXPECT_EQ("lazy-0", children[0]);
fit::result<Inspector> result;
fit::single_threaded_executor exec;
exec.schedule_task(inspector.OpenChild("lazy-0").then(
[&](fit::result<Inspector>& res) { result = std::move(res); }));
exec.run();
EXPECT_TRUE(result.is_ok());
}
TEST(Inspect, CreateCopyBytes) {
// Make a 16MB heap.
auto inspector = std::make_unique<Inspector>();
// Store a string.
std::string s = "abcd";
auto property = inspector->GetRoot().CreateString("string", s);
auto bytes = inspector->CopyBytes();
auto result = inspect::ReadFromBuffer(std::move(bytes));
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
EXPECT_EQ(s, hierarchy.node().properties()[0].Get<inspect::StringPropertyValue>().value());
}
TEST(Inspect, CreateLargeHeap) {
// Make a 16MB heap.
auto inspector =
std::make_unique<Inspector>(inspect::InspectSettings{.maximum_size = 16 * 1024 * 1024});
// Store a 4MB string.
std::string s(4 * 1024 * 1024, 'a');
auto property = inspector->GetRoot().CreateString("big_string", s);
auto result = inspect::ReadFromVmo(inspector->DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
EXPECT_EQ(s, hierarchy.node().properties()[0].Get<inspect::StringPropertyValue>().value());
}
TEST(Inspect, CreateInvalidSize) {
auto inspector = std::make_unique<Inspector>(inspect::InspectSettings{.maximum_size = 0});
EXPECT_TRUE(inspector->DuplicateVmo().get() == ZX_HANDLE_INVALID);
EXPECT_FALSE(bool(inspector->GetRoot()));
EXPECT_FALSE(bool(*inspector));
}
TEST(Inspect, CreateWithVmoInvalidSize) {
zx::vmo vmo;
ASSERT_OK(zx::vmo::create(0 /* size */, 0, &vmo));
Inspector inspector(std::move(vmo));
EXPECT_FALSE(bool(inspector));
}
TEST(Inspect, CreateWithVmoReadOnly) {
zx::vmo vmo;
ASSERT_OK(zx::vmo::create(4096 /* size */, 0, &vmo));
zx::vmo duplicate;
ASSERT_OK(vmo.duplicate(ZX_RIGHTS_BASIC | ZX_RIGHT_READ, &duplicate));
Inspector inspector(std::move(duplicate));
EXPECT_FALSE(bool(inspector));
}
TEST(Inspect, CreateWithVmoDuplicateVmo) {
zx::vmo vmo;
ASSERT_OK(zx::vmo::create(4096 /* size */, 0, &vmo));
zx::vmo duplicate;
ASSERT_OK(
vmo.duplicate(ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_MAP, &duplicate));
Inspector inspector(std::move(duplicate));
EXPECT_TRUE(bool(inspector));
}
TEST(Inspect, CreateWithDirtyVmo) {
zx::vmo vmo;
ASSERT_OK(zx::vmo::create(4096 /* size */, 0, &vmo));
// Write data into the VMO before using it, internally we will decommit
// the pages to zero them.
std::vector<uint8_t> bytes(4096, 'a');
ASSERT_OK(vmo.write(bytes.data(), 0, bytes.size()));
Inspector inspector(std::move(vmo));
ASSERT_TRUE(bool(inspector));
auto val = inspector.GetRoot().CreateUint("test", 100);
auto result = inspect::ReadFromVmo(inspector.DuplicateVmo());
ASSERT_TRUE(result.is_ok());
auto hierarchy = result.take_value();
EXPECT_EQ(1, hierarchy.node().properties().size());
EXPECT_EQ("test", hierarchy.node().properties()[0].name());
EXPECT_EQ(100, hierarchy.node().properties()[0].Get<inspect::UintPropertyValue>().value());
}
TEST(Inspect, UniqueName) {
inspect::Inspector inspector1, inspector2;
EXPECT_EQ("root0x0", inspector1.GetRoot().UniqueName("root"));
EXPECT_EQ("root0x1", inspector1.GetRoot().UniqueName("root"));
EXPECT_EQ("root0x2", inspector1.GetRoot().UniqueName("root"));
EXPECT_EQ("test0x3", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0x4", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0x5", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0x6", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0x7", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0x8", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0x9", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0xa", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0xb", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0xc", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0xd", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0xe", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0xf", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("test0x10", inspector1.GetRoot().UniqueName("test"));
EXPECT_EQ("root0x0", inspector2.GetRoot().UniqueName("root"));
}
} // namespace