Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

463 lines
14 KiB
C++

//===-- ProtocolRequestsTest.cpp ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Protocol/ProtocolRequests.h"
#include "Protocol/ProtocolTypes.h"
#include "TestingSupport/TestUtilities.h"
#include "llvm/Testing/Support/Error.h"
#include <gtest/gtest.h>
#include <optional>
using namespace llvm;
using namespace lldb_dap::protocol;
using namespace lldb_dap;
using lldb_private::PrettyPrint;
using llvm::json::parse;
TEST(ProtocolRequestsTest, ExceptionInfoArguments) {
llvm::Expected<ExceptionInfoArguments> expected =
parse<ExceptionInfoArguments>(R"({
"threadId": 3434
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->threadId, 3434U);
// Check required keys;
EXPECT_THAT_EXPECTED(parse<ExceptionInfoArguments>(R"({})"),
FailedWithMessage("missing value at (root).threadId"));
EXPECT_THAT_EXPECTED(parse<ExceptionInfoArguments>(R"({"id": 10})"),
FailedWithMessage("missing value at (root).threadId"));
}
TEST(ProtocolRequestsTest, ExceptionInfoResponseBody) {
ExceptionInfoResponseBody body;
body.exceptionId = "signal";
body.breakMode = eExceptionBreakModeAlways;
// Check required keys.
Expected<json::Value> expected = parse(
R"({
"exceptionId": "signal",
"breakMode": "always"
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body));
// Check optional keys.
body.description = "SIGNAL SIGWINCH";
body.breakMode = eExceptionBreakModeNever;
body.details = ExceptionDetails{};
body.details->message = "some message";
Expected<json::Value> expected_opt = parse(
R"({
"exceptionId": "signal",
"description": "SIGNAL SIGWINCH",
"breakMode": "never",
"details": {
"message": "some message"
}
})");
ASSERT_THAT_EXPECTED(expected_opt, llvm::Succeeded());
EXPECT_EQ(PrettyPrint(*expected_opt), PrettyPrint(body));
}
TEST(ProtocolRequestsTest, EvaluateArguments) {
llvm::Expected<EvaluateArguments> expected = parse<EvaluateArguments>(R"({
"expression": "hello world",
"context": "repl"
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->expression, "hello world");
EXPECT_EQ(expected->context, eEvaluateContextRepl);
// Check required keys.
EXPECT_THAT_EXPECTED(parse<EvaluateArguments>(R"({})"),
FailedWithMessage("missing value at (root).expression"));
}
TEST(ProtocolRequestsTest, EvaluateResponseBody) {
EvaluateResponseBody body;
body.result = "hello world";
body.variablesReference = var_ref_t(7);
// Check required keys.
Expected<json::Value> expected = parse(R"({
"result": "hello world",
"variablesReference": 7
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body));
// Check optional keys.
body.result = "'abc'";
body.type = "string";
body.variablesReference = var_ref_t(42);
body.namedVariables = 1;
body.indexedVariables = 2;
body.memoryReference = "0x123";
body.valueLocationReference = 22;
Expected<json::Value> expected_opt = parse(R"({
"result": "'abc'",
"type": "string",
"variablesReference": 42,
"namedVariables": 1,
"indexedVariables": 2,
"memoryReference": "0x123",
"valueLocationReference": 22
})");
ASSERT_THAT_EXPECTED(expected_opt, llvm::Succeeded());
EXPECT_EQ(PrettyPrint(*expected_opt), PrettyPrint(body));
}
TEST(ProtocolRequestsTest, InitializeRequestArguments) {
llvm::Expected<InitializeRequestArguments> expected =
parse<InitializeRequestArguments>(R"({"adapterID": "myid"})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->adapterID, "myid");
// Check optional keys.
expected = parse<InitializeRequestArguments>(R"({
"adapterID": "myid",
"clientID": "myclientid",
"clientName": "lldb-dap-unit-tests",
"locale": "en-US",
"linesStartAt1": true,
"columnsStartAt1": true,
"pathFormat": "uri",
"supportsVariableType": true,
"supportsVariablePaging": true,
"supportsRunInTerminalRequest": true,
"supportsMemoryReferences": true,
"supportsProgressReporting": true,
"supportsInvalidatedEvent": true,
"supportsMemoryEvent": true,
"supportsArgsCanBeInterpretedByShell": true,
"supportsStartDebuggingRequest": true,
"supportsANSIStyling": true
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->adapterID, "myid");
EXPECT_EQ(expected->clientID, "myclientid");
EXPECT_EQ(expected->clientName, "lldb-dap-unit-tests");
EXPECT_EQ(expected->locale, "en-US");
EXPECT_EQ(expected->linesStartAt1, true);
EXPECT_EQ(expected->columnsStartAt1, true);
EXPECT_EQ(expected->pathFormat, ePathFormatURI);
EXPECT_EQ(expected->supportedFeatures.contains(eClientFeatureVariableType),
true);
EXPECT_EQ(
expected->supportedFeatures.contains(eClientFeatureRunInTerminalRequest),
true);
EXPECT_EQ(
expected->supportedFeatures.contains(eClientFeatureMemoryReferences),
true);
EXPECT_EQ(
expected->supportedFeatures.contains(eClientFeatureProgressReporting),
true);
EXPECT_EQ(
expected->supportedFeatures.contains(eClientFeatureInvalidatedEvent),
true);
EXPECT_EQ(expected->supportedFeatures.contains(eClientFeatureMemoryEvent),
true);
EXPECT_EQ(expected->supportedFeatures.contains(
eClientFeatureArgsCanBeInterpretedByShell),
true);
EXPECT_EQ(
expected->supportedFeatures.contains(eClientFeatureStartDebuggingRequest),
true);
EXPECT_EQ(expected->supportedFeatures.contains(eClientFeatureANSIStyling),
true);
// Check required keys.
EXPECT_THAT_EXPECTED(parse<InitializeRequestArguments>(R"({})"),
FailedWithMessage("missing value at (root).adapterID"));
}
TEST(ProtocolRequestsTest, PauseRequestArguments) {
llvm::Expected<PauseArguments> expected =
parse<PauseArguments>(R"({"threadId": 123})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->threadId, 123U);
// Check required keys.
EXPECT_THAT_EXPECTED(parse<PauseArguments>(R"({})"),
FailedWithMessage("missing value at (root).threadId"));
}
TEST(ProtocolRequestsTest, LocationsArguments) {
llvm::Expected<LocationsArguments> expected =
parse<LocationsArguments>(R"({"locationReference": 123})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->locationReference, 123U);
// Check required keys.
EXPECT_THAT_EXPECTED(
parse<LocationsArguments>(R"({})"),
FailedWithMessage("missing value at (root).locationReference"));
}
TEST(ProtocolRequestsTest, LocationsResponseBody) {
LocationsResponseBody body;
body.source.sourceReference = 123;
body.source.name = "test.cpp";
body.line = 42;
// Check required keys.
Expected<json::Value> expected = parse(R"({
"source": {
"sourceReference": 123,
"name": "test.cpp"
},
"line": 42
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body));
// Check optional keys.
body.column = 2;
body.endLine = 43;
body.endColumn = 4;
expected = parse(R"({
"source": {
"sourceReference": 123,
"name": "test.cpp"
},
"line": 42,
"column": 2,
"endLine": 43,
"endColumn": 4
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body));
}
TEST(ProtocolRequestsTest, CompileUnitsArguments) {
llvm::Expected<CompileUnitsArguments> expected =
parse<CompileUnitsArguments>(R"({"moduleId": "42"})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->moduleId, "42");
// Check required keys.
EXPECT_THAT_EXPECTED(parse<CompileUnitsArguments>(R"({})"),
FailedWithMessage("missing value at (root).moduleId"));
}
TEST(ProtocolRequestsTest, CompileUnitsResponseBody) {
CompileUnitsResponseBody body;
body.compileUnits = {{"main.cpp"}, {"util.cpp"}};
// Check required keys.
Expected<json::Value> expected = parse(R"({
"compileUnits": [
{
"compileUnitPath": "main.cpp"
},
{
"compileUnitPath": "util.cpp"
}
]
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body));
}
TEST(ProtocolRequestsTest, TestGetTargetBreakpointsResponseBody) {
Breakpoint breakpoint1;
breakpoint1.id = 1;
breakpoint1.verified = true;
Breakpoint breakpoint2;
breakpoint2.id = 2;
breakpoint2.verified = false;
breakpoint2.message = "Failed to set breakpoint";
TestGetTargetBreakpointsResponseBody body;
body.breakpoints = {breakpoint1, breakpoint2};
// Check required keys.
Expected<json::Value> expected = parse(R"({
"breakpoints": [
{
"id": 1,
"verified": true
},
{
"id": 2,
"verified": false,
"message": "Failed to set breakpoint"
}
]
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body));
}
TEST(ProtocolRequestsTest, RestartArguments) {
llvm::Expected<RestartArguments> expected = parse<RestartArguments>(R"({})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_TRUE(std::holds_alternative<std::monostate>(expected->arguments));
// Check missed keys.
expected = parse<RestartArguments>(R"({
"arguments": {}
})");
EXPECT_THAT_EXPECTED(expected,
FailedWithMessage("failed to parse arguments, expected "
"`launch` or `attach` arguments"));
// Check launch arguments.
expected = parse<RestartArguments>(R"({
"arguments": {
"program": "main.exe",
"cwd": "/home/root"
}
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
const LaunchRequestArguments *launch_args =
std::get_if<LaunchRequestArguments>(&expected->arguments);
EXPECT_NE(launch_args, nullptr);
EXPECT_EQ(launch_args->configuration.program, "main.exe");
EXPECT_EQ(launch_args->cwd, "/home/root");
// Check attach arguments.
expected = parse<RestartArguments>(R"({
"arguments": {
"pid": 123
}
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
const AttachRequestArguments *attach_args =
std::get_if<AttachRequestArguments>(&expected->arguments);
EXPECT_NE(attach_args, nullptr);
EXPECT_EQ(attach_args->pid, 123U);
}
TEST(ProtocolRequestsTest, StackTraceArguments) {
llvm::Expected<StackTraceArguments> expected = parse<StackTraceArguments>(R"({
"threadId": 42,
"startFrame": 1,
"levels": 10,
"format": {
"parameters": true,
"line": true
}
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->threadId, 42U);
EXPECT_EQ(expected->startFrame, 1U);
EXPECT_EQ(expected->levels, 10U);
EXPECT_EQ(expected->format->parameters, true);
EXPECT_EQ(expected->format->line, true);
// Check required keys.
EXPECT_THAT_EXPECTED(parse<StackTraceArguments>(R"({})"),
FailedWithMessage("missing value at (root).threadId"));
}
TEST(ProtocolRequestsTest, StackTraceResponseBody) {
StackFrame frame1;
frame1.id = 1;
frame1.name = "main";
frame1.source = Source{};
frame1.source->name = "main.cpp";
frame1.source->sourceReference = 123;
frame1.line = 23;
frame1.column = 1;
StackFrame frame2;
frame2.id = 2;
frame2.name = "test";
frame2.presentationHint = StackFrame::ePresentationHintLabel;
StackTraceResponseBody body;
body.stackFrames = {frame1, frame2};
body.totalFrames = 2;
// Check required keys.
Expected<json::Value> expected = parse(R"({
"stackFrames": [
{
"id": 1,
"name": "main",
"source": {
"name": "main.cpp",
"sourceReference": 123
},
"line": 23,
"column": 1
},
{
"id": 2,
"name": "test",
"line": 0,
"column": 0,
"presentationHint": "label"
}
],
"totalFrames": 2
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body));
}
TEST(ProtocolRequestsTest, SetVariableArguments) {
llvm::Expected<SetVariableArguments> expected =
parse<SetVariableArguments>(R"({
"variablesReference": 42,
"name": "test",
"value": "12345"
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->variablesReference.AsUInt32(), 42U);
EXPECT_EQ(expected->name, "test");
EXPECT_EQ(expected->value, "12345");
EXPECT_EQ(expected->format, std::nullopt);
// Check required keys.
EXPECT_THAT_EXPECTED(
parse<SetVariableArguments>(R"({})"),
FailedWithMessage("missing value at (root).variablesReference"));
}
TEST(ProtocolRequestsTest, CancelRequestArguments) {
llvm::Expected<CancelArguments> expected = parse<CancelArguments>(R"({
"requestId": 42,
"progressId": "abc"
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->requestId, 42U);
EXPECT_EQ(expected->progressId, "abc");
expected = parse<CancelArguments>(R"({
"requestId": 42
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->requestId, 42U);
EXPECT_TRUE(expected->progressId.empty());
expected = parse<CancelArguments>(R"({
"progressId": "abc"
})");
ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());
EXPECT_EQ(expected->requestId, 0u);
EXPECT_EQ(expected->progressId, "abc");
// Check an empty message, all keys are optional.
EXPECT_THAT_EXPECTED(parse<CancelArguments>(R"({})"), Succeeded());
}