1179 lines · cpp
1//===-- ProtocolTypesTest.cpp -----------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Protocol/ProtocolTypes.h"10#include "Protocol/ProtocolEvents.h"11#include "Protocol/ProtocolRequests.h"12#include "TestingSupport/TestUtilities.h"13#include "llvm/ADT/StringRef.h"14#include "llvm/Support/JSON.h"15#include "llvm/Testing/Support/Error.h"16#include "gmock/gmock.h"17#include "gtest/gtest.h"18#include <optional>19 20using namespace llvm;21using namespace lldb;22using namespace lldb_dap;23using namespace lldb_dap::protocol;24using lldb_private::roundtripJSON;25using llvm::json::parse;26using llvm::json::Value;27 28/// Returns a pretty printed json string of a `llvm::json::Value`.29static std::string pp(const json::Value &E) {30 return formatv("{0:2}", E).str();31}32 33TEST(ProtocolTypesTest, ExceptionBreakpointsFilter) {34 ExceptionBreakpointsFilter filter;35 filter.filter = "testFilter";36 filter.label = "Test Filter";37 filter.description = "This is a test filter";38 filter.defaultState = true;39 filter.supportsCondition = true;40 filter.conditionDescription = "Condition for test filter";41 42 llvm::Expected<ExceptionBreakpointsFilter> deserialized_filter =43 roundtripJSON(filter);44 ASSERT_THAT_EXPECTED(deserialized_filter, llvm::Succeeded());45 46 EXPECT_EQ(filter.filter, deserialized_filter->filter);47 EXPECT_EQ(filter.label, deserialized_filter->label);48 EXPECT_EQ(filter.description, deserialized_filter->description);49 EXPECT_EQ(filter.defaultState, deserialized_filter->defaultState);50 EXPECT_EQ(filter.supportsCondition, deserialized_filter->supportsCondition);51 EXPECT_EQ(filter.conditionDescription,52 deserialized_filter->conditionDescription);53}54 55TEST(ProtocolTypesTest, Source) {56 Source source;57 source.name = "testName";58 source.path = "/path/to/source";59 source.sourceReference = 12345;60 source.presentationHint = Source::eSourcePresentationHintEmphasize;61 62 llvm::Expected<Source> deserialized_source = roundtripJSON(source);63 ASSERT_THAT_EXPECTED(deserialized_source, llvm::Succeeded());64 65 EXPECT_EQ(source.name, deserialized_source->name);66 EXPECT_EQ(source.path, deserialized_source->path);67 EXPECT_EQ(source.sourceReference, deserialized_source->sourceReference);68 EXPECT_EQ(source.presentationHint, deserialized_source->presentationHint);69}70 71TEST(ProtocolTypesTest, ColumnDescriptor) {72 ColumnDescriptor column;73 column.attributeName = "moduleName";74 column.label = "Module Name";75 column.format = "uppercase";76 column.type = eColumnTypeString;77 column.width = 20;78 79 llvm::Expected<ColumnDescriptor> deserialized_column = roundtripJSON(column);80 ASSERT_THAT_EXPECTED(deserialized_column, llvm::Succeeded());81 82 EXPECT_EQ(column.attributeName, deserialized_column->attributeName);83 EXPECT_EQ(column.label, deserialized_column->label);84 EXPECT_EQ(column.format, deserialized_column->format);85 EXPECT_EQ(column.type, deserialized_column->type);86 EXPECT_EQ(column.width, deserialized_column->width);87}88 89TEST(ProtocolTypesTest, BreakpointMode) {90 BreakpointMode mode;91 mode.mode = "testMode";92 mode.label = "Test Mode";93 mode.description = "This is a test mode";94 mode.appliesTo = {eBreakpointModeApplicabilitySource,95 eBreakpointModeApplicabilityException};96 97 llvm::Expected<BreakpointMode> deserialized_mode = roundtripJSON(mode);98 ASSERT_THAT_EXPECTED(deserialized_mode, llvm::Succeeded());99 100 EXPECT_EQ(mode.mode, deserialized_mode->mode);101 EXPECT_EQ(mode.label, deserialized_mode->label);102 EXPECT_EQ(mode.description, deserialized_mode->description);103 EXPECT_EQ(mode.appliesTo, deserialized_mode->appliesTo);104}105 106TEST(ProtocolTypesTest, Breakpoint) {107 Breakpoint breakpoint;108 breakpoint.id = 42;109 breakpoint.verified = true;110 breakpoint.message = "Breakpoint set successfully";111 breakpoint.source =112 Source{"test.cpp", "/path/to/test.cpp", 123,113 Source::eSourcePresentationHintNormal, std::nullopt};114 breakpoint.line = 10;115 breakpoint.column = 5;116 breakpoint.endLine = 15;117 breakpoint.endColumn = 10;118 breakpoint.instructionReference = "0x12345678";119 breakpoint.offset = 4;120 breakpoint.reason = BreakpointReason::eBreakpointReasonPending;121 122 llvm::Expected<Breakpoint> deserialized_breakpoint =123 roundtripJSON(breakpoint);124 ASSERT_THAT_EXPECTED(deserialized_breakpoint, llvm::Succeeded());125 126 EXPECT_EQ(breakpoint.id, deserialized_breakpoint->id);127 EXPECT_EQ(breakpoint.verified, deserialized_breakpoint->verified);128 EXPECT_EQ(breakpoint.message, deserialized_breakpoint->message);129 EXPECT_EQ(breakpoint.source->name, deserialized_breakpoint->source->name);130 EXPECT_EQ(breakpoint.source->path, deserialized_breakpoint->source->path);131 EXPECT_EQ(breakpoint.source->sourceReference,132 deserialized_breakpoint->source->sourceReference);133 EXPECT_EQ(breakpoint.source->presentationHint,134 deserialized_breakpoint->source->presentationHint);135 EXPECT_EQ(breakpoint.line, deserialized_breakpoint->line);136 EXPECT_EQ(breakpoint.column, deserialized_breakpoint->column);137 EXPECT_EQ(breakpoint.endLine, deserialized_breakpoint->endLine);138 EXPECT_EQ(breakpoint.endColumn, deserialized_breakpoint->endColumn);139 EXPECT_EQ(breakpoint.instructionReference,140 deserialized_breakpoint->instructionReference);141 EXPECT_EQ(breakpoint.offset, deserialized_breakpoint->offset);142 EXPECT_EQ(breakpoint.reason, deserialized_breakpoint->reason);143}144 145TEST(ProtocolTypesTest, SourceBreakpoint) {146 SourceBreakpoint source_breakpoint;147 source_breakpoint.line = 42;148 source_breakpoint.column = 5;149 source_breakpoint.condition = "x > 10";150 source_breakpoint.hitCondition = "5";151 source_breakpoint.logMessage = "Breakpoint hit at line 42";152 source_breakpoint.mode = "hardware";153 154 llvm::Expected<SourceBreakpoint> deserialized_source_breakpoint =155 roundtripJSON(source_breakpoint);156 ASSERT_THAT_EXPECTED(deserialized_source_breakpoint, llvm::Succeeded());157 158 EXPECT_EQ(source_breakpoint.line, deserialized_source_breakpoint->line);159 EXPECT_EQ(source_breakpoint.column, deserialized_source_breakpoint->column);160 EXPECT_EQ(source_breakpoint.condition,161 deserialized_source_breakpoint->condition);162 EXPECT_EQ(source_breakpoint.hitCondition,163 deserialized_source_breakpoint->hitCondition);164 EXPECT_EQ(source_breakpoint.logMessage,165 deserialized_source_breakpoint->logMessage);166 EXPECT_EQ(source_breakpoint.mode, deserialized_source_breakpoint->mode);167}168 169TEST(ProtocolTypesTest, FunctionBreakpoint) {170 FunctionBreakpoint function_breakpoint;171 function_breakpoint.name = "myFunction";172 function_breakpoint.condition = "x == 0";173 function_breakpoint.hitCondition = "3";174 175 llvm::Expected<FunctionBreakpoint> deserialized_function_breakpoint =176 roundtripJSON(function_breakpoint);177 ASSERT_THAT_EXPECTED(deserialized_function_breakpoint, llvm::Succeeded());178 179 EXPECT_EQ(function_breakpoint.name, deserialized_function_breakpoint->name);180 EXPECT_EQ(function_breakpoint.condition,181 deserialized_function_breakpoint->condition);182 EXPECT_EQ(function_breakpoint.hitCondition,183 deserialized_function_breakpoint->hitCondition);184}185 186TEST(ProtocolTypesTest, DataBreakpoint) {187 DataBreakpoint data_breakpoint_info;188 data_breakpoint_info.dataId = "variable1";189 data_breakpoint_info.accessType = eDataBreakpointAccessTypeReadWrite;190 data_breakpoint_info.condition = "x > 100";191 data_breakpoint_info.hitCondition = "10";192 193 llvm::Expected<DataBreakpoint> deserialized_data_breakpoint_info =194 roundtripJSON(data_breakpoint_info);195 ASSERT_THAT_EXPECTED(deserialized_data_breakpoint_info, llvm::Succeeded());196 197 EXPECT_EQ(data_breakpoint_info.dataId,198 deserialized_data_breakpoint_info->dataId);199 EXPECT_EQ(data_breakpoint_info.accessType,200 deserialized_data_breakpoint_info->accessType);201 EXPECT_EQ(data_breakpoint_info.condition,202 deserialized_data_breakpoint_info->condition);203 EXPECT_EQ(data_breakpoint_info.hitCondition,204 deserialized_data_breakpoint_info->hitCondition);205}206 207TEST(ProtocolTypesTest, Capabilities) {208 Capabilities capabilities;209 210 // Populate supported features.211 capabilities.supportedFeatures.insert(eAdapterFeatureANSIStyling);212 capabilities.supportedFeatures.insert(213 eAdapterFeatureBreakpointLocationsRequest);214 215 // Populate optional fields.216 capabilities.exceptionBreakpointFilters = {217 {{"filter1", "Filter 1", "Description 1", true, true, "Condition 1"},218 {"filter2", "Filter 2", "Description 2", false, false, "Condition 2"}}};219 220 capabilities.completionTriggerCharacters = {".", "->"};221 capabilities.additionalModuleColumns = {222 {"moduleName", "Module Name", "uppercase", eColumnTypeString, 20}};223 capabilities.supportedChecksumAlgorithms = {eChecksumAlgorithmMD5,224 eChecksumAlgorithmSHA256};225 capabilities.breakpointModes = {{"hardware",226 "Hardware Breakpoint",227 "Description",228 {eBreakpointModeApplicabilitySource}}};229 capabilities.lldbExtVersion = "1.0.0";230 231 // Perform roundtripJSON serialization and deserialization.232 llvm::Expected<Capabilities> deserialized_capabilities =233 roundtripJSON(capabilities);234 ASSERT_THAT_EXPECTED(deserialized_capabilities, llvm::Succeeded());235 236 // Verify supported features.237 EXPECT_EQ(capabilities.supportedFeatures,238 deserialized_capabilities->supportedFeatures);239 240 // Verify exception breakpoint filters.241 EXPECT_EQ(capabilities.exceptionBreakpointFilters.size(),242 deserialized_capabilities->exceptionBreakpointFilters.size());243 for (size_t i = 0; i < capabilities.exceptionBreakpointFilters.size(); ++i) {244 const auto &original = capabilities.exceptionBreakpointFilters.at(i);245 const auto &deserialized =246 deserialized_capabilities->exceptionBreakpointFilters.at(i);247 EXPECT_EQ(original.filter, deserialized.filter);248 EXPECT_EQ(original.label, deserialized.label);249 EXPECT_EQ(original.description, deserialized.description);250 EXPECT_EQ(original.defaultState, deserialized.defaultState);251 EXPECT_EQ(original.supportsCondition, deserialized.supportsCondition);252 EXPECT_EQ(original.conditionDescription, deserialized.conditionDescription);253 }254 255 // Verify completion trigger characters.256 EXPECT_EQ(capabilities.completionTriggerCharacters,257 deserialized_capabilities->completionTriggerCharacters);258 259 // Verify additional module columns.260 EXPECT_EQ(capabilities.additionalModuleColumns.size(),261 deserialized_capabilities->additionalModuleColumns.size());262 for (size_t i = 0; i < capabilities.additionalModuleColumns.size(); ++i) {263 const auto &original = capabilities.additionalModuleColumns.at(i);264 const auto &deserialized =265 deserialized_capabilities->additionalModuleColumns.at(i);266 EXPECT_EQ(original.attributeName, deserialized.attributeName);267 EXPECT_EQ(original.label, deserialized.label);268 EXPECT_EQ(original.format, deserialized.format);269 EXPECT_EQ(original.type, deserialized.type);270 EXPECT_EQ(original.width, deserialized.width);271 }272 273 // Verify supported checksum algorithms.274 EXPECT_EQ(capabilities.supportedChecksumAlgorithms,275 deserialized_capabilities->supportedChecksumAlgorithms);276 277 // Verify breakpoint modes.278 EXPECT_EQ(capabilities.breakpointModes.size(),279 deserialized_capabilities->breakpointModes.size());280 for (size_t i = 0; i < capabilities.breakpointModes.size(); ++i) {281 const auto &original = capabilities.breakpointModes.at(i);282 const auto &deserialized = deserialized_capabilities->breakpointModes.at(i);283 EXPECT_EQ(original.mode, deserialized.mode);284 EXPECT_EQ(original.label, deserialized.label);285 EXPECT_EQ(original.description, deserialized.description);286 EXPECT_EQ(original.appliesTo, deserialized.appliesTo);287 }288 289 // Verify lldb extension version.290 EXPECT_EQ(capabilities.lldbExtVersion,291 deserialized_capabilities->lldbExtVersion);292}293 294TEST(ProtocolTypesTest, Scope) {295 Scope scope;296 scope.name = "Locals";297 scope.presentationHint = Scope::eScopePresentationHintLocals;298 scope.variablesReference = 1;299 scope.namedVariables = 2;300 scope.indexedVariables = std::nullopt;301 scope.expensive = false;302 scope.line = 2;303 scope.column = 3;304 scope.endLine = 10;305 scope.endColumn = 20;306 307 Source source;308 source.name = "testName";309 source.path = "/path/to/source";310 source.sourceReference = 12345;311 source.presentationHint = Source::eSourcePresentationHintNormal;312 scope.source = source;313 314 llvm::Expected<Scope> deserialized_scope = roundtripJSON(scope);315 ASSERT_THAT_EXPECTED(deserialized_scope, llvm::Succeeded());316 EXPECT_EQ(scope.name, deserialized_scope->name);317 EXPECT_EQ(scope.presentationHint, deserialized_scope->presentationHint);318 EXPECT_EQ(scope.variablesReference, deserialized_scope->variablesReference);319 EXPECT_EQ(scope.namedVariables, deserialized_scope->namedVariables);320 EXPECT_EQ(scope.indexedVariables, deserialized_scope->indexedVariables);321 EXPECT_EQ(scope.expensive, deserialized_scope->expensive);322 EXPECT_EQ(scope.line, deserialized_scope->line);323 EXPECT_EQ(scope.column, deserialized_scope->column);324 EXPECT_EQ(scope.endLine, deserialized_scope->endLine);325 EXPECT_EQ(scope.endColumn, deserialized_scope->endColumn);326 327 EXPECT_THAT(deserialized_scope->source.has_value(), true);328 const Source &deserialized_source = deserialized_scope->source.value();329 330 EXPECT_EQ(source.path, deserialized_source.path);331 EXPECT_EQ(source.sourceReference, deserialized_source.sourceReference);332 EXPECT_EQ(source.presentationHint, deserialized_source.presentationHint);333}334 335TEST(ProtocolTypesTest, PresentationHint) {336 // Test all PresentationHint values.337 std::vector<std::pair<Source::PresentationHint, llvm::StringRef>> test_cases =338 {{Source::eSourcePresentationHintNormal, "normal"},339 {Source::eSourcePresentationHintEmphasize, "emphasize"},340 {Source::eSourcePresentationHintDeemphasize, "deemphasize"}};341 342 for (const auto &test_case : test_cases) {343 // Serialize the PresentationHint to JSON.344 llvm::json::Value serialized = toJSON(test_case.first);345 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);346 EXPECT_EQ(serialized.getAsString(), test_case.second);347 348 // Deserialize the JSON back to PresentationHint.349 Source::PresentationHint deserialized;350 llvm::json::Path::Root root;351 ASSERT_TRUE(fromJSON(serialized, deserialized, root))352 << llvm::toString(root.getError());353 EXPECT_EQ(deserialized, test_case.first);354 }355 356 // Test invalid value.357 llvm::json::Value invalid_value = "invalid_hint";358 Source::PresentationHint deserialized_invalid;359 llvm::json::Path::Root root;360 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));361}362 363TEST(ProtocolTypesTest, SteppingGranularity) {364 // Test all SteppingGranularity values.365 std::vector<std::pair<SteppingGranularity, llvm::StringRef>> test_cases = {366 {eSteppingGranularityStatement, "statement"},367 {eSteppingGranularityLine, "line"},368 {eSteppingGranularityInstruction, "instruction"}};369 370 for (const auto &test_case : test_cases) {371 // Serialize the SteppingGranularity to JSON.372 llvm::json::Value serialized = toJSON(test_case.first);373 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);374 EXPECT_EQ(serialized.getAsString(), test_case.second);375 376 // Deserialize the JSON back to SteppingGranularity.377 SteppingGranularity deserialized;378 llvm::json::Path::Root root;379 ASSERT_TRUE(fromJSON(serialized, deserialized, root))380 << llvm::toString(root.getError());381 EXPECT_EQ(deserialized, test_case.first);382 }383 384 // Test invalid value.385 llvm::json::Value invalid_value = "invalid_granularity";386 SteppingGranularity deserialized_invalid;387 llvm::json::Path::Root root;388 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));389}390 391TEST(ProtocolTypesTest, BreakpointReason) {392 // Test all BreakpointReason values.393 std::vector<std::pair<BreakpointReason, llvm::StringRef>> test_cases = {394 {BreakpointReason::eBreakpointReasonPending, "pending"},395 {BreakpointReason::eBreakpointReasonFailed, "failed"}};396 397 for (const auto &test_case : test_cases) {398 // Serialize the BreakpointReason to JSON.399 llvm::json::Value serialized = toJSON(test_case.first);400 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);401 EXPECT_EQ(serialized.getAsString(), test_case.second);402 403 // Deserialize the JSON back to BreakpointReason.404 BreakpointReason deserialized;405 llvm::json::Path::Root root;406 ASSERT_TRUE(fromJSON(serialized, deserialized, root))407 << llvm::toString(root.getError());408 EXPECT_EQ(deserialized, test_case.first);409 }410 411 // Test invalid value.412 llvm::json::Value invalid_value = "invalid_reason";413 BreakpointReason deserialized_invalid;414 llvm::json::Path::Root root;415 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));416}417 418TEST(ProtocolTypesTest, DataBreakpointAccessType) {419 // Test all DataBreakpointAccessType values.420 std::vector<std::pair<DataBreakpointAccessType, llvm::StringRef>> test_cases =421 {{eDataBreakpointAccessTypeRead, "read"},422 {eDataBreakpointAccessTypeWrite, "write"},423 {eDataBreakpointAccessTypeReadWrite, "readWrite"}};424 425 for (const auto &test_case : test_cases) {426 // Serialize the DataBreakpointAccessType to JSON.427 llvm::json::Value serialized = toJSON(test_case.first);428 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);429 EXPECT_EQ(serialized.getAsString(), test_case.second);430 431 // Deserialize the JSON back to DataBreakpointAccessType.432 DataBreakpointAccessType deserialized;433 llvm::json::Path::Root root;434 ASSERT_TRUE(fromJSON(serialized, deserialized, root))435 << llvm::toString(root.getError());436 EXPECT_EQ(deserialized, test_case.first);437 }438 439 // Test invalid value440 llvm::json::Value invalid_value = "invalid_access_type";441 DataBreakpointAccessType deserialized_invalid;442 llvm::json::Path::Root root;443 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));444}445 446TEST(ProtocolTypesTest, ColumnType) {447 // Test all ColumnType values.448 std::vector<std::pair<ColumnType, llvm::StringRef>> test_cases = {449 {eColumnTypeString, "string"},450 {eColumnTypeNumber, "number"},451 {eColumnTypeBoolean, "boolean"},452 {eColumnTypeTimestamp, "unixTimestampUTC"}};453 454 for (const auto &test_case : test_cases) {455 // Serialize the ColumnType to JSON.456 llvm::json::Value serialized = toJSON(test_case.first);457 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);458 EXPECT_EQ(serialized.getAsString(), test_case.second);459 460 // Deserialize the JSON back to ColumnType.461 ColumnType deserialized;462 llvm::json::Path::Root root;463 ASSERT_TRUE(fromJSON(serialized, deserialized, root))464 << llvm::toString(root.getError());465 EXPECT_EQ(deserialized, test_case.first);466 }467 468 // Test invalid value.469 llvm::json::Value invalid_value = "invalid_column_type";470 ColumnType deserialized_invalid;471 llvm::json::Path::Root root;472 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));473}474 475TEST(ProtocolTypesTest, BreakpointModeApplicability) {476 // Test all BreakpointModeApplicability values.477 std::vector<std::pair<BreakpointModeApplicability, llvm::StringRef>>478 test_cases = {{eBreakpointModeApplicabilitySource, "source"},479 {eBreakpointModeApplicabilityException, "exception"},480 {eBreakpointModeApplicabilityData, "data"},481 {eBreakpointModeApplicabilityInstruction, "instruction"}};482 483 for (const auto &test_case : test_cases) {484 // Serialize the BreakpointModeApplicability to JSON.485 llvm::json::Value serialized = toJSON(test_case.first);486 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);487 EXPECT_EQ(serialized.getAsString(), test_case.second);488 489 // Deserialize the JSON back to BreakpointModeApplicability.490 BreakpointModeApplicability deserialized;491 llvm::json::Path::Root root;492 ASSERT_TRUE(fromJSON(serialized, deserialized, root))493 << llvm::toString(root.getError());494 EXPECT_EQ(deserialized, test_case.first);495 }496 497 // Test invalid value.498 llvm::json::Value invalid_value = "invalid_applicability";499 BreakpointModeApplicability deserialized_invalid;500 llvm::json::Path::Root root;501 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));502}503 504TEST(ProtocolTypesTest, ChecksumAlgorithm) {505 // Test all ChecksumAlgorithm values.506 std::vector<std::pair<ChecksumAlgorithm, llvm::StringRef>> test_cases = {507 {eChecksumAlgorithmMD5, "MD5"},508 {eChecksumAlgorithmSHA1, "SHA1"},509 {eChecksumAlgorithmSHA256, "SHA256"},510 {eChecksumAlgorithmTimestamp, "timestamp"}};511 512 for (const auto &test_case : test_cases) {513 // Serialize the ChecksumAlgorithm to JSON.514 llvm::json::Value serialized = toJSON(test_case.first);515 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);516 EXPECT_EQ(serialized.getAsString(), test_case.second);517 518 // Deserialize the JSON back to ChecksumAlgorithm.519 ChecksumAlgorithm deserialized;520 llvm::json::Path::Root root;521 ASSERT_TRUE(fromJSON(serialized, deserialized, root))522 << llvm::toString(root.getError());523 EXPECT_EQ(deserialized, test_case.first);524 }525 526 // Test invalid value.527 llvm::json::Value invalid_value = "invalid_algorithm";528 ChecksumAlgorithm deserialized_invalid;529 llvm::json::Path::Root root;530 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));531}532 533TEST(ProtocolTypesTest, DisassembledInstructionPresentationHint) {534 // Test all PresentationHint values.535 std::vector<536 std::pair<DisassembledInstruction::PresentationHint, llvm::StringRef>>537 test_cases = {{DisassembledInstruction::538 eDisassembledInstructionPresentationHintNormal,539 "normal"},540 {DisassembledInstruction::541 eDisassembledInstructionPresentationHintInvalid,542 "invalid"}};543 544 for (const auto &test_case : test_cases) {545 // Serialize the PresentationHint to JSON.546 llvm::json::Value serialized = toJSON(test_case.first);547 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);548 EXPECT_EQ(serialized.getAsString(), test_case.second);549 550 // Deserialize the JSON back to PresentationHint.551 DisassembledInstruction::PresentationHint deserialized;552 llvm::json::Path::Root root;553 ASSERT_TRUE(fromJSON(serialized, deserialized, root))554 << llvm::toString(root.getError());555 EXPECT_EQ(deserialized, test_case.first);556 }557 558 // Test invalid value.559 llvm::json::Value invalid_value = "invalid_hint";560 DisassembledInstruction::PresentationHint deserialized_invalid;561 llvm::json::Path::Root root;562 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));563}564 565TEST(ProtocolTypesTest, DisassembledInstruction) {566 DisassembledInstruction instruction;567 instruction.address = 0x12345678;568 instruction.instructionBytes = "0F 1F 00";569 instruction.instruction = "mov eax, ebx";570 instruction.symbol = "main";571 instruction.location =572 Source{"test.cpp", "/path/to/test.cpp", 123,573 Source::eSourcePresentationHintNormal, std::nullopt};574 instruction.line = 10;575 instruction.column = 5;576 instruction.endLine = 15;577 instruction.endColumn = 10;578 instruction.presentationHint =579 DisassembledInstruction::eDisassembledInstructionPresentationHintNormal;580 581 StringLiteral json = R"({582 "address": "0x12345678",583 "column": 5,584 "endColumn": 10,585 "endLine": 15,586 "instruction": "mov eax, ebx",587 "instructionBytes": "0F 1F 00",588 "line": 10,589 "location": {590 "name": "test.cpp",591 "path": "/path/to/test.cpp",592 "presentationHint": "normal",593 "sourceReference": 123594 },595 "presentationHint": "normal",596 "symbol": "main"597})";598 599 // Validate toJSON600 EXPECT_EQ(json, pp(instruction));601 602 // Validate fromJSON603 EXPECT_THAT_EXPECTED(parse<DisassembledInstruction>(json),604 HasValue(Value(instruction)));605 // Validate parsing errors606 EXPECT_THAT_EXPECTED(607 parse<DisassembledInstruction>(R"({"address":1})",608 "disassemblyInstruction"),609 FailedWithMessage("expected string at disassemblyInstruction.address"));610 EXPECT_THAT_EXPECTED(611 parse<DisassembledInstruction>(R"({"address":"-1"})",612 "disassemblyInstruction"),613 FailedWithMessage(614 "malformed memory reference at disassemblyInstruction.address"));615 EXPECT_THAT_EXPECTED(616 parse<DisassembledInstruction>(617 R"({"address":"0xfffffffffffffffffffffffffff"})",618 "disassemblyInstruction"),619 FailedWithMessage(620 "malformed memory reference at disassemblyInstruction.address"));621}622 623TEST(ProtocolTypesTest, Thread) {624 const Thread thread{1, "thr1"};625 const StringRef json = R"({626 "id": 1,627 "name": "thr1"628})";629 // Validate toJSON630 EXPECT_EQ(json, pp(thread));631 // Validate fromJSON632 EXPECT_THAT_EXPECTED(parse<Thread>(json), HasValue(Value(thread)));633 // Validate parsing errors634 EXPECT_THAT_EXPECTED(parse<Thread>(R"({"id":1})", "thread"),635 FailedWithMessage("missing value at thread.name"));636 EXPECT_THAT_EXPECTED(parse<Thread>(R"({"id":"one"})", "thread"),637 FailedWithMessage("expected uint64_t at thread.id"));638 EXPECT_THAT_EXPECTED(parse<Thread>(R"({"id":1,"name":false})", "thread"),639 FailedWithMessage("expected string at thread.name"));640}641 642TEST(ProtocolTypesTest, ThreadResponseBody) {643 const ThreadsResponseBody body{{{1, "thr1"}, {2, "thr2"}}};644 const StringRef json = R"({645 "threads": [646 {647 "id": 1,648 "name": "thr1"649 },650 {651 "id": 2,652 "name": "thr2"653 }654 ]655})";656 // Validate toJSON657 EXPECT_EQ(json, pp(body));658}659 660TEST(ProtocolTypesTest, CapabilitiesEventBody) {661 Capabilities capabilities;662 capabilities.supportedFeatures = {663 eAdapterFeatureANSIStyling,664 eAdapterFeatureBreakpointLocationsRequest,665 };666 CapabilitiesEventBody body;667 body.capabilities = capabilities;668 StringRef json = R"({669 "capabilities": {670 "supportsANSIStyling": true,671 "supportsBreakpointLocationsRequest": true672 }673})";674 // Validate toJSON675 EXPECT_EQ(json, pp(body));676}677 678TEST(ProtocolTypesTest, ExceptionFilterOptions) {679 EXPECT_THAT_EXPECTED(parse<ExceptionFilterOptions>(R"({"filterId":"id"})"),680 HasValue(Value(ExceptionFilterOptions{681 /*filterId=*/"id", /*condition=*/"", /*mode*/ ""})));682 EXPECT_THAT_EXPECTED(683 parse<ExceptionFilterOptions>(R"({"filterId":"id","condition":"1+2"})"),684 HasValue(Value(ExceptionFilterOptions{685 /*filterId=*/"id", /*condition=*/"1+2", /*mode*/ ""})));686 EXPECT_THAT_EXPECTED(687 parse<ExceptionFilterOptions>(688 R"({"filterId":"id","condition":"1+2","mode":"m"})"),689 HasValue(Value(ExceptionFilterOptions{690 /*filterId=*/"id", /*condition=*/"1+2", /*mode*/ "m"})));691 692 // Validate parsing errors693 EXPECT_THAT_EXPECTED(694 parse<ExceptionFilterOptions>(R"({})", "exceptionFilterOptions"),695 FailedWithMessage("missing value at exceptionFilterOptions.filterId"));696 EXPECT_THAT_EXPECTED(697 parse<ExceptionFilterOptions>(R"({"filterId":"id","condition":42})",698 "exceptionFilterOptions"),699 FailedWithMessage("expected string at exceptionFilterOptions.condition"));700 EXPECT_THAT_EXPECTED(701 parse<ExceptionFilterOptions>(R"({"filterId":"id","mode":42})",702 "exceptionFilterOptions"),703 FailedWithMessage("expected string at exceptionFilterOptions.mode"));704}705 706TEST(ProtocolTypesTest, SetExceptionBreakpointsArguments) {707 EXPECT_THAT_EXPECTED(708 parse<SetExceptionBreakpointsArguments>(R"({"filters":[]})"),709 HasValue(testing::FieldsAre(/*filters=*/testing::IsEmpty(),710 /*filterOptions=*/testing::IsEmpty())));711 EXPECT_THAT_EXPECTED(712 parse<SetExceptionBreakpointsArguments>(R"({"filters":["abc"]})"),713 HasValue(testing::FieldsAre(/*filters=*/std::vector<std::string>{"abc"},714 /*filterOptions=*/testing::IsEmpty())));715 EXPECT_THAT_EXPECTED(716 parse<SetExceptionBreakpointsArguments>(717 R"({"filters":[],"filterOptions":[{"filterId":"abc"}]})"),718 HasValue(testing::FieldsAre(719 /*filters=*/testing::IsEmpty(),720 /*filterOptions=*/testing::Contains(testing::FieldsAre(721 /*filterId=*/"abc", /*condition=*/"", /*mode=*/"")))));722 723 // Validate parse errors724 EXPECT_THAT_EXPECTED(parse<SetExceptionBreakpointsArguments>(R"({})"),725 FailedWithMessage("missing value at (root).filters"));726 EXPECT_THAT_EXPECTED(727 parse<SetExceptionBreakpointsArguments>(R"({"filters":false})"),728 FailedWithMessage("expected array at (root).filters"));729}730 731TEST(ProtocolTypesTest, SetExceptionBreakpointsResponseBody) {732 SetExceptionBreakpointsResponseBody body;733 Breakpoint bp;734 bp.id = 12, bp.verified = true;735 body.breakpoints = {bp};736 EXPECT_EQ(R"({737 "breakpoints": [738 {739 "id": 12,740 "verified": true741 }742 ]743})",744 pp(body));745}746 747TEST(ProtocolTypesTest, StepInTarget) {748 StepInTarget target;749 target.id = 230;750 target.label = "the_function_name";751 target.line = 2;752 target.column = 320;753 target.endLine = 32;754 target.endColumn = 23;755 756 llvm::Expected<StepInTarget> deserialized_target = roundtripJSON(target);757 ASSERT_THAT_EXPECTED(deserialized_target, llvm::Succeeded());758 759 EXPECT_EQ(target.id, deserialized_target->id);760 EXPECT_EQ(target.label, deserialized_target->label);761 EXPECT_EQ(target.line, deserialized_target->line);762 EXPECT_EQ(target.column, deserialized_target->column);763 EXPECT_EQ(target.endLine, deserialized_target->endLine);764 EXPECT_EQ(target.endColumn, deserialized_target->endColumn);765}766 767TEST(ProtocolTypesTest, ReadMemoryArguments) {768 ReadMemoryArguments args;769 args.count = 20;770 args.memoryReference = 43962;771 args.offset = 0;772 773 llvm::Expected<ReadMemoryArguments> expected =774 parse<ReadMemoryArguments>(R"({"memoryReference":"-4000", "count": 20})");775 ASSERT_THAT_EXPECTED(expected, llvm::Failed());776 expected = parse<ReadMemoryArguments>(777 R"({"memoryReference":"0xabba", "count": 20})");778 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());779 780 EXPECT_EQ(args.count, expected->count);781 EXPECT_EQ(args.memoryReference, expected->memoryReference);782 EXPECT_EQ(args.offset, expected->offset);783}784 785TEST(ProtocolTypesTest, ReadMemoryResponseBody) {786 ReadMemoryResponseBody response;787 response.address = 0xdeadbeef;788 const std::string data_str = "hello world!";789 std::transform(data_str.begin(), data_str.end(),790 std::back_inserter(response.data),791 [](char letter) { return std::byte(letter); });792 response.unreadableBytes = 1;793 794 Expected<Value> expected = json::parse(795 R"({ "address": "0xDEADBEEF", "data": "aGVsbG8gd29ybGQh", "unreadableBytes": 1})");796 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());797 EXPECT_EQ(pp(*expected), pp(response));798}799 800TEST(ProtocolTypesTest, Modules) {801 Module module;802 module.id = "AC805E8E-B6A4-CD92-4B05-5CFA7CE24AE8-8926C776";803 module.name = "libm.so.6";804 module.path = "/some/path/to/libm.so.6";805 module.isOptimized = true;806 module.isUserCode = true;807 module.version = "0.0.1";808 module.symbolStatus = "Symbol not found.";809 module.symbolFilePath = "/some/file/path/to/the/symbol/module";810 module.dateTimeStamp = "2020-12-09T16:09:53+00:00";811 module.addressRange = "0xcafeface";812 module.debugInfoSizeBytes = 1572864;813 814 Expected<json::Value> expected = json::parse(815 R"({816 "id" : "AC805E8E-B6A4-CD92-4B05-5CFA7CE24AE8-8926C776",817 "name": "libm.so.6",818 "path": "/some/path/to/libm.so.6",819 "isOptimized": true,820 "isUserCode": true,821 "version": "0.0.1",822 "symbolStatus": "Symbol not found.",823 "symbolFilePath": "/some/file/path/to/the/symbol/module",824 "dateTimeStamp": "2020-12-09T16:09:53+00:00",825 "addressRange": "0xcafeface",826 "debugInfoSize": "1.5MB" })");827 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());828 EXPECT_EQ(pp(*expected), pp(module));829 830 // Test without optional values.831 module.path.clear();832 module.isOptimized = false;833 module.isUserCode = false;834 module.version.clear();835 module.symbolStatus.clear();836 module.symbolFilePath.clear();837 module.dateTimeStamp.clear();838 module.addressRange.clear();839 module.debugInfoSizeBytes = 0;840 EXPECT_NE(pp(*expected), pp(module));841 842 Expected<json::Value> expected_no_opt = json::parse(843 R"({844 "id" : "AC805E8E-B6A4-CD92-4B05-5CFA7CE24AE8-8926C776",845 "name": "libm.so.6"})");846 ASSERT_THAT_EXPECTED(expected_no_opt, llvm::Succeeded());847 EXPECT_EQ(pp(*expected_no_opt), pp(module));848}849 850TEST(ProtocolTypesTest, ModulesArguments) {851 ModulesArguments args;852 853 llvm::Expected<ModulesArguments> expected = parse<ModulesArguments>(R"({})");854 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());855 EXPECT_EQ(args.startModule, expected->startModule);856 EXPECT_EQ(args.moduleCount, expected->moduleCount);857 858 // Non Default values.859 args.startModule = 1;860 args.moduleCount = 2;861 llvm::Expected<ModulesArguments> expected_no_default =862 parse<ModulesArguments>(R"({ "startModule": 1, "moduleCount": 2})");863 ASSERT_THAT_EXPECTED(expected_no_default, llvm::Succeeded());864 EXPECT_EQ(args.startModule, expected_no_default->startModule);865 EXPECT_EQ(args.moduleCount, expected_no_default->moduleCount);866}867 868TEST(ProtocolTypesTest, ModulesResponseBody) {869 ModulesResponseBody response;870 Module module1;871 module1.id = "first id";872 module1.name = "first name";873 874 Module module2;875 module2.id = "second id";876 module2.name = "second name";877 response.modules = {std::move(module1), std::move(module2)};878 response.totalModules = 2;879 880 Expected<json::Value> expected = json::parse(881 R"({882 "modules": [883 { "id": "first id", "name": "first name"},884 { "id": "second id", "name": "second name"}885 ],886 "totalModules": 2 })");887 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());888 EXPECT_EQ(pp(*expected), pp(response));889}890 891TEST(ProtocolTypesTest, VariablePresentationHint) {892 VariablePresentationHint hint;893 hint.kind = "kind";894 hint.attributes = {"a", "b", "c"};895 hint.visibility = "public";896 hint.lazy = true;897 898 const StringRef json = R"({899 "attributes": [900 "a",901 "b",902 "c"903 ],904 "kind": "kind",905 "lazy": true,906 "visibility": "public"907})";908 909 EXPECT_EQ(pp(Value(hint)), json);910 EXPECT_THAT_EXPECTED(json::parse(json), HasValue(Value(hint)));911}912 913TEST(ProtocolTypesTest, Variable) {914 Variable var;915 var.name = "var1";916 var.variablesReference = 42;917 var.value = "value";918 var.type = "type";919 920 VariablePresentationHint hint;921 hint.kind = "kind";922 var.presentationHint = std::move(hint);923 var.evaluateName = "my_name";924 var.namedVariables = 7;925 var.indexedVariables = 7;926 var.memoryReference = 291u;927 var.declarationLocationReference = 24;928 var.valueLocationReference = 100;929 930 const StringRef json = R"({931 "declarationLocationReference": 24,932 "evaluateName": "my_name",933 "indexedVariables": 7,934 "memoryReference": "0x123",935 "name": "var1",936 "namedVariables": 7,937 "presentationHint": {938 "kind": "kind"939 },940 "type": "type",941 "value": "value",942 "valueLocationReference": 100,943 "variablesReference": 42944})";945 946 EXPECT_EQ(pp(Value(var)), json);947 EXPECT_THAT_EXPECTED(json::parse(json), HasValue(Value(var)));948}949 950TEST(ProtocolTypesTest, VariablesArguments) {951 llvm::Expected<VariablesArguments> expected = parse<VariablesArguments>(R"({952 "variablesReference": 42,953 "filter": "indexed",954 "start": 10,955 "count": 5,956 "format": {957 "hex": true958 }959 })");960 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());961 EXPECT_EQ(expected->variablesReference, 42u);962 EXPECT_EQ(expected->filter, VariablesArguments::eVariablesFilterIndexed);963 EXPECT_EQ(expected->start, 10u);964 EXPECT_EQ(expected->count, 5u);965 EXPECT_EQ(expected->format->hex, true);966 967 EXPECT_THAT_EXPECTED(968 parse<VariablesArguments>(R"({})"),969 FailedWithMessage("missing value at (root).variablesReference"));970 EXPECT_THAT_EXPECTED(971 parse<VariablesArguments>(972 R"({"variablesReference": 42, "filter": "my-filter"})"),973 FailedWithMessage(974 "unexpected value, expected 'named' or 'indexed' at (root).filter"));975}976 977TEST(ProtocolTypesTest, VariablesResponseBody) {978 Variable var1;979 var1.name = "var1";980 var1.variablesReference = 42;981 var1.value = "<var1-value>";982 983 Variable var2;984 var2.name = "var2";985 var2.variablesReference = 3;986 var2.value = "<var2-value>";987 988 VariablesResponseBody response{{var1, var2}};989 990 Expected<json::Value> expected = json::parse(R"({991 "variables": [992 {993 "name": "var1",994 "value": "<var1-value>",995 "variablesReference": 42996 },997 {998 "name": "var2",999 "value": "<var2-value>",1000 "variablesReference": 31001 }1002 ]1003 })");1004 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());1005 EXPECT_EQ(pp(*expected), pp(response));1006}1007 1008TEST(ProtocolTypesTest, CompletionItem) {1009 CompletionItem item;1010 item.label = "label";1011 item.text = "text";1012 item.sortText = "sortText";1013 item.detail = "detail";1014 item.type = eCompletionItemTypeConstructor;1015 item.start = 1;1016 item.length = 3;1017 item.selectionStart = 4;1018 item.selectionLength = 8;1019 1020 const StringRef json = R"({1021 "detail": "detail",1022 "label": "label",1023 "length": 3,1024 "selectionLength": 8,1025 "selectionStart": 4,1026 "sortText": "sortText",1027 "start": 1,1028 "text": "text",1029 "type": "constructor"1030})";1031 1032 EXPECT_EQ(pp(Value(item)), json);1033 EXPECT_THAT_EXPECTED(json::parse(json), HasValue(Value(item)));1034}1035 1036TEST(ProtocolTypesTest, CompletionsArguments) {1037 llvm::Expected<CompletionsArguments> expected =1038 parse<CompletionsArguments>(R"({1039 "column": 8,1040 "frameId": 7,1041 "line": 9,1042 "text": "abc"1043 })");1044 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());1045 EXPECT_EQ(expected->frameId, 7u);1046 EXPECT_EQ(expected->text, "abc");1047 EXPECT_EQ(expected->column, 8);1048 EXPECT_EQ(expected->line, 9);1049 1050 // Check required keys.1051 EXPECT_THAT_EXPECTED(parse<CompletionsArguments>(R"({})"),1052 FailedWithMessage("missing value at (root).text"));1053 EXPECT_THAT_EXPECTED(parse<CompletionsArguments>(R"({"text":"abc"})"),1054 FailedWithMessage("missing value at (root).column"));1055}1056 1057TEST(ProtocolTypesTest, CompletionsResponseBody) {1058 CompletionItem item;1059 item.label = "label";1060 item.text = "text";1061 item.detail = "detail";1062 CompletionsResponseBody response{{item}};1063 1064 Expected<json::Value> expected = json::parse(R"({1065 "targets": [1066 {1067 "detail": "detail",1068 "label": "label",1069 "text": "text"1070 }1071 ]1072 })");1073 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());1074 EXPECT_EQ(pp(*expected), pp(response));1075}1076 1077TEST(ProtocolTypesTest, InvalidatedEventBody) {1078 InvalidatedEventBody body;1079 body.areas = {InvalidatedEventBody::eAreaStacks,1080 InvalidatedEventBody::eAreaThreads};1081 body.stackFrameId = 1;1082 body.threadId = 20;1083 Expected<json::Value> expected = json::parse(R"({1084 "areas": [1085 "stacks",1086 "threads"1087 ],1088 "stackFrameId": 1,1089 "threadId": 201090 })");1091 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());1092 EXPECT_EQ(pp(*expected), pp(body));1093}1094 1095TEST(ProtocolTypesTest, MemoryEventBody) {1096 MemoryEventBody body;1097 body.memoryReference = 12345;1098 body.offset = 0;1099 body.count = 4;1100 StringRef json = R"({1101 "count": 4,1102 "memoryReference": "0x3039",1103 "offset": 01104})";1105 EXPECT_EQ(json, pp(body));1106}1107 1108TEST(ProtocolTypesTest, DataBreakpointInfoArguments) {1109 llvm::Expected<DataBreakpointInfoArguments> expected =1110 parse<DataBreakpointInfoArguments>(R"({1111 "name": "data",1112 "variablesReference": 8,1113 "frameId": 9,1114 "bytes": 10,1115 "asAddress": false,1116 "mode": "source"1117 })");1118 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());1119 EXPECT_EQ(expected->name, "data");1120 EXPECT_EQ(expected->variablesReference, 8);1121 EXPECT_EQ(expected->frameId, 9u);1122 EXPECT_EQ(expected->bytes, 10);1123 EXPECT_EQ(expected->asAddress, false);1124 EXPECT_EQ(expected->mode, "source");1125 1126 // Check required keys.1127 EXPECT_THAT_EXPECTED(parse<DataBreakpointInfoArguments>(R"({})"),1128 FailedWithMessage("missing value at (root).name"));1129 EXPECT_THAT_EXPECTED(parse<DataBreakpointInfoArguments>(R"({"name":"data"})"),1130 llvm::Succeeded());1131}1132 1133TEST(ProtocolTypesTest, ExceptionBreakMode) {1134 const std::vector<std::pair<ExceptionBreakMode, llvm::StringRef>> test_cases =1135 {{ExceptionBreakMode::eExceptionBreakModeAlways, "always"},1136 {ExceptionBreakMode::eExceptionBreakModeNever, "never"},1137 {ExceptionBreakMode::eExceptionBreakModeUnhandled, "unhandled"},1138 {ExceptionBreakMode::eExceptionBreakModeUserUnhandled, "userUnhandled"}};1139 1140 for (const auto [value, expected] : test_cases) {1141 json::Value const serialized = toJSON(value);1142 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);1143 EXPECT_EQ(serialized.getAsString(), expected);1144 }1145}1146 1147TEST(ProtocolTypesTest, ExceptionDetails) {1148 ExceptionDetails details;1149 1150 // Check required keys.1151 Expected<json::Value> expected = parse(R"({})");1152 ASSERT_THAT_EXPECTED(expected, llvm::Succeeded());1153 EXPECT_EQ(pp(*expected), pp(details));1154 1155 // Check optional keys.1156 details.message = "SIGABRT exception";1157 details.typeName = "signal";1158 details.fullTypeName = "SIGABRT";1159 details.evaluateName = "process handle SIGABRT";1160 details.stackTrace = "some stacktrace";1161 ExceptionDetails inner_details;1162 inner_details.message = "inner message";1163 details.innerException = {std::move(inner_details)};1164 1165 Expected<json::Value> expected_opt = parse(R"({1166 "message": "SIGABRT exception",1167 "typeName": "signal",1168 "fullTypeName": "SIGABRT",1169 "evaluateName": "process handle SIGABRT",1170 "stackTrace": "some stacktrace",1171 "innerException": [{1172 "message": "inner message"1173 }]1174 })");1175 1176 ASSERT_THAT_EXPECTED(expected_opt, llvm::Succeeded());1177 EXPECT_EQ(pp(*expected_opt), pp(details));1178}1179