blob: d97bbaffa2bc0aa532c9a4d2b45d1b3d562ba0ae [file] [log] [blame]
//===-- ProtocolTypesTest.cpp -----------------------------------*- C++ -*-===//
//
// 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/ProtocolTypes.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
using namespace lldb;
using namespace lldb_dap;
using namespace lldb_dap::protocol;
template <typename T> static llvm::Expected<T> roundtrip(const T &input) {
llvm::json::Value value = toJSON(input);
llvm::json::Path::Root root;
T output;
if (!fromJSON(value, output, root))
return root.getError();
return output;
}
TEST(ProtocolTypesTest, ExceptionBreakpointsFilter) {
ExceptionBreakpointsFilter filter;
filter.filter = "testFilter";
filter.label = "Test Filter";
filter.description = "This is a test filter";
filter.defaultState = true;
filter.supportsCondition = true;
filter.conditionDescription = "Condition for test filter";
llvm::Expected<ExceptionBreakpointsFilter> deserialized_filter =
roundtrip(filter);
ASSERT_THAT_EXPECTED(deserialized_filter, llvm::Succeeded());
EXPECT_EQ(filter.filter, deserialized_filter->filter);
EXPECT_EQ(filter.label, deserialized_filter->label);
EXPECT_EQ(filter.description, deserialized_filter->description);
EXPECT_EQ(filter.defaultState, deserialized_filter->defaultState);
EXPECT_EQ(filter.supportsCondition, deserialized_filter->supportsCondition);
EXPECT_EQ(filter.conditionDescription,
deserialized_filter->conditionDescription);
}
TEST(ProtocolTypesTest, Source) {
Source source;
source.name = "testName";
source.path = "/path/to/source";
source.sourceReference = 12345;
source.presentationHint = ePresentationHintEmphasize;
llvm::Expected<Source> deserialized_source = roundtrip(source);
ASSERT_THAT_EXPECTED(deserialized_source, llvm::Succeeded());
EXPECT_EQ(source.name, deserialized_source->name);
EXPECT_EQ(source.path, deserialized_source->path);
EXPECT_EQ(source.sourceReference, deserialized_source->sourceReference);
EXPECT_EQ(source.presentationHint, deserialized_source->presentationHint);
}
TEST(ProtocolTypesTest, ColumnDescriptor) {
ColumnDescriptor column;
column.attributeName = "moduleName";
column.label = "Module Name";
column.format = "uppercase";
column.type = eColumnTypeString;
column.width = 20;
llvm::Expected<ColumnDescriptor> deserialized_column = roundtrip(column);
ASSERT_THAT_EXPECTED(deserialized_column, llvm::Succeeded());
EXPECT_EQ(column.attributeName, deserialized_column->attributeName);
EXPECT_EQ(column.label, deserialized_column->label);
EXPECT_EQ(column.format, deserialized_column->format);
EXPECT_EQ(column.type, deserialized_column->type);
EXPECT_EQ(column.width, deserialized_column->width);
}
TEST(ProtocolTypesTest, BreakpointMode) {
BreakpointMode mode;
mode.mode = "testMode";
mode.label = "Test Mode";
mode.description = "This is a test mode";
mode.appliesTo = {eBreakpointModeApplicabilitySource,
eBreakpointModeApplicabilityException};
llvm::Expected<BreakpointMode> deserialized_mode = roundtrip(mode);
ASSERT_THAT_EXPECTED(deserialized_mode, llvm::Succeeded());
EXPECT_EQ(mode.mode, deserialized_mode->mode);
EXPECT_EQ(mode.label, deserialized_mode->label);
EXPECT_EQ(mode.description, deserialized_mode->description);
EXPECT_EQ(mode.appliesTo, deserialized_mode->appliesTo);
}
TEST(ProtocolTypesTest, Breakpoint) {
Breakpoint breakpoint;
breakpoint.id = 42;
breakpoint.verified = true;
breakpoint.message = "Breakpoint set successfully";
breakpoint.source =
Source{"test.cpp", "/path/to/test.cpp", 123, ePresentationHintNormal};
breakpoint.line = 10;
breakpoint.column = 5;
breakpoint.endLine = 15;
breakpoint.endColumn = 10;
breakpoint.instructionReference = "0x12345678";
breakpoint.offset = 4;
breakpoint.reason = BreakpointReason::eBreakpointReasonPending;
llvm::Expected<Breakpoint> deserialized_breakpoint = roundtrip(breakpoint);
ASSERT_THAT_EXPECTED(deserialized_breakpoint, llvm::Succeeded());
EXPECT_EQ(breakpoint.id, deserialized_breakpoint->id);
EXPECT_EQ(breakpoint.verified, deserialized_breakpoint->verified);
EXPECT_EQ(breakpoint.message, deserialized_breakpoint->message);
EXPECT_EQ(breakpoint.source->name, deserialized_breakpoint->source->name);
EXPECT_EQ(breakpoint.source->path, deserialized_breakpoint->source->path);
EXPECT_EQ(breakpoint.source->sourceReference,
deserialized_breakpoint->source->sourceReference);
EXPECT_EQ(breakpoint.source->presentationHint,
deserialized_breakpoint->source->presentationHint);
EXPECT_EQ(breakpoint.line, deserialized_breakpoint->line);
EXPECT_EQ(breakpoint.column, deserialized_breakpoint->column);
EXPECT_EQ(breakpoint.endLine, deserialized_breakpoint->endLine);
EXPECT_EQ(breakpoint.endColumn, deserialized_breakpoint->endColumn);
EXPECT_EQ(breakpoint.instructionReference,
deserialized_breakpoint->instructionReference);
EXPECT_EQ(breakpoint.offset, deserialized_breakpoint->offset);
EXPECT_EQ(breakpoint.reason, deserialized_breakpoint->reason);
}
TEST(ProtocolTypesTest, SourceBreakpoint) {
SourceBreakpoint source_breakpoint;
source_breakpoint.line = 42;
source_breakpoint.column = 5;
source_breakpoint.condition = "x > 10";
source_breakpoint.hitCondition = "5";
source_breakpoint.logMessage = "Breakpoint hit at line 42";
source_breakpoint.mode = "hardware";
llvm::Expected<SourceBreakpoint> deserialized_source_breakpoint =
roundtrip(source_breakpoint);
ASSERT_THAT_EXPECTED(deserialized_source_breakpoint, llvm::Succeeded());
EXPECT_EQ(source_breakpoint.line, deserialized_source_breakpoint->line);
EXPECT_EQ(source_breakpoint.column, deserialized_source_breakpoint->column);
EXPECT_EQ(source_breakpoint.condition,
deserialized_source_breakpoint->condition);
EXPECT_EQ(source_breakpoint.hitCondition,
deserialized_source_breakpoint->hitCondition);
EXPECT_EQ(source_breakpoint.logMessage,
deserialized_source_breakpoint->logMessage);
EXPECT_EQ(source_breakpoint.mode, deserialized_source_breakpoint->mode);
}
TEST(ProtocolTypesTest, FunctionBreakpoint) {
FunctionBreakpoint function_breakpoint;
function_breakpoint.name = "myFunction";
function_breakpoint.condition = "x == 0";
function_breakpoint.hitCondition = "3";
llvm::Expected<FunctionBreakpoint> deserialized_function_breakpoint =
roundtrip(function_breakpoint);
ASSERT_THAT_EXPECTED(deserialized_function_breakpoint, llvm::Succeeded());
EXPECT_EQ(function_breakpoint.name, deserialized_function_breakpoint->name);
EXPECT_EQ(function_breakpoint.condition,
deserialized_function_breakpoint->condition);
EXPECT_EQ(function_breakpoint.hitCondition,
deserialized_function_breakpoint->hitCondition);
}
TEST(ProtocolTypesTest, DataBreakpoint) {
DataBreakpoint data_breakpoint_info;
data_breakpoint_info.dataId = "variable1";
data_breakpoint_info.accessType = eDataBreakpointAccessTypeReadWrite;
data_breakpoint_info.condition = "x > 100";
data_breakpoint_info.hitCondition = "10";
llvm::Expected<DataBreakpoint> deserialized_data_breakpoint_info =
roundtrip(data_breakpoint_info);
ASSERT_THAT_EXPECTED(deserialized_data_breakpoint_info, llvm::Succeeded());
EXPECT_EQ(data_breakpoint_info.dataId,
deserialized_data_breakpoint_info->dataId);
EXPECT_EQ(data_breakpoint_info.accessType,
deserialized_data_breakpoint_info->accessType);
EXPECT_EQ(data_breakpoint_info.condition,
deserialized_data_breakpoint_info->condition);
EXPECT_EQ(data_breakpoint_info.hitCondition,
deserialized_data_breakpoint_info->hitCondition);
}
TEST(ProtocolTypesTest, Capabilities) {
Capabilities capabilities;
// Populate supported features.
capabilities.supportedFeatures.insert(eAdapterFeatureANSIStyling);
capabilities.supportedFeatures.insert(
eAdapterFeatureBreakpointLocationsRequest);
// Populate optional fields.
capabilities.exceptionBreakpointFilters = {
{{"filter1", "Filter 1", "Description 1", true, true, "Condition 1"},
{"filter2", "Filter 2", "Description 2", false, false, "Condition 2"}}};
capabilities.completionTriggerCharacters = {".", "->"};
capabilities.additionalModuleColumns = {
{"moduleName", "Module Name", "uppercase", eColumnTypeString, 20}};
capabilities.supportedChecksumAlgorithms = {eChecksumAlgorithmMD5,
eChecksumAlgorithmSHA256};
capabilities.breakpointModes = {{"hardware",
"Hardware Breakpoint",
"Description",
{eBreakpointModeApplicabilitySource}}};
capabilities.lldbExtVersion = "1.0.0";
// Perform roundtrip serialization and deserialization.
llvm::Expected<Capabilities> deserialized_capabilities =
roundtrip(capabilities);
ASSERT_THAT_EXPECTED(deserialized_capabilities, llvm::Succeeded());
// Verify supported features.
EXPECT_EQ(capabilities.supportedFeatures,
deserialized_capabilities->supportedFeatures);
// Verify exception breakpoint filters.
ASSERT_TRUE(
deserialized_capabilities->exceptionBreakpointFilters.has_value());
EXPECT_EQ(capabilities.exceptionBreakpointFilters->size(),
deserialized_capabilities->exceptionBreakpointFilters->size());
for (size_t i = 0; i < capabilities.exceptionBreakpointFilters->size(); ++i) {
const auto &original = capabilities.exceptionBreakpointFilters->at(i);
const auto &deserialized =
deserialized_capabilities->exceptionBreakpointFilters->at(i);
EXPECT_EQ(original.filter, deserialized.filter);
EXPECT_EQ(original.label, deserialized.label);
EXPECT_EQ(original.description, deserialized.description);
EXPECT_EQ(original.defaultState, deserialized.defaultState);
EXPECT_EQ(original.supportsCondition, deserialized.supportsCondition);
EXPECT_EQ(original.conditionDescription, deserialized.conditionDescription);
}
// Verify completion trigger characters.
ASSERT_TRUE(
deserialized_capabilities->completionTriggerCharacters.has_value());
EXPECT_EQ(capabilities.completionTriggerCharacters,
deserialized_capabilities->completionTriggerCharacters);
// Verify additional module columns.
ASSERT_TRUE(deserialized_capabilities->additionalModuleColumns.has_value());
EXPECT_EQ(capabilities.additionalModuleColumns->size(),
deserialized_capabilities->additionalModuleColumns->size());
for (size_t i = 0; i < capabilities.additionalModuleColumns->size(); ++i) {
const auto &original = capabilities.additionalModuleColumns->at(i);
const auto &deserialized =
deserialized_capabilities->additionalModuleColumns->at(i);
EXPECT_EQ(original.attributeName, deserialized.attributeName);
EXPECT_EQ(original.label, deserialized.label);
EXPECT_EQ(original.format, deserialized.format);
EXPECT_EQ(original.type, deserialized.type);
EXPECT_EQ(original.width, deserialized.width);
}
// Verify supported checksum algorithms.
ASSERT_TRUE(
deserialized_capabilities->supportedChecksumAlgorithms.has_value());
EXPECT_EQ(capabilities.supportedChecksumAlgorithms,
deserialized_capabilities->supportedChecksumAlgorithms);
// Verify breakpoint modes.
ASSERT_TRUE(deserialized_capabilities->breakpointModes.has_value());
EXPECT_EQ(capabilities.breakpointModes->size(),
deserialized_capabilities->breakpointModes->size());
for (size_t i = 0; i < capabilities.breakpointModes->size(); ++i) {
const auto &original = capabilities.breakpointModes->at(i);
const auto &deserialized =
deserialized_capabilities->breakpointModes->at(i);
EXPECT_EQ(original.mode, deserialized.mode);
EXPECT_EQ(original.label, deserialized.label);
EXPECT_EQ(original.description, deserialized.description);
EXPECT_EQ(original.appliesTo, deserialized.appliesTo);
}
// Verify lldb extension version.
ASSERT_TRUE(deserialized_capabilities->lldbExtVersion.has_value());
EXPECT_EQ(capabilities.lldbExtVersion,
deserialized_capabilities->lldbExtVersion);
}
TEST(ProtocolTypesTest, PresentationHint) {
// Test all PresentationHint values.
std::vector<std::pair<PresentationHint, llvm::StringRef>> test_cases = {
{ePresentationHintNormal, "normal"},
{ePresentationHintEmphasize, "emphasize"},
{ePresentationHintDeemphasize, "deemphasize"}};
for (const auto &test_case : test_cases) {
// Serialize the PresentationHint to JSON.
llvm::json::Value serialized = toJSON(test_case.first);
ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
EXPECT_EQ(serialized.getAsString(), test_case.second);
// Deserialize the JSON back to PresentationHint.
PresentationHint deserialized;
llvm::json::Path::Root root;
ASSERT_TRUE(fromJSON(serialized, deserialized, root))
<< llvm::toString(root.getError());
EXPECT_EQ(deserialized, test_case.first);
}
// Test invalid value.
llvm::json::Value invalid_value = "invalid_hint";
PresentationHint deserialized_invalid;
llvm::json::Path::Root root;
EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
}
TEST(ProtocolTypesTest, SteppingGranularity) {
// Test all SteppingGranularity values.
std::vector<std::pair<SteppingGranularity, llvm::StringRef>> test_cases = {
{eSteppingGranularityStatement, "statement"},
{eSteppingGranularityLine, "line"},
{eSteppingGranularityInstruction, "instruction"}};
for (const auto &test_case : test_cases) {
// Serialize the SteppingGranularity to JSON.
llvm::json::Value serialized = toJSON(test_case.first);
ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
EXPECT_EQ(serialized.getAsString(), test_case.second);
// Deserialize the JSON back to SteppingGranularity.
SteppingGranularity deserialized;
llvm::json::Path::Root root;
ASSERT_TRUE(fromJSON(serialized, deserialized, root))
<< llvm::toString(root.getError());
EXPECT_EQ(deserialized, test_case.first);
}
// Test invalid value.
llvm::json::Value invalid_value = "invalid_granularity";
SteppingGranularity deserialized_invalid;
llvm::json::Path::Root root;
EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
}
TEST(ProtocolTypesTest, BreakpointReason) {
// Test all BreakpointReason values.
std::vector<std::pair<BreakpointReason, llvm::StringRef>> test_cases = {
{BreakpointReason::eBreakpointReasonPending, "pending"},
{BreakpointReason::eBreakpointReasonFailed, "failed"}};
for (const auto &test_case : test_cases) {
// Serialize the BreakpointReason to JSON.
llvm::json::Value serialized = toJSON(test_case.first);
ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
EXPECT_EQ(serialized.getAsString(), test_case.second);
// Deserialize the JSON back to BreakpointReason.
BreakpointReason deserialized;
llvm::json::Path::Root root;
ASSERT_TRUE(fromJSON(serialized, deserialized, root))
<< llvm::toString(root.getError());
EXPECT_EQ(deserialized, test_case.first);
}
// Test invalid value.
llvm::json::Value invalid_value = "invalid_reason";
BreakpointReason deserialized_invalid;
llvm::json::Path::Root root;
EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
}
TEST(ProtocolTypesTest, DataBreakpointAccessType) {
// Test all DataBreakpointAccessType values.
std::vector<std::pair<DataBreakpointAccessType, llvm::StringRef>> test_cases =
{{eDataBreakpointAccessTypeRead, "read"},
{eDataBreakpointAccessTypeWrite, "write"},
{eDataBreakpointAccessTypeReadWrite, "readWrite"}};
for (const auto &test_case : test_cases) {
// Serialize the DataBreakpointAccessType to JSON.
llvm::json::Value serialized = toJSON(test_case.first);
ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
EXPECT_EQ(serialized.getAsString(), test_case.second);
// Deserialize the JSON back to DataBreakpointAccessType.
DataBreakpointAccessType deserialized;
llvm::json::Path::Root root;
ASSERT_TRUE(fromJSON(serialized, deserialized, root))
<< llvm::toString(root.getError());
EXPECT_EQ(deserialized, test_case.first);
}
// Test invalid value
llvm::json::Value invalid_value = "invalid_access_type";
DataBreakpointAccessType deserialized_invalid;
llvm::json::Path::Root root;
EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
}
TEST(ProtocolTypesTest, ColumnType) {
// Test all ColumnType values.
std::vector<std::pair<ColumnType, llvm::StringRef>> test_cases = {
{eColumnTypeString, "string"},
{eColumnTypeNumber, "number"},
{eColumnTypeBoolean, "boolean"},
{eColumnTypeTimestamp, "unixTimestampUTC"}};
for (const auto &test_case : test_cases) {
// Serialize the ColumnType to JSON.
llvm::json::Value serialized = toJSON(test_case.first);
ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
EXPECT_EQ(serialized.getAsString(), test_case.second);
// Deserialize the JSON back to ColumnType.
ColumnType deserialized;
llvm::json::Path::Root root;
ASSERT_TRUE(fromJSON(serialized, deserialized, root))
<< llvm::toString(root.getError());
EXPECT_EQ(deserialized, test_case.first);
}
// Test invalid value.
llvm::json::Value invalid_value = "invalid_column_type";
ColumnType deserialized_invalid;
llvm::json::Path::Root root;
EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
}
TEST(ProtocolTypesTest, BreakpointModeApplicability) {
// Test all BreakpointModeApplicability values.
std::vector<std::pair<BreakpointModeApplicability, llvm::StringRef>>
test_cases = {{eBreakpointModeApplicabilitySource, "source"},
{eBreakpointModeApplicabilityException, "exception"},
{eBreakpointModeApplicabilityData, "data"},
{eBreakpointModeApplicabilityInstruction, "instruction"}};
for (const auto &test_case : test_cases) {
// Serialize the BreakpointModeApplicability to JSON.
llvm::json::Value serialized = toJSON(test_case.first);
ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
EXPECT_EQ(serialized.getAsString(), test_case.second);
// Deserialize the JSON back to BreakpointModeApplicability.
BreakpointModeApplicability deserialized;
llvm::json::Path::Root root;
ASSERT_TRUE(fromJSON(serialized, deserialized, root))
<< llvm::toString(root.getError());
EXPECT_EQ(deserialized, test_case.first);
}
// Test invalid value.
llvm::json::Value invalid_value = "invalid_applicability";
BreakpointModeApplicability deserialized_invalid;
llvm::json::Path::Root root;
EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
}
TEST(ProtocolTypesTest, ChecksumAlgorithm) {
// Test all ChecksumAlgorithm values.
std::vector<std::pair<ChecksumAlgorithm, llvm::StringRef>> test_cases = {
{eChecksumAlgorithmMD5, "MD5"},
{eChecksumAlgorithmSHA1, "SHA1"},
{eChecksumAlgorithmSHA256, "SHA256"},
{eChecksumAlgorithmTimestamp, "timestamp"}};
for (const auto &test_case : test_cases) {
// Serialize the ChecksumAlgorithm to JSON.
llvm::json::Value serialized = toJSON(test_case.first);
ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
EXPECT_EQ(serialized.getAsString(), test_case.second);
// Deserialize the JSON back to ChecksumAlgorithm.
ChecksumAlgorithm deserialized;
llvm::json::Path::Root root;
ASSERT_TRUE(fromJSON(serialized, deserialized, root))
<< llvm::toString(root.getError());
EXPECT_EQ(deserialized, test_case.first);
}
// Test invalid value.
llvm::json::Value invalid_value = "invalid_algorithm";
ChecksumAlgorithm deserialized_invalid;
llvm::json::Path::Root root;
EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
}