blob: 8220ae4a8b64e480d10210e6ddd221a043e4a33a [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 "src/developer/debug/zxdb/client/remote_api_test.h"
#include <inttypes.h>
#include "src/developer/debug/ipc/protocol.h"
#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/client/system_impl.h"
#include "src/developer/debug/zxdb/client/target_impl.h"
#include "src/developer/debug/zxdb/client/thread_impl.h"
#include "src/lib/fxl/strings/string_printf.h"
namespace zxdb {
RemoteAPITest::RemoteAPITest() { loop_.Init(); }
RemoteAPITest::~RemoteAPITest() { loop_.Cleanup(); }
void RemoteAPITest::SetUp() {
session_ = std::make_unique<Session>(GetRemoteAPIImpl(), GetArch());
session_->system().settings().SetBool(ClientSettings::System::kPauseOnAttach,
true);
session_->system().settings().SetBool(ClientSettings::System::kPauseOnLaunch,
true);
}
void RemoteAPITest::TearDown() { session_.reset(); }
Process* RemoteAPITest::InjectProcess(uint64_t process_koid) {
auto targets = session().system_impl().GetTargetImpls();
if (targets.size() != 1u) {
ADD_FAILURE();
return nullptr;
}
if (targets[0]->GetState() != Target::State::kNone) {
ADD_FAILURE();
return nullptr;
}
targets[0]->CreateProcessForTesting(process_koid, "test");
return targets[0]->GetProcess();
}
Thread* RemoteAPITest::InjectThread(uint64_t process_koid,
uint64_t thread_koid) {
debug_ipc::NotifyThread notify;
notify.record.process_koid = process_koid;
notify.record.thread_koid = thread_koid;
notify.record.name = fxl::StringPrintf("test %" PRIu64, thread_koid);
notify.record.state = debug_ipc::ThreadRecord::State::kRunning;
session_->DispatchNotifyThreadStarting(notify);
return session_->ThreadImplFromKoid(process_koid, thread_koid);
}
void RemoteAPITest::InjectException(
const debug_ipc::NotifyException& exception) {
session_->DispatchNotifyException(exception);
}
void RemoteAPITest::InjectExceptionWithStack(
const debug_ipc::NotifyException& exception,
std::vector<std::unique_ptr<Frame>> frames, bool has_all_frames) {
ThreadImpl* thread = session_->ThreadImplFromKoid(
exception.thread.process_koid, exception.thread.thread_koid);
FXL_CHECK(thread); // Tests should always pass valid KOIDs.
// Need to supply at least one stack frame.
FXL_CHECK(!frames.empty());
// Create an exception record with a thread frame so it's valid. There must
// be one frame even though the stack will be immediately overwritten.
debug_ipc::NotifyException modified(exception);
modified.thread.stack_amount = debug_ipc::ThreadRecord::StackAmount::kMinimal;
modified.thread.frames.clear();
modified.thread.frames.emplace_back(frames[0]->GetAddress(),
frames[0]->GetStackPointer());
// To manually set the thread state, set the general metadata which will pick
// up the basic flags and the first stack frame. Then re-set the stack frame
// with the information passed in by our caller.
thread->SetMetadata(modified.thread);
thread->GetStack().SetFramesForTest(std::move(frames), has_all_frames);
// Normal exception dispatch path, but skipping the metadata (so the metadata
// set above will stay).
session_->DispatchNotifyException(modified, false);
}
void RemoteAPITest::InjectExceptionWithStack(
uint64_t process_koid, uint64_t thread_koid,
debug_ipc::NotifyException::Type exception_type,
std::vector<std::unique_ptr<Frame>> frames, bool has_all_frames,
const std::vector<debug_ipc::BreakpointStats>& breakpoints) {
// Need to supply at least one stack frame to get the address from.
FXL_CHECK(!frames.empty());
debug_ipc::NotifyException exception;
exception.type = exception_type;
exception.thread.process_koid = process_koid;
exception.thread.thread_koid = thread_koid;
exception.thread.state = debug_ipc::ThreadRecord::State::kBlocked;
exception.hit_breakpoints = breakpoints;
InjectExceptionWithStack(exception, std::move(frames), has_all_frames);
}
} // namespace zxdb