blob: cd6bfff32a265265c15784f0e6a4a99f90b9d7d7 [file] [log] [blame]
// Copyright 2021 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 <gtest/gtest.h>
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/debug_adapter/context_test.h"
namespace zxdb {
namespace {
// Create our own fake RemoteAPI to observe and verify thread resumes.
class FakeRemoteAPI : public RemoteAPI {
public:
std::vector<debug_ipc::ResumeRequest>& resume_requests() { return resume_requests_; }
void Resume(const debug_ipc::ResumeRequest& request,
fit::callback<void(const Err&, debug_ipc::ResumeReply)> cb) override {
resume_requests_.push_back(request);
RemoteAPI::Resume(request, std::move(cb));
}
private:
std::vector<debug_ipc::ResumeRequest> resume_requests_;
};
class RequestContinueTest : public DebugAdapterContextTest {
public:
FakeRemoteAPI* remote_api() { return remote_api_; }
protected:
std::unique_ptr<RemoteAPI> GetRemoteAPIImpl() override {
auto remote_api = std::make_unique<FakeRemoteAPI>();
remote_api_ = remote_api.get();
return remote_api;
}
private:
FakeRemoteAPI* remote_api_;
};
} // namespace
TEST_F(RequestContinueTest, ContinueSystem) {
InitializeDebugging();
InjectProcess(kProcessKoid);
InjectProcess(kProcessKoid + 1);
// Run client to receive process started events.
RunClient();
RunClient();
InjectThread(kProcessKoid, kThreadKoid);
InjectThread(kProcessKoid, kThreadKoid + 1);
InjectThread(kProcessKoid + 1, kThreadKoid + 2);
// Run client to receive thread started events.
RunClient();
RunClient();
RunClient();
// Send continue request from the client.
dap::ContinueRequest request = {};
request.threadId = kThreadKoid;
auto response = client().send(request);
// Read request and process it in server.
context().OnStreamReadable();
// Verify both threads are resumed.
auto resume_requests = remote_api()->resume_requests();
EXPECT_EQ(3u, resume_requests.size());
EXPECT_EQ(debug_ipc::ResumeRequest::How::kResolveAndContinue, resume_requests[0].how);
EXPECT_EQ(1u, resume_requests[0].ids.size());
EXPECT_EQ(kProcessKoid, resume_requests[0].ids[0].process);
EXPECT_EQ(kThreadKoid, resume_requests[0].ids[0].thread);
EXPECT_EQ(debug_ipc::ResumeRequest::How::kResolveAndContinue, resume_requests[1].how);
EXPECT_EQ(1u, resume_requests[1].ids.size());
EXPECT_EQ(kProcessKoid, resume_requests[1].ids[0].process);
EXPECT_EQ(kThreadKoid + 1, resume_requests[1].ids[0].thread);
EXPECT_EQ(debug_ipc::ResumeRequest::How::kResolveAndContinue, resume_requests[2].how);
EXPECT_EQ(1u, resume_requests[2].ids.size());
EXPECT_EQ(kProcessKoid + 1, resume_requests[2].ids[0].process);
EXPECT_EQ(kThreadKoid + 2, resume_requests[2].ids[0].thread);
// Run client to receive continue response.
RunClient();
auto got = response.get();
EXPECT_FALSE(got.error);
EXPECT_TRUE(got.response.allThreadsContinued.value(true));
}
TEST_F(RequestContinueTest, ContinueSingleThread) {
InitializeDebugging();
InjectProcess(kProcessKoid);
InjectProcess(kProcessKoid + 1);
// Run client to receive process started events.
RunClient();
RunClient();
InjectThread(kProcessKoid, kThreadKoid);
InjectThread(kProcessKoid, kThreadKoid + 1);
InjectThread(kProcessKoid + 1, kThreadKoid + 2);
// Run client to receive thread started events.
RunClient();
RunClient();
RunClient();
// Send continue request from the client.
dap::ContinueRequest request = {};
request.threadId = kThreadKoid;
request.singleThread = true;
auto response = client().send(request);
// Read request and process it in server.
context().OnStreamReadable();
// Verify the single thread is resumed.
auto resume_requests = remote_api()->resume_requests();
EXPECT_EQ(1u, resume_requests.size());
EXPECT_EQ(debug_ipc::ResumeRequest::How::kResolveAndContinue, resume_requests[0].how);
EXPECT_EQ(1u, resume_requests[0].ids.size());
EXPECT_EQ(kProcessKoid, resume_requests[0].ids[0].process);
EXPECT_EQ(kThreadKoid, resume_requests[0].ids[0].thread);
// Run client to receive continue response.
RunClient();
auto got = response.get();
EXPECT_FALSE(got.error);
EXPECT_FALSE(got.response.allThreadsContinued.value(true));
}
} // namespace zxdb