blob: 84cb922d2178f35b11bd1f37c78b1673ec24169a [file] [log] [blame]
// Copyright 2024 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/debugged_job.h"
#include <gtest/gtest.h>
#include "src/developer/debug/debug_agent/mock_debug_agent_harness.h"
#include "src/developer/debug/debug_agent/mock_process.h"
#include "src/developer/debug/debug_agent/mock_thread.h"
namespace debug_agent {
TEST(DebuggedJob, ReportUnhandledException) {
debug_agent::MockDebugAgentHarness harness;
DebuggedJob job(harness.debug_agent());
constexpr zx_koid_t kJobKoid = 1234;
auto mock_job_handle = std::make_unique<MockJobHandle>(kJobKoid);
constexpr zx_koid_t kProcess1Koid = 1235;
constexpr zx_koid_t kProcess1Thread1Koid = 1236;
constexpr zx_koid_t kProcess2Koid = 1237;
constexpr zx_koid_t kProcess2Thread1Koid = 1238;
constexpr zx_koid_t kProcess2Thread2Koid = 1239;
MockProcess* p1 = harness.AddProcess(kProcess1Koid);
auto p1_handle = p1->mock_process_handle();
auto p1_t1 = p1->AddThread(kProcess1Thread1Koid);
p1_handle.set_threads({p1_t1->mock_thread_handle()});
MockProcess* p2 = harness.AddProcess(kProcess2Koid);
auto p2_t1 = p2->AddThread(kProcess2Thread1Koid);
auto p2_t2 = p2->AddThread(kProcess2Thread2Koid);
auto p2_handle = p2->mock_process_handle();
p2_handle.set_threads({p2_t1->mock_thread_handle(), p2_t2->mock_thread_handle()});
mock_job_handle->set_child_processes({p1_handle, p2_handle});
MockJobHandle* job_handle = mock_job_handle.get();
DebuggedJobCreateInfo create_info(std::move(mock_job_handle));
// This tells the MockJobHandle that we are allowed to receive exception events, mimicking a real
// system.
create_info.type = JobExceptionChannelType::kException;
job.Init(std::move(create_info));
auto mock_exception = std::make_unique<MockExceptionHandle>(kProcess1Koid, kProcess1Thread1Koid);
job_handle->OnException(std::move(mock_exception), MockJobExceptionInfo::kException);
ASSERT_FALSE(harness.stream_backend()->exceptions().empty());
ASSERT_EQ(harness.stream_backend()->exceptions().size(), 1u);
// This exception should be marked that it came from the job and there's nothing to do other than
// display the exception and move on.
EXPECT_TRUE(harness.stream_backend()->exceptions()[0].job_only);
// Other fields in the exception notification should always be empty.
EXPECT_TRUE(harness.stream_backend()->exceptions()[0].hit_breakpoints.empty());
EXPECT_TRUE(harness.stream_backend()->exceptions()[0].other_affected_threads.empty());
// The exception should be released after the notification is sent.
EXPECT_EQ(mock_exception, nullptr);
}
} // namespace debug_agent