blob: 9763e524a7c36f4c969bf793cf1c051b7b62b139 [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 "src/developer/debug/debug_agent/mock_object_provider.h"
#include "src/developer/debug/shared/logging/logging.h"
#include "src/lib/fxl/logging.h"
namespace debug_agent {
namespace {
template <typename T>
MockObject* SearchForKoid(const std::vector<std::unique_ptr<T>>& objects, zx_koid_t koid) {
for (auto& object : objects) {
if (object->koid == koid)
return object.get();
}
return nullptr;
}
} // namespace
std::vector<zx::job> MockObjectProvider::GetChildJobs(zx_handle_t job_handle) const {
zx_koid_t job_koid = static_cast<zx_koid_t>(job_handle);
auto it = object_map_.find(job_koid);
FXL_DCHECK(it != object_map_.end());
MockJobObject* job = reinterpret_cast<MockJobObject*>(it->second);
FXL_DCHECK(job) << "On koid: " << job_koid;
FXL_DCHECK(job->type == MockObject::Type::kJob);
std::vector<zx::job> child_jobs;
for (auto& child_job : job->child_jobs) {
child_jobs.push_back(zx::job(static_cast<zx_handle_t>(child_job->koid)));
}
return child_jobs;
}
std::vector<zx::process> MockObjectProvider::GetChildProcesses(zx_handle_t job_handle) const {
zx_koid_t job_koid = static_cast<zx_koid_t>(job_handle);
auto it = object_map_.find(job_koid);
FXL_DCHECK(it != object_map_.end());
MockJobObject* job = reinterpret_cast<MockJobObject*>(it->second);
FXL_DCHECK(job) << "On koid: " << job_koid;
FXL_DCHECK(job->type == MockObject::Type::kJob);
std::vector<zx::process> child_processes;
for (auto& child_process : job->child_processes) {
child_processes.push_back(zx::process(static_cast<zx_handle_t>(child_process->koid)));
}
return child_processes;
}
std::vector<zx_koid_t> MockObjectProvider::GetChildKoids(zx_handle_t parent,
uint32_t child_kind) const {
MockObject* object = ObjectByKoid(parent);
if (!object)
return {};
std::vector<zx_koid_t> koids;
if (child_kind == ZX_INFO_PROCESS_THREADS) {
MockProcessObject* process = object->AsProcess();
FXL_DCHECK(process);
koids.reserve(process->child_threads.size());
for (auto& thread : process->child_threads) {
koids.push_back(thread->koid);
}
}
// Write the other cases as needed by tests.
return koids;
}
zx_status_t MockObjectProvider::GetChild(zx_handle_t parent, zx_koid_t koid, uint32_t rights,
zx_handle_t* child) const {
MockObject* object = ObjectByKoid(parent);
FXL_DCHECK(object);
// Add as needed by tests.
MockObject* child_object = nullptr;
if (object->type == MockObject::Type::kProcess) {
MockProcessObject* process = object->AsProcess();
FXL_DCHECK(process);
child_object = SearchForKoid(process->child_threads, koid);
}
if (!child_object)
return ZX_ERR_NOT_FOUND;
*child = child_object->koid;
return ZX_OK;
}
std::string MockObjectProvider::NameForObject(zx_handle_t object_handle) const {
zx_koid_t koid = static_cast<zx_koid_t>(object_handle);
DEBUG_LOG(Test) << "Getting name for: " << object_handle;
auto it = object_map_.find(koid);
FXL_DCHECK(it != object_map_.end());
DEBUG_LOG(Test) << "Getting name for " << object_handle << ", got " << it->second->name;
return it->second->name;
}
zx_koid_t MockObjectProvider::KoidForObject(zx_handle_t object_handle) const {
zx_koid_t koid = static_cast<zx_koid_t>(object_handle);
auto it = object_map_.find(koid);
FXL_DCHECK(it != object_map_.end());
DEBUG_LOG(Test) << "Getting koid for " << object_handle << ", got " << it->second->koid;
return it->second->koid;
};
zx::job MockObjectProvider::GetRootJob() const { return zx::job(GetRootJobKoid()); }
zx_koid_t MockObjectProvider::GetRootJobKoid() const { return root()->koid; }
// Test Setup Implementation.
std::unique_ptr<MockObjectProvider> CreateDefaultMockObjectProvider() {
auto provider = std::make_unique<MockObjectProvider>();
MockJobObject* root = provider->AppendJob(nullptr, "root");
provider->AppendProcess(root, "root-p1");
provider->AppendProcess(root, "root-p2");
provider->AppendProcess(root, "root-p3");
MockJobObject* job1 = provider->AppendJob(root, "job1");
provider->AppendProcess(job1, "job1-p1");
provider->AppendProcess(job1, "job1-p2");
MockJobObject* job11 = provider->AppendJob(job1, "job11");
MockProcessObject* process = provider->AppendProcess(job11, "job11-p1");
provider->AppendThread(process, "second-thread");
MockJobObject* job12 = provider->AppendJob(job1, "job12");
MockJobObject* job121 = provider->AppendJob(job12, "job121");
provider->AppendProcess(job121, "job121-p1");
process = provider->AppendProcess(job121, "job121-p2");
provider->AppendThread(process, "second-thread");
provider->AppendThread(process, "third-thread");
return provider;
}
MockJobObject* MockObjectProvider::AppendJob(MockJobObject* job, std::string name) {
if (job == nullptr) {
root_ = CreateJob(name);
return root_.get();
}
job->child_jobs.push_back(CreateJob(std::move(name)));
return job->child_jobs.back().get();
}
MockProcessObject* MockObjectProvider::AppendProcess(MockJobObject* job, std::string name) {
job->child_processes.push_back(CreateProcess(std::move(name)));
// Create the initial thread.
MockProcessObject* process = job->child_processes.back().get();
process->child_threads.push_back(CreateThread());
return process;
}
MockThreadObject* MockObjectProvider::AppendThread(MockProcessObject* process, std::string name) {
process->child_threads.push_back(CreateThread(std::move(name)));
return process->child_threads.back().get();
}
std::unique_ptr<MockJobObject> MockObjectProvider::CreateJob(std::string name) {
int koid = next_koid_++;
auto job = std::make_unique<MockJobObject>();
job->koid = koid;
job->name = std::move(name);
job->type = MockObject::Type::kJob;
object_map_[job->koid] = job.get();
job_map_[job->name] = job.get();
return job;
}
std::unique_ptr<MockProcessObject> MockObjectProvider::CreateProcess(std::string name) {
int koid = next_koid_++;
auto process = std::make_unique<MockProcessObject>();
process->koid = koid;
process->name = std::move(name);
process->type = MockObject::Type::kProcess;
object_map_[process->koid] = process.get();
process_map_[process->name] = process.get();
return process;
}
std::unique_ptr<MockThreadObject> MockObjectProvider::CreateThread(std::string name) {
int koid = next_koid_++;
auto thread = std::make_unique<MockThreadObject>();
thread->koid = koid;
thread->name = std::move(name);
thread->type = MockObject::Type::kThread;
object_map_[thread->koid] = thread.get();
return thread;
}
MockObject* MockObjectProvider::ObjectByKoid(zx_koid_t koid) const {
auto it = object_map_.find(koid);
if (it == object_map_.end())
return nullptr;
return it->second;
}
const MockJobObject* MockObjectProvider::JobByName(const std::string& name) const {
auto it = job_map_.find(name);
if (it == job_map_.end())
return nullptr;
return it->second;
}
const MockProcessObject* MockObjectProvider::ProcessByName(const std::string& name) const {
auto it = process_map_.find(name);
if (it == process_map_.end())
return nullptr;
return it->second;
}
const MockThreadObject* MockProcessObject::GetThread(const std::string& thread_name) const {
for (auto& thread : child_threads) {
if (thread->name == thread_name)
return thread.get();
}
return nullptr;
}
} // namespace debug_agent