| // Copyright 2022 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/zxdump/task.h> |
| |
| #include <gtest/gtest.h> |
| |
| #include "dump-tests.h" |
| #include "rights.h" |
| |
| namespace { |
| |
| TEST(ZxdumpTests, TaskBasic) { |
| zxdump::testing::TestProcess process; |
| constexpr const char* kChildName = "task-basic-test"; |
| |
| ASSERT_NO_FATAL_FAILURE(process.SpawnAction({ |
| .action = FDIO_SPAWN_ACTION_SET_NAME, |
| .name = {kChildName}, |
| })); |
| ASSERT_NO_FATAL_FAILURE(process.StartChild()); |
| |
| zxdump::TaskHolder holder; |
| auto insert_result = holder.Insert(process.handle()); |
| ASSERT_TRUE(insert_result.is_ok()) << insert_result.error_value(); |
| |
| // The dump has no jobs, so there should be a placeholder "super-root". |
| EXPECT_EQ(ZX_KOID_INVALID, holder.root_job().koid()); |
| |
| auto processes = holder.root_job().processes(); |
| ASSERT_TRUE(processes.is_ok()) << processes.error_value(); |
| |
| // The fake job should have exactly one process. |
| EXPECT_EQ(processes->get().size(), 1u); |
| for (auto& [read_koid, read_process] : processes->get()) { |
| EXPECT_NE(read_koid, ZX_KOID_INVALID); |
| |
| // Get the basic info from the real live process handle. |
| zx_info_handle_basic_t basic; |
| ASSERT_EQ(ZX_OK, process.borrow()->get_info(ZX_INFO_HANDLE_BASIC, &basic, sizeof(basic), |
| nullptr, nullptr)); |
| EXPECT_EQ(read_koid, basic.koid); |
| EXPECT_EQ(ZX_OBJ_TYPE_PROCESS, basic.type); |
| |
| auto read_basic = read_process.get_info<ZX_INFO_HANDLE_BASIC>(); |
| ASSERT_TRUE(read_basic.is_ok()) << read_basic.error_value(); |
| EXPECT_EQ(basic.koid, read_basic->koid); |
| EXPECT_EQ(basic.rights, read_basic->rights); |
| EXPECT_EQ(basic.type, read_basic->type); |
| EXPECT_EQ(basic.related_koid, read_basic->related_koid); |
| |
| auto read_name = read_process.get_property<ZX_PROP_NAME>(); |
| ASSERT_TRUE(read_name.is_ok()) << read_name.error_value(); |
| EXPECT_STREQ(kChildName, read_name->data()); |
| |
| auto threads = read_process.threads(); |
| ASSERT_TRUE(threads.is_ok()) << threads.error_value(); |
| |
| // The test process has only one thread. |
| EXPECT_EQ(threads->get().size(), 1u); |
| for (auto& [thread_koid, thread] : threads->get()) { |
| zx::handle child_handle; |
| ASSERT_EQ(ZX_OK, |
| process.borrow()->get_child(thread_koid, zxdump::kThreadRights, &child_handle)); |
| ASSERT_EQ(ZX_OK, child_handle.get_info(ZX_INFO_HANDLE_BASIC, &basic, sizeof(basic), nullptr, |
| nullptr)); |
| read_basic = thread.get_info<ZX_INFO_HANDLE_BASIC>(); |
| ASSERT_TRUE(read_basic.is_ok()) << read_basic.error_value(); |
| EXPECT_EQ(basic.koid, read_basic->koid); |
| EXPECT_EQ(basic.type, read_basic->type); |
| EXPECT_EQ(basic.related_koid, read_basic->related_koid); |
| } |
| } |
| } |
| |
| TEST(ZxdumpTests, ReadMemoryFromLiveProcess) { |
| zxdump::testing::TestProcessForMemory process; |
| ASSERT_NO_FATAL_FAILURE(process.StartChild()); |
| |
| zxdump::TaskHolder holder; |
| auto insert_result = holder.Insert(process.handle()); |
| ASSERT_TRUE(insert_result.is_ok()) << insert_result.error_value(); |
| |
| ASSERT_NO_FATAL_FAILURE(process.CheckDump(holder)); |
| } |
| |
| TEST(ZxdumpTests, TaskProcessThreads) { |
| zxdump::testing::TestProcessForThreads process; |
| ASSERT_NO_FATAL_FAILURE(process.StartChild()); |
| |
| zxdump::TaskHolder holder; |
| auto insert_result = holder.Insert(process.handle()); |
| ASSERT_TRUE(insert_result.is_ok()) << insert_result.error_value(); |
| |
| ASSERT_NO_FATAL_FAILURE(process.CheckDump(holder)); |
| } |
| |
| } // namespace |