Skip to content

Commit ad2f703

Browse files
authored
[lldb-dap] Add unit test for capabilities (#139835)
Add unit a test for the capabilities type.
1 parent fbeab2c commit ad2f703

File tree

3 files changed

+235
-1
lines changed

3 files changed

+235
-1
lines changed

lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,32 @@ json::Value toJSON(const ChecksumAlgorithm &CA) {
165165
llvm_unreachable("unhandled checksum algorithm.");
166166
}
167167

168+
bool fromJSON(const llvm::json::Value &Params, ChecksumAlgorithm &CA,
169+
llvm::json::Path P) {
170+
auto rawAlgorithm = Params.getAsString();
171+
if (!rawAlgorithm) {
172+
P.report("expected a string");
173+
return false;
174+
}
175+
176+
std::optional<ChecksumAlgorithm> algorithm =
177+
llvm::StringSwitch<std::optional<ChecksumAlgorithm>>(*rawAlgorithm)
178+
.Case("MD5", eChecksumAlgorithmMD5)
179+
.Case("SHA1", eChecksumAlgorithmSHA1)
180+
.Case("SHA256", eChecksumAlgorithmSHA256)
181+
.Case("timestamp", eChecksumAlgorithmTimestamp)
182+
.Default(std::nullopt);
183+
184+
if (!algorithm) {
185+
P.report(
186+
"unexpected value, expected 'MD5', 'SHA1', 'SHA256', or 'timestamp'");
187+
return false;
188+
}
189+
190+
CA = *algorithm;
191+
return true;
192+
}
193+
168194
json::Value toJSON(const BreakpointModeApplicability &BMA) {
169195
switch (BMA) {
170196
case eBreakpointModeApplicabilitySource:
@@ -304,6 +330,84 @@ static llvm::StringLiteral ToString(AdapterFeature feature) {
304330
llvm_unreachable("unhandled adapter feature.");
305331
}
306332

333+
llvm::json::Value toJSON(const AdapterFeature &feature) {
334+
return ToString(feature);
335+
}
336+
337+
bool fromJSON(const llvm::json::Value &Params, AdapterFeature &feature,
338+
llvm::json::Path P) {
339+
auto rawFeature = Params.getAsString();
340+
if (!rawFeature) {
341+
P.report("expected a string");
342+
return false;
343+
}
344+
345+
std::optional<AdapterFeature> parsedFeature =
346+
llvm::StringSwitch<std::optional<AdapterFeature>>(*rawFeature)
347+
.Case("supportsANSIStyling", eAdapterFeatureANSIStyling)
348+
.Case("supportsBreakpointLocationsRequest",
349+
eAdapterFeatureBreakpointLocationsRequest)
350+
.Case("supportsCancelRequest", eAdapterFeatureCancelRequest)
351+
.Case("supportsClipboardContext", eAdapterFeatureClipboardContext)
352+
.Case("supportsCompletionsRequest", eAdapterFeatureCompletionsRequest)
353+
.Case("supportsConditionalBreakpoints",
354+
eAdapterFeatureConditionalBreakpoints)
355+
.Case("supportsConfigurationDoneRequest",
356+
eAdapterFeatureConfigurationDoneRequest)
357+
.Case("supportsDataBreakpointBytes",
358+
eAdapterFeatureDataBreakpointBytes)
359+
.Case("supportsDataBreakpoints", eAdapterFeatureDataBreakpoints)
360+
.Case("supportsDelayedStackTraceLoading",
361+
eAdapterFeatureDelayedStackTraceLoading)
362+
.Case("supportsDisassembleRequest", eAdapterFeatureDisassembleRequest)
363+
.Case("supportsEvaluateForHovers", eAdapterFeatureEvaluateForHovers)
364+
.Case("supportsExceptionFilterOptions",
365+
eAdapterFeatureExceptionFilterOptions)
366+
.Case("supportsExceptionInfoRequest",
367+
eAdapterFeatureExceptionInfoRequest)
368+
.Case("supportsExceptionOptions", eAdapterFeatureExceptionOptions)
369+
.Case("supportsFunctionBreakpoints",
370+
eAdapterFeatureFunctionBreakpoints)
371+
.Case("supportsGotoTargetsRequest", eAdapterFeatureGotoTargetsRequest)
372+
.Case("supportsHitConditionalBreakpoints",
373+
eAdapterFeatureHitConditionalBreakpoints)
374+
.Case("supportsInstructionBreakpoints",
375+
eAdapterFeatureInstructionBreakpoints)
376+
.Case("supportsLoadedSourcesRequest",
377+
eAdapterFeatureLoadedSourcesRequest)
378+
.Case("supportsLogPoints", eAdapterFeatureLogPoints)
379+
.Case("supportsModulesRequest", eAdapterFeatureModulesRequest)
380+
.Case("supportsReadMemoryRequest", eAdapterFeatureReadMemoryRequest)
381+
.Case("supportsRestartFrame", eAdapterFeatureRestartFrame)
382+
.Case("supportsRestartRequest", eAdapterFeatureRestartRequest)
383+
.Case("supportsSetExpression", eAdapterFeatureSetExpression)
384+
.Case("supportsSetVariable", eAdapterFeatureSetVariable)
385+
.Case("supportsSingleThreadExecutionRequests",
386+
eAdapterFeatureSingleThreadExecutionRequests)
387+
.Case("supportsStepBack", eAdapterFeatureStepBack)
388+
.Case("supportsStepInTargetsRequest",
389+
eAdapterFeatureStepInTargetsRequest)
390+
.Case("supportsSteppingGranularity",
391+
eAdapterFeatureSteppingGranularity)
392+
.Case("supportsTerminateRequest", eAdapterFeatureTerminateRequest)
393+
.Case("supportsTerminateThreadsRequest",
394+
eAdapterFeatureTerminateThreadsRequest)
395+
.Case("supportSuspendDebuggee", eAdapterFeatureSuspendDebuggee)
396+
.Case("supportsValueFormattingOptions",
397+
eAdapterFeatureValueFormattingOptions)
398+
.Case("supportsWriteMemoryRequest", eAdapterFeatureWriteMemoryRequest)
399+
.Case("supportTerminateDebuggee", eAdapterFeatureTerminateDebuggee)
400+
.Default(std::nullopt);
401+
402+
if (!parsedFeature) {
403+
P.report("unexpected value for AdapterFeature");
404+
return false;
405+
}
406+
407+
feature = *parsedFeature;
408+
return true;
409+
}
410+
307411
json::Value toJSON(const Capabilities &C) {
308412
json::Object result;
309413

@@ -331,6 +435,32 @@ json::Value toJSON(const Capabilities &C) {
331435
return result;
332436
}
333437

438+
bool fromJSON(const llvm::json::Value &Params, Capabilities &C,
439+
llvm::json::Path P) {
440+
auto *Object = Params.getAsObject();
441+
if (!Object) {
442+
P.report("expected an object");
443+
return false;
444+
}
445+
// Check for the presence of supported features.
446+
for (unsigned i = eAdapterFeatureFirst; i <= eAdapterFeatureLast; ++i) {
447+
AdapterFeature feature = static_cast<AdapterFeature>(i);
448+
if (Object->getBoolean(ToString(feature)))
449+
C.supportedFeatures.insert(feature);
450+
}
451+
llvm::json::ObjectMapper O(Params, P);
452+
return O &&
453+
O.mapOptional("exceptionBreakpointFilters",
454+
C.exceptionBreakpointFilters) &&
455+
O.mapOptional("completionTriggerCharacters",
456+
C.completionTriggerCharacters) &&
457+
O.mapOptional("additionalModuleColumns", C.additionalModuleColumns) &&
458+
O.mapOptional("supportedChecksumAlgorithms",
459+
C.supportedChecksumAlgorithms) &&
460+
O.mapOptional("breakpointModes", C.breakpointModes) &&
461+
O.mapOptional("$__lldb_version", C.lldbExtVersion);
462+
}
463+
334464
bool fromJSON(const llvm::json::Value &Params, SteppingGranularity &SG,
335465
llvm::json::Path P) {
336466
auto raw_granularity = Params.getAsString();

lldb/tools/lldb-dap/Protocol/ProtocolTypes.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ enum ChecksumAlgorithm : unsigned {
102102
eChecksumAlgorithmSHA256,
103103
eChecksumAlgorithmTimestamp
104104
};
105+
bool fromJSON(const llvm::json::Value &, ChecksumAlgorithm &, llvm::json::Path);
105106
llvm::json::Value toJSON(const ChecksumAlgorithm &);
106107

107108
/// Describes one or more type of breakpoint a BreakpointMode applies to. This
@@ -237,7 +238,11 @@ enum AdapterFeature : unsigned {
237238
/// The debug adapter supports the `terminateDebuggee` attribute on the
238239
/// `disconnect` request.
239240
eAdapterFeatureTerminateDebuggee,
241+
eAdapterFeatureFirst = eAdapterFeatureANSIStyling,
242+
eAdapterFeatureLast = eAdapterFeatureTerminateDebuggee,
240243
};
244+
bool fromJSON(const llvm::json::Value &, AdapterFeature &, llvm::json::Path);
245+
llvm::json::Value toJSON(const AdapterFeature &);
241246

242247
/// Information about the capabilities of a debug adapter.
243248
struct Capabilities {
@@ -275,13 +280,15 @@ struct Capabilities {
275280

276281
/// @}
277282
};
283+
bool fromJSON(const llvm::json::Value &, Capabilities &, llvm::json::Path);
278284
llvm::json::Value toJSON(const Capabilities &);
279285

280286
enum PresentationHint : unsigned {
281287
ePresentationHintNormal,
282288
ePresentationHintEmphasize,
283-
ePresentationHintDeemphasize,
289+
ePresentationHintDeemphasize
284290
};
291+
bool fromJSON(const llvm::json::Value &, PresentationHint &, llvm::json::Path);
285292
llvm::json::Value toJSON(PresentationHint hint);
286293

287294
/// A `Source` is a descriptor for source code. It is returned from the debug

lldb/unittests/DAP/ProtocolTypesTest.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,100 @@ TEST(ProtocolTypesTest, DataBreakpoint) {
194194
EXPECT_EQ(data_breakpoint_info.hitCondition,
195195
deserialized_data_breakpoint_info->hitCondition);
196196
}
197+
198+
TEST(ProtocolTypesTest, Capabilities) {
199+
Capabilities capabilities;
200+
201+
// Populate supported features.
202+
capabilities.supportedFeatures.insert(eAdapterFeatureANSIStyling);
203+
capabilities.supportedFeatures.insert(
204+
eAdapterFeatureBreakpointLocationsRequest);
205+
206+
// Populate optional fields.
207+
capabilities.exceptionBreakpointFilters = {
208+
{{"filter1", "Filter 1", "Description 1", true, true, "Condition 1"},
209+
{"filter2", "Filter 2", "Description 2", false, false, "Condition 2"}}};
210+
211+
capabilities.completionTriggerCharacters = {".", "->"};
212+
capabilities.additionalModuleColumns = {
213+
{"moduleName", "Module Name", "uppercase", eColumnTypeString, 20}};
214+
capabilities.supportedChecksumAlgorithms = {eChecksumAlgorithmMD5,
215+
eChecksumAlgorithmSHA256};
216+
capabilities.breakpointModes = {{"hardware",
217+
"Hardware Breakpoint",
218+
"Description",
219+
{eBreakpointModeApplicabilitySource}}};
220+
capabilities.lldbExtVersion = "1.0.0";
221+
222+
// Perform roundtrip serialization and deserialization.
223+
llvm::Expected<Capabilities> deserialized_capabilities =
224+
roundtrip(capabilities);
225+
ASSERT_THAT_EXPECTED(deserialized_capabilities, llvm::Succeeded());
226+
227+
// Verify supported features.
228+
EXPECT_EQ(capabilities.supportedFeatures,
229+
deserialized_capabilities->supportedFeatures);
230+
231+
// Verify exception breakpoint filters.
232+
ASSERT_TRUE(
233+
deserialized_capabilities->exceptionBreakpointFilters.has_value());
234+
EXPECT_EQ(capabilities.exceptionBreakpointFilters->size(),
235+
deserialized_capabilities->exceptionBreakpointFilters->size());
236+
for (size_t i = 0; i < capabilities.exceptionBreakpointFilters->size(); ++i) {
237+
const auto &original = capabilities.exceptionBreakpointFilters->at(i);
238+
const auto &deserialized =
239+
deserialized_capabilities->exceptionBreakpointFilters->at(i);
240+
EXPECT_EQ(original.filter, deserialized.filter);
241+
EXPECT_EQ(original.label, deserialized.label);
242+
EXPECT_EQ(original.description, deserialized.description);
243+
EXPECT_EQ(original.defaultState, deserialized.defaultState);
244+
EXPECT_EQ(original.supportsCondition, deserialized.supportsCondition);
245+
EXPECT_EQ(original.conditionDescription, deserialized.conditionDescription);
246+
}
247+
248+
// Verify completion trigger characters.
249+
ASSERT_TRUE(
250+
deserialized_capabilities->completionTriggerCharacters.has_value());
251+
EXPECT_EQ(capabilities.completionTriggerCharacters,
252+
deserialized_capabilities->completionTriggerCharacters);
253+
254+
// Verify additional module columns.
255+
ASSERT_TRUE(deserialized_capabilities->additionalModuleColumns.has_value());
256+
EXPECT_EQ(capabilities.additionalModuleColumns->size(),
257+
deserialized_capabilities->additionalModuleColumns->size());
258+
for (size_t i = 0; i < capabilities.additionalModuleColumns->size(); ++i) {
259+
const auto &original = capabilities.additionalModuleColumns->at(i);
260+
const auto &deserialized =
261+
deserialized_capabilities->additionalModuleColumns->at(i);
262+
EXPECT_EQ(original.attributeName, deserialized.attributeName);
263+
EXPECT_EQ(original.label, deserialized.label);
264+
EXPECT_EQ(original.format, deserialized.format);
265+
EXPECT_EQ(original.type, deserialized.type);
266+
EXPECT_EQ(original.width, deserialized.width);
267+
}
268+
269+
// Verify supported checksum algorithms.
270+
ASSERT_TRUE(
271+
deserialized_capabilities->supportedChecksumAlgorithms.has_value());
272+
EXPECT_EQ(capabilities.supportedChecksumAlgorithms,
273+
deserialized_capabilities->supportedChecksumAlgorithms);
274+
275+
// Verify breakpoint modes.
276+
ASSERT_TRUE(deserialized_capabilities->breakpointModes.has_value());
277+
EXPECT_EQ(capabilities.breakpointModes->size(),
278+
deserialized_capabilities->breakpointModes->size());
279+
for (size_t i = 0; i < capabilities.breakpointModes->size(); ++i) {
280+
const auto &original = capabilities.breakpointModes->at(i);
281+
const auto &deserialized =
282+
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+
ASSERT_TRUE(deserialized_capabilities->lldbExtVersion.has_value());
291+
EXPECT_EQ(capabilities.lldbExtVersion,
292+
deserialized_capabilities->lldbExtVersion);
293+
}

0 commit comments

Comments
 (0)