blob: 7d31f33438fb742720931d6ff49949234a4a84e5 [file] [log] [blame]
// Copyright 2025 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 "src/developer/debug/debug_agent/testing/runtime_dir_helper.h"
#include <gtest/gtest.h>
#include "fbl/ref_ptr.h"
#include "fidl/fuchsia.io/cpp/fidl.h"
#include "fidl/fuchsia.io/cpp/markers.h"
#include "fidl/fuchsia.io/cpp/natural_types.h"
#include "lib/fidl/cpp/wire/channel.h"
#include "lib/fidl/cpp/wire/internal/transport_channel.h"
#include "lib/syslog/cpp/macros.h"
#include "src/storage/lib/vfs/cpp/managed_vfs.h"
#include "src/storage/lib/vfs/cpp/pseudo_dir.h"
#include "src/storage/lib/vfs/cpp/pseudo_file.h"
namespace testing {
namespace {
fbl::RefPtr<fs::PseudoDir> MakeElfJobIdFile(zx_koid_t job) {
auto job_id_file =
fbl::MakeRefCounted<fs::UnbufferedPseudoFile>([job](fbl::String* output) -> zx_status_t {
*output = std::to_string(job);
return ZX_OK;
});
auto elf_dir = fbl::MakeRefCounted<fs::PseudoDir>();
FX_CHECK(elf_dir->AddEntry("job_id", std::move(job_id_file)) == ZX_OK);
auto job_dir = fbl::MakeRefCounted<fs::PseudoDir>();
FX_CHECK(job_dir->AddEntry("elf", std::move(elf_dir)) == ZX_OK);
return job_dir;
}
fuchsia_io::DirectoryOpenRequest MakeDirOpenRequest(
std::string_view dirname, fidl::ServerEnd<fuchsia_io::Directory> server_end) {
fuchsia_io::DirectoryOpenRequest r;
r.path(std::string{dirname});
r.flags(fuchsia_io::kPermReadable);
r.object(server_end.TakeChannel());
return r;
}
} // namespace
RuntimeDirHelper::~RuntimeDirHelper() { Cleanup(); }
void RuntimeDirHelper::Start(async_dispatcher_t* client_dispatcher) {
ASSERT_FALSE(root_dir_client_.is_valid());
ASSERT_TRUE(root_dir_);
auto [client_end, server_end] = *fidl::CreateEndpoints<fuchsia_io::Directory>();
ASSERT_EQ(vfs_.ServeDirectory(std::move(root_dir_), std::move(server_end)), ZX_OK);
ASSERT_EQ(loop_.StartThread(), ZX_OK);
// |root_dir_| is now invalid.
root_dir_client_.Bind(std::move(client_end), client_dispatcher);
}
void RuntimeDirHelper::Cleanup() {
vfs_.Shutdown([loop = &loop_](zx_status_t status) {
ASSERT_EQ(status, ZX_OK);
loop->Quit();
});
loop_.JoinThreads();
}
void RuntimeDirHelper::AddJobIdFile(zx_koid_t job) {
ASSERT_FALSE(root_dir_client_.is_valid());
ASSERT_TRUE(root_dir_);
auto job_dir = MakeElfJobIdFile(job);
ASSERT_EQ(root_dir_->AddEntry(std::to_string(job), std::move(job_dir)), ZX_OK);
}
fidl::ClientEnd<fuchsia_io::Directory> RuntimeDirHelper::GetScopedDirectoryHandle(zx_koid_t job) {
FX_CHECK(root_dir_client_.is_valid());
FX_CHECK(!root_dir_);
auto [client_end, server_end] = *fidl::CreateEndpoints<fuchsia_io::Directory>();
FX_CHECK(root_dir_client_->Open(MakeDirOpenRequest(std::to_string(job), std::move(server_end)))
.is_ok());
return std::move(client_end);
}
} // namespace testing