blob: 874f2d6f9ee6368dc56ebd30c27b05303173aa40 [file] [log] [blame]
// Copyright 2020 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/driver/component/cpp/start_args.h>
#include <lib/zx/eventpair.h>
#include <array>
#include <gtest/gtest.h>
#include "src/lib/testing/predicates/status.h"
namespace fdf {
using namespace fuchsia_driver_framework;
} // namespace fdf
namespace fdata = fuchsia_data;
namespace frunner = fuchsia_component_runner;
TEST(StartArgsTest, SymbolValueWire) {
fidl::Arena arena;
fidl::VectorView<fdf::wire::NodeSymbol> symbol_entries(arena, 1);
symbol_entries[0].Allocate(arena);
symbol_entries[0].set_name(arena, "sym").set_address(arena, 0xfeed);
fdf::wire::DriverStartArgs args(arena);
args.set_symbols(arena, symbol_entries);
EXPECT_EQ(0xfeedu, *fdf::SymbolValue<zx_vaddr_t>(args, "sym"));
EXPECT_EQ(ZX_ERR_NOT_FOUND, fdf::SymbolValue<zx_vaddr_t>(args, "unknown").error_value());
}
TEST(StartArgsTest, SymbolValue) {
std::vector<fdf::NodeSymbol> symbol_entries(1);
symbol_entries[0] = fdf::NodeSymbol({
.name = "sym",
.address = 0xfeed,
});
EXPECT_EQ(0xfeedu, *fdf::SymbolValue<zx_vaddr_t>(symbol_entries, "sym"));
EXPECT_EQ(ZX_ERR_NOT_FOUND,
fdf::SymbolValue<zx_vaddr_t>(symbol_entries, "unknown").error_value());
}
TEST(StartArgsTest, ProgramValueWire) {
fidl::Arena arena;
fidl::VectorView<fdata::wire::DictionaryEntry> program_entries(arena, 2);
program_entries[0].key.Set(arena, "key-for-str");
program_entries[0].value = fdata::wire::DictionaryValue::WithStr(arena, "value-for-str");
program_entries[1].key.Set(arena, "key-for-strvec");
program_entries[1].value = fdata::wire::DictionaryValue::WithStrVec(arena);
fdata::wire::Dictionary program(arena);
program.set_entries(arena, std::move(program_entries));
EXPECT_EQ("value-for-str", *fdf::ProgramValue(program, "key-for-str"));
EXPECT_EQ(ZX_ERR_WRONG_TYPE, fdf::ProgramValue(program, "key-for-strvec").error_value());
EXPECT_EQ(ZX_ERR_NOT_FOUND, fdf::ProgramValue(program, "key-unkown").error_value());
fdata::wire::Dictionary empty_program;
EXPECT_EQ(ZX_ERR_NOT_FOUND, fdf::ProgramValue(empty_program, "").error_value());
}
TEST(StartArgsTest, ProgramValue) {
std::vector<fdata::DictionaryEntry> program_entries(2);
program_entries[0] = fdata::DictionaryEntry(
"key-for-str", std::make_unique<fuchsia_data::DictionaryValue>(
fuchsia_data::DictionaryValue::WithStr("value-for-str")));
program_entries[1] =
fdata::DictionaryEntry("key-for-strvec", std::make_unique<fuchsia_data::DictionaryValue>(
fuchsia_data::DictionaryValue::WithStrVec({})));
auto program = fdata::Dictionary({
.entries = std::move(program_entries),
});
EXPECT_EQ("value-for-str", *fdf::ProgramValue(program, "key-for-str"));
EXPECT_EQ(ZX_ERR_WRONG_TYPE, fdf::ProgramValue(program, "key-for-strvec").error_value());
EXPECT_EQ(ZX_ERR_NOT_FOUND, fdf::ProgramValue(program, "key-unkown").error_value());
fdata::Dictionary empty_program;
EXPECT_EQ(ZX_ERR_NOT_FOUND, fdf::ProgramValue(empty_program, "").error_value());
}
TEST(StartArgsTest, ProgramValueAsVectorWire) {
fidl::Arena arena;
fidl::VectorView<fdata::wire::DictionaryEntry> program_entries(arena, 2);
program_entries[0].key.Set(arena, "key-for-str");
program_entries[0].value = fdata::wire::DictionaryValue::WithStr(arena, "value-for-str");
fidl::StringView strs[]{
fidl::StringView{"test"},
fidl::StringView{"test2"},
};
program_entries[1].key.Set(arena, "key-for-strvec");
program_entries[1].value = fdata::wire::DictionaryValue::WithStrVec(
arena, fidl::VectorView<fidl::StringView>::FromExternal(strs));
fdata::wire::Dictionary program(arena);
program.set_entries(arena, std::move(program_entries));
auto values = fdf::ProgramValueAsVector(program, "key-for-strvec");
EXPECT_EQ(2lu, values->size());
std::sort(values->begin(), values->end());
EXPECT_EQ("test", (*values)[0]);
EXPECT_EQ("test2", (*values)[1]);
EXPECT_EQ(ZX_ERR_WRONG_TYPE, fdf::ProgramValueAsVector(program, "key-for-str").error_value());
EXPECT_EQ(ZX_ERR_NOT_FOUND, fdf::ProgramValueAsVector(program, "key-unkown").error_value());
fdata::wire::Dictionary empty_program;
EXPECT_EQ(ZX_ERR_NOT_FOUND, fdf::ProgramValueAsVector(empty_program, "").error_value());
}
TEST(StartArgsTest, ProgramValueAsVector) {
std::vector<fdata::DictionaryEntry> program_entries(2);
program_entries[0] = fdata::DictionaryEntry(
"key-for-str", std::make_unique<fuchsia_data::DictionaryValue>(
fuchsia_data::DictionaryValue::WithStr("value-for-str")));
program_entries[1] = fdata::DictionaryEntry(
"key-for-strvec",
std::make_unique<fuchsia_data::DictionaryValue>(fuchsia_data::DictionaryValue::WithStrVec({
"test",
"test2",
})));
fdata::Dictionary program({
.entries = std::move(program_entries),
});
auto values = fdf::ProgramValueAsVector(program, "key-for-strvec");
EXPECT_EQ(2lu, values->size());
std::sort(values->begin(), values->end());
EXPECT_EQ("test", (*values)[0]);
EXPECT_EQ("test2", (*values)[1]);
EXPECT_EQ(ZX_ERR_WRONG_TYPE, fdf::ProgramValueAsVector(program, "key-for-str").error_value());
EXPECT_EQ(ZX_ERR_NOT_FOUND, fdf::ProgramValueAsVector(program, "key-unkown").error_value());
fdata::Dictionary empty_program;
EXPECT_EQ(ZX_ERR_NOT_FOUND, fdf::ProgramValueAsVector(empty_program, "").error_value());
}
TEST(StartArgsTest, NsValueWire) {
auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
ASSERT_EQ(ZX_OK, endpoints.status_value());
zx_handle_t client_handle = endpoints->client.handle()->get();
fidl::Arena arena;
fidl::VectorView<frunner::wire::ComponentNamespaceEntry> ns_entries(arena, 1);
ns_entries[0].Allocate(arena);
ns_entries[0].set_path(arena, "/svc").set_directory(std::move(endpoints->client));
auto svc = fdf::NsValue(ns_entries, "/svc");
ASSERT_EQ(svc->handle()->get(), client_handle);
auto pkg = fdf::NsValue(ns_entries, "/pkg");
EXPECT_EQ(ZX_ERR_NOT_FOUND, pkg.error_value());
}
TEST(StartArgsTest, NsValue) {
auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
ASSERT_EQ(ZX_OK, endpoints.status_value());
zx_handle_t client_handle = endpoints->client.handle()->get();
std::vector<frunner::ComponentNamespaceEntry> ns_entries(1);
ns_entries[0] = frunner::ComponentNamespaceEntry({
.path = "/svc",
.directory = std::move(endpoints->client),
});
auto svc = fdf::NsValue(ns_entries, "/svc");
ASSERT_EQ(svc->handle()->get(), client_handle);
auto pkg = fdf::NsValue(ns_entries, "/pkg");
EXPECT_EQ(ZX_ERR_NOT_FOUND, pkg.error_value());
}
TEST(StartArgsTest, AdoptEncodedFidlMessage) {
std::array<uint8_t, 16> bytes;
bytes.fill(1);
zx::eventpair ep1, ep2;
ASSERT_OK(zx::eventpair::create(0, &ep1, &ep2));
zx_handle_t handles[] = {
ep1.get(),
};
EncodedFidlMessage msg{
.bytes = bytes.data(),
.handles = handles,
.num_bytes = static_cast<uint32_t>(bytes.size()),
.num_handles = static_cast<uint32_t>(std::size(handles)),
};
// Handles should be closed when the message goes out of scope.
{ fdf::AdoptEncodedFidlMessage adopted{msg}; }
zx_signals_t observed = ZX_SIGNAL_NONE;
ASSERT_OK(ep2.wait_one(ZX_EVENTPAIR_PEER_CLOSED, zx::time::infinite_past(), &observed));
EXPECT_EQ(observed, ZX_EVENTPAIR_PEER_CLOSED);
[[maybe_unused]] zx_handle_t h = ep1.release();
}
TEST(StartArgsTest, AdoptEncodedFidlMessageToFidl) {
std::array<uint8_t, 16> bytes;
bytes.fill(1);
zx::eventpair ep1, ep2;
ASSERT_OK(zx::eventpair::create(0, &ep1, &ep2));
zx_handle_t handles[] = {
ep1.get(),
};
EncodedFidlMessage msg{
.bytes = bytes.data(),
.handles = handles,
.num_bytes = static_cast<uint32_t>(bytes.size()),
.num_handles = static_cast<uint32_t>(std::size(handles)),
};
fdf::AdoptEncodedFidlMessage adopted{msg};
// Handles should be closed when the message goes out of scope.
{ fidl::EncodedMessage encoded = adopted.TakeMessage(); }
zx_signals_t observed = ZX_SIGNAL_NONE;
ASSERT_OK(ep2.wait_one(ZX_EVENTPAIR_PEER_CLOSED, zx::time::infinite_past(), &observed));
EXPECT_EQ(observed, ZX_EVENTPAIR_PEER_CLOSED);
[[maybe_unused]] zx_handle_t h = ep1.release();
}