blob: 6556a276f2fbfffeceac6e8bf153a06ad65455ca [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 <fuchsia/inspect/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/fdio/util.h>
#include "gmock/gmock.h"
#include "lib/component/cpp/environment_services_helper.h"
#include "lib/component/cpp/expose.h"
#include "lib/component/cpp/testing/test_util.h"
#include "lib/component/cpp/testing/test_with_environment.h"
#include "lib/fxl/files/glob.h"
#include "lib/fxl/strings/substitute.h"
#include "lib/svc/cpp/services.h"
namespace component {
namespace {
using ::fxl::Substitute;
using ::testing::ElementsAre;
using testing::EnclosingEnvironment;
using ::testing::UnorderedElementsAre;
using ByteVector = ::component::Property::ByteVector;
const char kTestComponent[] = "fuchsia-pkg://fuchsia.com/inspect_test_app#meta/inspect_test_app.cmx";
const char kTestProcessName[] = "inspect_test_app.cmx";
class InspectTest : public component::testing::TestWithEnvironment {
protected:
InspectTest() {
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kTestComponent;
environment_ = CreateNewEnclosingEnvironment("test", CreateServices());
environment_->CreateComponent(std::move(launch_info),
controller_.NewRequest());
bool ready = false;
controller_.events().OnDirectoryReady = [&ready] { ready = true; };
RunLoopWithTimeoutOrUntil([&ready] { return ready; }, zx::sec(10));
}
~InspectTest() { CheckShutdown(); }
void CheckShutdown() {
controller_->Kill();
bool done = false;
controller_.events().OnTerminated =
[&done](int64_t code, fuchsia::sys::TerminationReason reason) {
ASSERT_EQ(fuchsia::sys::TerminationReason::EXITED, reason);
done = true;
};
ASSERT_TRUE(
RunLoopWithTimeoutOrUntil([&done] { return done; }, zx::sec(10)));
}
std::string GetObjectPath(const std::string& relative_path) {
files::Glob glob(
Substitute("/hub/r/test/*/c/$0/*/out/objects", kTestProcessName));
if (glob.size() == 0) {
return "";
}
std::string path = *glob.begin();
return Substitute("$0/$1", path, relative_path);
}
std::vector<std::string> GetGlob(const std::string& path) {
files::Glob glob(GetObjectPath("*"));
return std::vector<std::string>{glob.begin(), glob.end()};
}
private:
std::unique_ptr<EnclosingEnvironment> environment_;
fuchsia::sys::ComponentControllerPtr controller_;
};
TEST_F(InspectTest, InspectTopLevel) {
EXPECT_THAT(
GetGlob(GetObjectPath("*")),
ElementsAre(GetObjectPath("lazy_child"), GetObjectPath("table-t1"),
GetObjectPath("table-t2")));
}
MATCHER_P2(StringProperty, name, value, "") {
return arg.value.is_str() && arg.key == name && arg.value.str() == value;
}
MATCHER_P2(VectorProperty, name, value, "") {
return arg.value.is_bytes() && arg.key == name && arg.value.bytes() == value;
}
MATCHER_P2(UIntMetric, name, value, "") {
return arg.key == name && arg.value.is_uint_value() &&
arg.value.uint_value() == (uint64_t)value;
}
MATCHER_P2(IntMetric, name, value, "") {
return arg.key == name && arg.value.is_int_value() &&
arg.value.int_value() == (int64_t)value;
}
TEST_F(InspectTest, InspectOpenRead) {
fuchsia::inspect::InspectSyncPtr inspect;
ASSERT_EQ(ZX_OK,
fdio_service_connect(GetObjectPath("table-t1/.channel").c_str(),
inspect.NewRequest().TakeChannel().release()));
fidl::VectorPtr<std::string> children;
ASSERT_EQ(ZX_OK, inspect->ListChildren(&children));
EXPECT_THAT(*children, UnorderedElementsAre("item-0x0", "item-0x1"));
fuchsia::inspect::Object obj;
ASSERT_EQ(ZX_OK, inspect->ReadData(&obj));
EXPECT_EQ("table-t1", obj.name);
EXPECT_THAT(*obj.properties,
UnorderedElementsAre(
StringProperty("version", "1.0"),
VectorProperty("frame", ByteVector({0x10, 0x00, 0x10})),
VectorProperty("\x10\x10", ByteVector({0x00, 0x00, 0x00}))));
EXPECT_THAT(*obj.metrics, UnorderedElementsAre(UIntMetric("item_size", 32),
IntMetric("\x10", -10)));
ASSERT_EQ(ZX_OK,
fdio_service_connect(GetObjectPath("table-t2/.channel").c_str(),
inspect.NewRequest().TakeChannel().release()));
children->clear();
ASSERT_EQ(ZX_OK, inspect->ListChildren(&children));
EXPECT_THAT(*children, UnorderedElementsAre("item-0x2", "table-subtable"));
obj = fuchsia::inspect::Object();
ASSERT_EQ(ZX_OK, inspect->ReadData(&obj));
EXPECT_EQ("table-t2", obj.name);
fuchsia::inspect::Object subtable;
fuchsia::inspect::InspectSyncPtr child_request;
bool ok = false;
ASSERT_EQ(ZX_OK, inspect->OpenChild("table-subtable",
child_request.NewRequest(), &ok));
ASSERT_TRUE(ok);
child_request->ReadData(&subtable);
EXPECT_EQ(subtable.name, "table-subtable");
children->clear();
ASSERT_EQ(ZX_OK, child_request->ListChildren(&children));
EXPECT_THAT(*children, UnorderedElementsAre("item-0x3"));
EXPECT_THAT(*subtable.metrics,
UnorderedElementsAre(UIntMetric("item_size", 16),
IntMetric("\x10", -10)));
ASSERT_EQ(ZX_OK,
fdio_service_connect(GetObjectPath(".channel").c_str(),
inspect.NewRequest().TakeChannel().release()));
fuchsia::inspect::InspectSyncPtr lazy_child;
bool open_ok;
inspect->OpenChild("lazy_child", lazy_child.NewRequest(), &open_ok);
ASSERT_TRUE(open_ok);
obj = fuchsia::inspect::Object();
lazy_child->ReadData(&obj);
EXPECT_THAT(*obj.properties,
UnorderedElementsAre(StringProperty("version", "1")));
}
} // namespace
} // namespace component