blob: d656efb47a12ea813d2029cd159664deffdb4f8f [file] [log] [blame]
// Copyright 2021 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/component/config/cpp/fidl.h>
#include <fuchsia/component/test/cpp/fidl.h>
#include <fuchsia/io/cpp/fidl.h>
#include <fuchsia/mem/cpp/fidl.h>
#include <lib/fdio/namespace.h>
#include <lib/sys/component/cpp/testing/internal/errors.h>
#include <lib/sys/component/cpp/testing/realm_builder_types.h>
#include <lib/sys/cpp/outgoing_directory.h>
#include <lib/zx/channel.h>
#include <lib/zx/vmo.h>
#include <zircon/assert.h>
#include <zircon/types.h>
#include <memory>
#include "zircon/status.h"
namespace component_testing {
namespace {
constexpr char kSvcDirectoryPath[] = "/svc";
#define ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(MethodName, Type, FidlType) \
ConfigValue ConfigValue::MethodName(Type value) { \
fuchsia::component::config::ValueSpec spec; \
spec.set_value(fuchsia::component::config::Value::WithSingle( \
fuchsia::component::config::SingleValue::FidlType(std::move(value)))); \
return ConfigValue(std::move(spec)); \
}
#define ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_CTOR_DEF(Type, FidlType) \
ConfigValue::ConfigValue(Type value) { \
spec.set_value(fuchsia::component::config::Value::WithSingle( \
fuchsia::component::config::SingleValue::FidlType(std::move(value)))); \
}
#define ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(Type, FidlType) \
ConfigValue::ConfigValue(Type value) { \
spec.set_value(fuchsia::component::config::Value::WithVector( \
fuchsia::component::config::VectorValue::FidlType(std::move(value)))); \
}
// Checks that path doesn't contain leading nor trailing slashes.
bool IsValidPath(std::string_view path) {
return !path.empty() && path.front() != '/' && path.back() != '/';
}
} // namespace
LocalComponent::~LocalComponent() = default;
LocalComponentHandles::LocalComponentHandles(fdio_ns_t* ns, sys::OutgoingDirectory outgoing_dir)
: namespace_(ns), outgoing_dir_(std::move(outgoing_dir)) {}
LocalComponentHandles::~LocalComponentHandles() { ZX_ASSERT(fdio_ns_destroy(namespace_) == ZX_OK); }
LocalComponentHandles::LocalComponentHandles(LocalComponentHandles&& other) noexcept
: namespace_(other.namespace_), outgoing_dir_(std::move(other.outgoing_dir_)) {
other.namespace_ = nullptr;
}
LocalComponentHandles& LocalComponentHandles::operator=(LocalComponentHandles&& other) noexcept {
namespace_ = other.namespace_;
outgoing_dir_ = std::move(other.outgoing_dir_);
other.namespace_ = nullptr;
return *this;
}
fdio_ns_t* LocalComponentHandles::ns() { return namespace_; }
sys::OutgoingDirectory* LocalComponentHandles::outgoing() { return &outgoing_dir_; }
sys::ServiceDirectory LocalComponentHandles::svc() {
zx::channel local;
zx::channel remote;
ZX_COMPONENT_ASSERT_STATUS_OK("zx::channel/create", zx::channel::create(0, &local, &remote));
// TODO(https://fxbug.dev/101092): Replace this with fdio_ns_service_connect when
// ServiceDirectory::Connect (via fdio_service_connect_at) no longer requests R/W.
constexpr uint32_t kServiceFlags = static_cast<uint32_t>(fuchsia::io::OpenFlags::RIGHT_READABLE |
fuchsia::io::OpenFlags::RIGHT_WRITABLE);
auto status = fdio_ns_open(namespace_, kSvcDirectoryPath, kServiceFlags, remote.release());
ZX_ASSERT_MSG(status == ZX_OK,
"fdio_ns_service_connect on LocalComponent's /svc directory failed: %s\nThis most"
"often occurs when a component has no FIDL protocols routed to it.",
zx_status_get_string(status));
return sys::ServiceDirectory(std::move(local));
}
constexpr size_t kDefaultVmoSize = 4096;
DirectoryContents& DirectoryContents::AddFile(std::string_view path, BinaryContents contents) {
ZX_ASSERT_MSG(IsValidPath(path), "[DirectoryContents/AddFile] Encountered invalid path: %s",
path.data());
zx::vmo vmo;
ZX_COMPONENT_ASSERT_STATUS_OK("AddFile/zx_vmo_create", zx::vmo::create(kDefaultVmoSize, 0, &vmo));
ZX_COMPONENT_ASSERT_STATUS_OK("AddFile/zx_vmo_write",
vmo.write(contents.buffer, contents.offset, contents.size));
fuchsia::mem::Buffer out_buffer{.vmo = std::move(vmo), .size = contents.size};
contents_.entries.emplace_back(fuchsia::component::test::DirectoryEntry{
.file_path = std::string(path), .file_contents = std::move(out_buffer)});
return *this;
}
DirectoryContents& DirectoryContents::AddFile(std::string_view path, std::string_view contents) {
return AddFile(path,
BinaryContents{.buffer = contents.data(), .size = contents.size(), .offset = 0});
}
fuchsia::component::test::DirectoryContents DirectoryContents::TakeAsFidl() {
return std::move(contents_);
}
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_CTOR_DEF(std::string, WithString)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_CTOR_DEF(const char*, WithString)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(Bool, bool, WithBool_)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(Uint8, uint8_t, WithUint8)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(Uint16, uint16_t, WithUint16)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(Uint32, uint32_t, WithUint32)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(Uint64, uint64_t, WithUint64)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(Int8, int8_t, WithInt8)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(Int16, int16_t, WithInt16)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(Int32, int32_t, WithInt32)
ZX_SYS_COMPONENT_REPLACE_CONFIG_SINGLE_VALUE_DEF(Int64, int64_t, WithInt64)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<bool>, WithBoolVector)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<uint8_t>, WithUint8Vector)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<uint16_t>, WithUint16Vector)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<uint32_t>, WithUint32Vector)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<uint64_t>, WithUint64Vector)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<int8_t>, WithInt8Vector)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<int16_t>, WithInt16Vector)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<int32_t>, WithInt32Vector)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<int64_t>, WithInt64Vector)
ZX_SYS_COMPONENT_REPLACE_CONFIG_VECTOR_VALUE_CTOR_DEF(std::vector<std::string>, WithStringVector)
ConfigValue::ConfigValue(fuchsia::component::config::ValueSpec spec) : spec(std::move(spec)) {}
ConfigValue& ConfigValue::operator=(ConfigValue&& other) noexcept {
spec = std::move(other.spec);
return *this;
}
ConfigValue::ConfigValue(ConfigValue&& other) noexcept : spec(std::move(other.spec)) {}
fuchsia::component::config::ValueSpec ConfigValue::TakeAsFidl() { return std::move(spec); }
} // namespace component_testing