[Lldb-commits] [lldb] ad2f703 - [lldb-dap] Add unit test for capabilities (#139835)
via lldb-commits
lldb-commits at lists.llvm.org
Tue May 13 22:51:06 PDT 2025
Author: Jonas Devlieghere
Date: 2025-05-13T22:51:03-07:00
New Revision: ad2f7034a2823f2366e55a5758c1c623b9348746
URL: https://github.com/llvm/llvm-project/commit/ad2f7034a2823f2366e55a5758c1c623b9348746
DIFF: https://github.com/llvm/llvm-project/commit/ad2f7034a2823f2366e55a5758c1c623b9348746.diff
LOG: [lldb-dap] Add unit test for capabilities (#139835)
Add unit a test for the capabilities type.
Added:
Modified:
lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
lldb/unittests/DAP/ProtocolTypesTest.cpp
Removed:
################################################################################
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index 8d95687e00e53..fafd061334bc9 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -165,6 +165,32 @@ json::Value toJSON(const ChecksumAlgorithm &CA) {
llvm_unreachable("unhandled checksum algorithm.");
}
+bool fromJSON(const llvm::json::Value &Params, ChecksumAlgorithm &CA,
+ llvm::json::Path P) {
+ auto rawAlgorithm = Params.getAsString();
+ if (!rawAlgorithm) {
+ P.report("expected a string");
+ return false;
+ }
+
+ std::optional<ChecksumAlgorithm> algorithm =
+ llvm::StringSwitch<std::optional<ChecksumAlgorithm>>(*rawAlgorithm)
+ .Case("MD5", eChecksumAlgorithmMD5)
+ .Case("SHA1", eChecksumAlgorithmSHA1)
+ .Case("SHA256", eChecksumAlgorithmSHA256)
+ .Case("timestamp", eChecksumAlgorithmTimestamp)
+ .Default(std::nullopt);
+
+ if (!algorithm) {
+ P.report(
+ "unexpected value, expected 'MD5', 'SHA1', 'SHA256', or 'timestamp'");
+ return false;
+ }
+
+ CA = *algorithm;
+ return true;
+}
+
json::Value toJSON(const BreakpointModeApplicability &BMA) {
switch (BMA) {
case eBreakpointModeApplicabilitySource:
@@ -304,6 +330,84 @@ static llvm::StringLiteral ToString(AdapterFeature feature) {
llvm_unreachable("unhandled adapter feature.");
}
+llvm::json::Value toJSON(const AdapterFeature &feature) {
+ return ToString(feature);
+}
+
+bool fromJSON(const llvm::json::Value &Params, AdapterFeature &feature,
+ llvm::json::Path P) {
+ auto rawFeature = Params.getAsString();
+ if (!rawFeature) {
+ P.report("expected a string");
+ return false;
+ }
+
+ std::optional<AdapterFeature> parsedFeature =
+ llvm::StringSwitch<std::optional<AdapterFeature>>(*rawFeature)
+ .Case("supportsANSIStyling", eAdapterFeatureANSIStyling)
+ .Case("supportsBreakpointLocationsRequest",
+ eAdapterFeatureBreakpointLocationsRequest)
+ .Case("supportsCancelRequest", eAdapterFeatureCancelRequest)
+ .Case("supportsClipboardContext", eAdapterFeatureClipboardContext)
+ .Case("supportsCompletionsRequest", eAdapterFeatureCompletionsRequest)
+ .Case("supportsConditionalBreakpoints",
+ eAdapterFeatureConditionalBreakpoints)
+ .Case("supportsConfigurationDoneRequest",
+ eAdapterFeatureConfigurationDoneRequest)
+ .Case("supportsDataBreakpointBytes",
+ eAdapterFeatureDataBreakpointBytes)
+ .Case("supportsDataBreakpoints", eAdapterFeatureDataBreakpoints)
+ .Case("supportsDelayedStackTraceLoading",
+ eAdapterFeatureDelayedStackTraceLoading)
+ .Case("supportsDisassembleRequest", eAdapterFeatureDisassembleRequest)
+ .Case("supportsEvaluateForHovers", eAdapterFeatureEvaluateForHovers)
+ .Case("supportsExceptionFilterOptions",
+ eAdapterFeatureExceptionFilterOptions)
+ .Case("supportsExceptionInfoRequest",
+ eAdapterFeatureExceptionInfoRequest)
+ .Case("supportsExceptionOptions", eAdapterFeatureExceptionOptions)
+ .Case("supportsFunctionBreakpoints",
+ eAdapterFeatureFunctionBreakpoints)
+ .Case("supportsGotoTargetsRequest", eAdapterFeatureGotoTargetsRequest)
+ .Case("supportsHitConditionalBreakpoints",
+ eAdapterFeatureHitConditionalBreakpoints)
+ .Case("supportsInstructionBreakpoints",
+ eAdapterFeatureInstructionBreakpoints)
+ .Case("supportsLoadedSourcesRequest",
+ eAdapterFeatureLoadedSourcesRequest)
+ .Case("supportsLogPoints", eAdapterFeatureLogPoints)
+ .Case("supportsModulesRequest", eAdapterFeatureModulesRequest)
+ .Case("supportsReadMemoryRequest", eAdapterFeatureReadMemoryRequest)
+ .Case("supportsRestartFrame", eAdapterFeatureRestartFrame)
+ .Case("supportsRestartRequest", eAdapterFeatureRestartRequest)
+ .Case("supportsSetExpression", eAdapterFeatureSetExpression)
+ .Case("supportsSetVariable", eAdapterFeatureSetVariable)
+ .Case("supportsSingleThreadExecutionRequests",
+ eAdapterFeatureSingleThreadExecutionRequests)
+ .Case("supportsStepBack", eAdapterFeatureStepBack)
+ .Case("supportsStepInTargetsRequest",
+ eAdapterFeatureStepInTargetsRequest)
+ .Case("supportsSteppingGranularity",
+ eAdapterFeatureSteppingGranularity)
+ .Case("supportsTerminateRequest", eAdapterFeatureTerminateRequest)
+ .Case("supportsTerminateThreadsRequest",
+ eAdapterFeatureTerminateThreadsRequest)
+ .Case("supportSuspendDebuggee", eAdapterFeatureSuspendDebuggee)
+ .Case("supportsValueFormattingOptions",
+ eAdapterFeatureValueFormattingOptions)
+ .Case("supportsWriteMemoryRequest", eAdapterFeatureWriteMemoryRequest)
+ .Case("supportTerminateDebuggee", eAdapterFeatureTerminateDebuggee)
+ .Default(std::nullopt);
+
+ if (!parsedFeature) {
+ P.report("unexpected value for AdapterFeature");
+ return false;
+ }
+
+ feature = *parsedFeature;
+ return true;
+}
+
json::Value toJSON(const Capabilities &C) {
json::Object result;
@@ -331,6 +435,32 @@ json::Value toJSON(const Capabilities &C) {
return result;
}
+bool fromJSON(const llvm::json::Value &Params, Capabilities &C,
+ llvm::json::Path P) {
+ auto *Object = Params.getAsObject();
+ if (!Object) {
+ P.report("expected an object");
+ return false;
+ }
+ // Check for the presence of supported features.
+ for (unsigned i = eAdapterFeatureFirst; i <= eAdapterFeatureLast; ++i) {
+ AdapterFeature feature = static_cast<AdapterFeature>(i);
+ if (Object->getBoolean(ToString(feature)))
+ C.supportedFeatures.insert(feature);
+ }
+ llvm::json::ObjectMapper O(Params, P);
+ return O &&
+ O.mapOptional("exceptionBreakpointFilters",
+ C.exceptionBreakpointFilters) &&
+ O.mapOptional("completionTriggerCharacters",
+ C.completionTriggerCharacters) &&
+ O.mapOptional("additionalModuleColumns", C.additionalModuleColumns) &&
+ O.mapOptional("supportedChecksumAlgorithms",
+ C.supportedChecksumAlgorithms) &&
+ O.mapOptional("breakpointModes", C.breakpointModes) &&
+ O.mapOptional("$__lldb_version", C.lldbExtVersion);
+}
+
bool fromJSON(const llvm::json::Value &Params, SteppingGranularity &SG,
llvm::json::Path P) {
auto raw_granularity = Params.getAsString();
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index c48988a48a373..f8d2b35ce3e14 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -102,6 +102,7 @@ enum ChecksumAlgorithm : unsigned {
eChecksumAlgorithmSHA256,
eChecksumAlgorithmTimestamp
};
+bool fromJSON(const llvm::json::Value &, ChecksumAlgorithm &, llvm::json::Path);
llvm::json::Value toJSON(const ChecksumAlgorithm &);
/// Describes one or more type of breakpoint a BreakpointMode applies to. This
@@ -237,7 +238,11 @@ enum AdapterFeature : unsigned {
/// The debug adapter supports the `terminateDebuggee` attribute on the
/// `disconnect` request.
eAdapterFeatureTerminateDebuggee,
+ eAdapterFeatureFirst = eAdapterFeatureANSIStyling,
+ eAdapterFeatureLast = eAdapterFeatureTerminateDebuggee,
};
+bool fromJSON(const llvm::json::Value &, AdapterFeature &, llvm::json::Path);
+llvm::json::Value toJSON(const AdapterFeature &);
/// Information about the capabilities of a debug adapter.
struct Capabilities {
@@ -275,13 +280,15 @@ struct Capabilities {
/// @}
};
+bool fromJSON(const llvm::json::Value &, Capabilities &, llvm::json::Path);
llvm::json::Value toJSON(const Capabilities &);
enum PresentationHint : unsigned {
ePresentationHintNormal,
ePresentationHintEmphasize,
- ePresentationHintDeemphasize,
+ ePresentationHintDeemphasize
};
+bool fromJSON(const llvm::json::Value &, PresentationHint &, llvm::json::Path);
llvm::json::Value toJSON(PresentationHint hint);
/// A `Source` is a descriptor for source code. It is returned from the debug
diff --git a/lldb/unittests/DAP/ProtocolTypesTest.cpp b/lldb/unittests/DAP/ProtocolTypesTest.cpp
index f5d72f06432d5..fd3e3be073183 100644
--- a/lldb/unittests/DAP/ProtocolTypesTest.cpp
+++ b/lldb/unittests/DAP/ProtocolTypesTest.cpp
@@ -194,3 +194,100 @@ TEST(ProtocolTypesTest, DataBreakpoint) {
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);
+}
More information about the lldb-commits
mailing list