blob: 16e54b6daf3e3442b5d31fa3eb4d15b3e6ed48fb [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 <fuchsia/inspect/cpp/fidl.h>
#include <lib/async/cpp/executor.h>
#include <lib/fit/single_threaded_executor.h>
#include <lib/gtest/real_loop_fixture.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/inspect/service/cpp/reader.h>
#include <lib/inspect/service/cpp/service.h>
#include <lib/inspect/testing/cpp/inspect.h>
#include <gmock/gmock.h>
using inspect::Hierarchy;
using inspect::Inspector;
using ::testing::AllOf;
using ::testing::UnorderedElementsAre;
using namespace inspect::testing;
namespace {
class InspectReaderTest : public gtest::RealLoopFixture {
public:
InspectReaderTest()
: executor_(dispatcher()),
inspector_(),
handler_(inspect::MakeTreeHandler(&inspector_, dispatcher())) {}
protected:
inspect::Node& root() { return inspector_.GetRoot(); }
fuchsia::inspect::TreePtr Connect(async_dispatcher_t* dispatcher = nullptr) {
fuchsia::inspect::TreePtr ret;
handler_(ret.NewRequest(dispatcher));
return ret;
}
void ResetHandler(async_dispatcher_t* dispatcher) {
handler_ = inspect::MakeTreeHandler(&inspector_, dispatcher);
}
async::Executor executor_;
private:
Inspector inspector_;
fidl::InterfaceRequestHandler<fuchsia::inspect::Tree> handler_;
};
inspect::ValueList RecordValues(inspect::Node& root) {
inspect::ValueList values;
root.CreateInt("val", 1, &values);
root.CreateLazyNode(
"test",
[] {
Inspector insp;
insp.GetRoot().CreateInt("val2", 2, &insp);
insp.GetRoot().CreateLazyValues(
"tempvals",
[] {
Inspector insp;
insp.GetRoot().CreateInt("val3", 3, &insp);
return fit::make_ok_promise(std::move(insp));
},
&insp);
return fit::make_ok_promise(std::move(insp));
},
&values);
root.CreateLazyNode(
"next",
[] {
Inspector insp;
insp.GetRoot().CreateInt("val4", 4, &insp);
return fit::make_ok_promise(std::move(insp));
},
&values);
root.CreateLazyNode(
"node_error", [] { return fit::make_result_promise<Inspector>(fit::error()); }, &values);
root.CreateLazyNode(
"values_error", [] { return fit::make_result_promise<Inspector>(fit::error()); }, &values);
return values;
}
TEST_F(InspectReaderTest, ReadHierarchy) {
inspect::ValueList values;
fit::result<Hierarchy> hierarchy;
auto value_list = RecordValues(root());
bool done = false;
executor_.schedule_task(
inspect::ReadFromTree(Connect()).then([&](fit::result<Hierarchy>& result) {
hierarchy = std::move(result);
done = true;
}));
RunLoopUntil([&] { return done; });
ASSERT_TRUE(hierarchy.is_ok());
EXPECT_THAT(
hierarchy.value(),
AllOf(NodeMatches(NameMatches("root")),
ChildrenMatch(UnorderedElementsAre(
AllOf(NodeMatches(
AllOf(NameMatches("test"),
PropertyList(UnorderedElementsAre(IntIs("val2", 2), IntIs("val3", 3)))))),
AllOf(NodeMatches(AllOf(NameMatches("next"),
PropertyList(UnorderedElementsAre(IntIs("val4", 4))))))))));
}
TEST_F(InspectReaderTest, ReadHierarchyWithDifferentDispatcher) {
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
ResetHandler(loop.dispatcher());
inspect::ValueList values;
fit::result<Hierarchy> hierarchy;
auto value_list = RecordValues(root());
bool done = false;
async::Executor local_executor(loop.dispatcher());
local_executor.schedule_task(
inspect::ReadFromTree(Connect(loop.dispatcher())).then([&](fit::result<Hierarchy>& result) {
hierarchy = std::move(result);
done = true;
}));
while (true) {
loop.Run(zx::deadline_after(zx::msec(10)));
if (done) {
break;
}
}
ASSERT_TRUE(hierarchy.is_ok());
EXPECT_THAT(
hierarchy.value(),
AllOf(NodeMatches(NameMatches("root")),
ChildrenMatch(UnorderedElementsAre(
AllOf(NodeMatches(
AllOf(NameMatches("test"),
PropertyList(UnorderedElementsAre(IntIs("val2", 2), IntIs("val3", 3)))))),
AllOf(NodeMatches(AllOf(NameMatches("next"),
PropertyList(UnorderedElementsAre(IntIs("val4", 4))))))))));
}
} // namespace