blob: dd8fbbf00adc69691798025cb9d4d3a86a638c79 [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 "garnet/lib/debugger_utils/jobs.h"
#include "garnet/lib/debugger_utils/sysinfo.h"
#include "gtest/gtest.h"
namespace debugserver {
namespace util {
namespace {
zx_koid_t GetKoid(zx_handle_t task) {
zx_info_handle_basic_t info;
auto status = zx_object_get_info(task, ZX_INFO_HANDLE_BASIC, &info,
sizeof(info), nullptr, nullptr);
EXPECT_EQ(status, ZX_OK);
if (status != ZX_OK) {
return ZX_KOID_INVALID;
}
return info.koid;
}
zx_koid_t GetParentKoid(zx_handle_t task) {
zx_info_handle_basic_t info;
auto status = zx_object_get_info(task, ZX_INFO_HANDLE_BASIC, &info,
sizeof(info), nullptr, nullptr);
EXPECT_EQ(status, ZX_OK);
if (status != ZX_OK) {
return ZX_KOID_INVALID;
}
return info.related_koid;
}
TEST(JobsTest, ThisJobAndStop) {
auto job = GetDefaultJob();
auto jid = GetKoid(job.get());
JobTreeJobCallback job_callback = [&](zx::job& job, zx_koid_t koid,
zx_koid_t parent_koid,
int depth) -> zx_status_t {
if (koid == jid) {
return ZX_ERR_STOP;
}
return ZX_OK;
};
EXPECT_EQ(WalkJobTree(job, &job_callback, nullptr, nullptr), ZX_ERR_STOP);
}
TEST(JobsTest, ThisProcessAndStop) {
auto job = GetDefaultJob();
auto pid = GetKoid(zx_process_self());
JobTreeProcessCallback process_callback =
[&](zx::process& process, zx_koid_t koid, zx_koid_t parent_koid,
int depth) -> zx_status_t {
if (koid == pid) {
return ZX_ERR_STOP;
}
return ZX_OK;
};
EXPECT_EQ(WalkJobTree(job, nullptr, &process_callback, nullptr), ZX_ERR_STOP);
}
TEST(JobsTest, ThisThreadAndStop) {
auto job = GetDefaultJob();
auto tid = GetKoid(zx_thread_self());
JobTreeThreadCallback thread_callback =
[&](zx::thread& thread, zx_koid_t koid, zx_koid_t parent_koid,
int depth) -> zx_status_t {
if (koid == tid) {
return ZX_ERR_STOP;
}
return ZX_OK;
};
EXPECT_EQ(WalkJobTree(job, nullptr, nullptr, &thread_callback), ZX_ERR_STOP);
}
static zx_status_t GetHandleInfo(zx_handle_t handle,
zx_info_handle_basic_t* info) {
return zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, info,
sizeof(*info), nullptr, nullptr);
}
static void TestKoids(zx_handle_t task, zx_koid_t koid, zx_koid_t parent_koid) {
zx_info_handle_basic_t info;
ASSERT_EQ(GetHandleInfo(task, &info), ZX_OK);
EXPECT_EQ(koid, info.koid);
EXPECT_EQ(parent_koid, info.related_koid);
}
static void TestJobProcessThread(zx::job& search_job) {
auto tid = GetKoid(zx_thread_self());
auto pid = GetKoid(zx_process_self());
auto jid = GetParentKoid(zx_process_self());
int job_depth = -1;
int process_depth = -1;
int thread_depth = -1;
JobTreeJobCallback job_callback = [&](zx::job& task, zx_koid_t koid,
zx_koid_t parent_koid,
int depth) -> zx_status_t {
TestKoids(task.get(), koid, parent_koid);
EXPECT_GE(depth, 0);
if (koid == jid) {
job_depth = depth;
}
return ZX_OK;
};
JobTreeProcessCallback process_callback =
[&](zx::process& task, zx_koid_t koid, zx_koid_t parent_koid,
int depth) -> zx_status_t {
TestKoids(task.get(), koid, parent_koid);
EXPECT_GT(depth, 0);
if (koid == pid) {
process_depth = depth;
}
return ZX_OK;
};
JobTreeThreadCallback thread_callback = [&](zx::thread& task, zx_koid_t koid,
zx_koid_t parent_koid,
int depth) -> zx_status_t {
TestKoids(task.get(), koid, parent_koid);
EXPECT_GT(depth, 1);
if (koid == tid) {
thread_depth = depth;
}
return ZX_OK;
};
EXPECT_EQ(WalkJobTree(search_job, &job_callback, &process_callback,
&thread_callback),
ZX_OK);
EXPECT_EQ(job_depth + 1, process_depth);
EXPECT_EQ(process_depth + 1, thread_depth);
}
TEST(JobsTest, JobProcessThread) {
auto job = GetDefaultJob();
TestJobProcessThread(job);
}
TEST(JobsTest, RootJob) {
// Make sure we can find ourselves from the root job.
// This will likely evolve or be replaced, but it's useful to test
// current functionality.
auto job = GetRootJob();
TestJobProcessThread(job);
}
TEST(JobsTest, FindProcess) {
auto job = GetDefaultJob();
auto pid = GetKoid(zx_process_self());
auto process = FindProcess(job.get(), pid);
zx_info_handle_basic_t info;
ASSERT_EQ(GetHandleInfo(process.get(), &info), ZX_OK);
EXPECT_EQ(info.koid, pid);
}
} // namespace
} // namespace util
} // namespace debugserver