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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Protocol/ProtocolTypes.h"
10#include "Protocol/ProtocolEvents.h"
11#include "Protocol/ProtocolRequests.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/Support/JSON.h"
14#include "llvm/Testing/Support/Error.h"
15#include "gmock/gmock.h"
16#include "gtest/gtest.h"
17#include <optional>
18
19using namespace llvm;
20using namespace lldb;
21using namespace lldb_dap;
22using namespace lldb_dap::protocol;
23using llvm::json::parse;
24using llvm::json::Value;
25
26/// Returns a pretty printed json string of a `llvm::json::Value`.
27static std::string pp(const json::Value &E) {
28 return formatv(Fmt: "{0:2}", Vals: E).str();
29}
30
31template <typename T> static llvm::Expected<T> roundtrip(const T &input) {
32 llvm::json::Value value = toJSON(input);
33 llvm::json::Path::Root root;
34 T output;
35 if (!fromJSON(value, output, root))
36 return root.getError();
37 return output;
38}
39
40TEST(ProtocolTypesTest, ExceptionBreakpointsFilter) {
41 ExceptionBreakpointsFilter filter;
42 filter.filter = "testFilter";
43 filter.label = "Test Filter";
44 filter.description = "This is a test filter";
45 filter.defaultState = true;
46 filter.supportsCondition = true;
47 filter.conditionDescription = "Condition for test filter";
48
49 llvm::Expected<ExceptionBreakpointsFilter> deserialized_filter =
50 roundtrip(input: filter);
51 ASSERT_THAT_EXPECTED(deserialized_filter, llvm::Succeeded());
52
53 EXPECT_EQ(filter.filter, deserialized_filter->filter);
54 EXPECT_EQ(filter.label, deserialized_filter->label);
55 EXPECT_EQ(filter.description, deserialized_filter->description);
56 EXPECT_EQ(filter.defaultState, deserialized_filter->defaultState);
57 EXPECT_EQ(filter.supportsCondition, deserialized_filter->supportsCondition);
58 EXPECT_EQ(filter.conditionDescription,
59 deserialized_filter->conditionDescription);
60}
61
62TEST(ProtocolTypesTest, Source) {
63 Source source;
64 source.name = "testName";
65 source.path = "/path/to/source";
66 source.sourceReference = 12345;
67 source.presentationHint = Source::eSourcePresentationHintEmphasize;
68
69 llvm::Expected<Source> deserialized_source = roundtrip(input: source);
70 ASSERT_THAT_EXPECTED(deserialized_source, llvm::Succeeded());
71
72 EXPECT_EQ(source.name, deserialized_source->name);
73 EXPECT_EQ(source.path, deserialized_source->path);
74 EXPECT_EQ(source.sourceReference, deserialized_source->sourceReference);
75 EXPECT_EQ(source.presentationHint, deserialized_source->presentationHint);
76}
77
78TEST(ProtocolTypesTest, ColumnDescriptor) {
79 ColumnDescriptor column;
80 column.attributeName = "moduleName";
81 column.label = "Module Name";
82 column.format = "uppercase";
83 column.type = eColumnTypeString;
84 column.width = 20;
85
86 llvm::Expected<ColumnDescriptor> deserialized_column = roundtrip(input: column);
87 ASSERT_THAT_EXPECTED(deserialized_column, llvm::Succeeded());
88
89 EXPECT_EQ(column.attributeName, deserialized_column->attributeName);
90 EXPECT_EQ(column.label, deserialized_column->label);
91 EXPECT_EQ(column.format, deserialized_column->format);
92 EXPECT_EQ(column.type, deserialized_column->type);
93 EXPECT_EQ(column.width, deserialized_column->width);
94}
95
96TEST(ProtocolTypesTest, BreakpointMode) {
97 BreakpointMode mode;
98 mode.mode = "testMode";
99 mode.label = "Test Mode";
100 mode.description = "This is a test mode";
101 mode.appliesTo = {eBreakpointModeApplicabilitySource,
102 eBreakpointModeApplicabilityException};
103
104 llvm::Expected<BreakpointMode> deserialized_mode = roundtrip(input: mode);
105 ASSERT_THAT_EXPECTED(deserialized_mode, llvm::Succeeded());
106
107 EXPECT_EQ(mode.mode, deserialized_mode->mode);
108 EXPECT_EQ(mode.label, deserialized_mode->label);
109 EXPECT_EQ(mode.description, deserialized_mode->description);
110 EXPECT_EQ(mode.appliesTo, deserialized_mode->appliesTo);
111}
112
113TEST(ProtocolTypesTest, Breakpoint) {
114 Breakpoint breakpoint;
115 breakpoint.id = 42;
116 breakpoint.verified = true;
117 breakpoint.message = "Breakpoint set successfully";
118 breakpoint.source = Source{.name: "test.cpp", .path: "/path/to/test.cpp", .sourceReference: 123,
119 .presentationHint: Source::eSourcePresentationHintNormal};
120 breakpoint.line = 10;
121 breakpoint.column = 5;
122 breakpoint.endLine = 15;
123 breakpoint.endColumn = 10;
124 breakpoint.instructionReference = "0x12345678";
125 breakpoint.offset = 4;
126 breakpoint.reason = BreakpointReason::eBreakpointReasonPending;
127
128 llvm::Expected<Breakpoint> deserialized_breakpoint = roundtrip(input: breakpoint);
129 ASSERT_THAT_EXPECTED(deserialized_breakpoint, llvm::Succeeded());
130
131 EXPECT_EQ(breakpoint.id, deserialized_breakpoint->id);
132 EXPECT_EQ(breakpoint.verified, deserialized_breakpoint->verified);
133 EXPECT_EQ(breakpoint.message, deserialized_breakpoint->message);
134 EXPECT_EQ(breakpoint.source->name, deserialized_breakpoint->source->name);
135 EXPECT_EQ(breakpoint.source->path, deserialized_breakpoint->source->path);
136 EXPECT_EQ(breakpoint.source->sourceReference,
137 deserialized_breakpoint->source->sourceReference);
138 EXPECT_EQ(breakpoint.source->presentationHint,
139 deserialized_breakpoint->source->presentationHint);
140 EXPECT_EQ(breakpoint.line, deserialized_breakpoint->line);
141 EXPECT_EQ(breakpoint.column, deserialized_breakpoint->column);
142 EXPECT_EQ(breakpoint.endLine, deserialized_breakpoint->endLine);
143 EXPECT_EQ(breakpoint.endColumn, deserialized_breakpoint->endColumn);
144 EXPECT_EQ(breakpoint.instructionReference,
145 deserialized_breakpoint->instructionReference);
146 EXPECT_EQ(breakpoint.offset, deserialized_breakpoint->offset);
147 EXPECT_EQ(breakpoint.reason, deserialized_breakpoint->reason);
148}
149
150TEST(ProtocolTypesTest, SourceBreakpoint) {
151 SourceBreakpoint source_breakpoint;
152 source_breakpoint.line = 42;
153 source_breakpoint.column = 5;
154 source_breakpoint.condition = "x > 10";
155 source_breakpoint.hitCondition = "5";
156 source_breakpoint.logMessage = "Breakpoint hit at line 42";
157 source_breakpoint.mode = "hardware";
158
159 llvm::Expected<SourceBreakpoint> deserialized_source_breakpoint =
160 roundtrip(input: source_breakpoint);
161 ASSERT_THAT_EXPECTED(deserialized_source_breakpoint, llvm::Succeeded());
162
163 EXPECT_EQ(source_breakpoint.line, deserialized_source_breakpoint->line);
164 EXPECT_EQ(source_breakpoint.column, deserialized_source_breakpoint->column);
165 EXPECT_EQ(source_breakpoint.condition,
166 deserialized_source_breakpoint->condition);
167 EXPECT_EQ(source_breakpoint.hitCondition,
168 deserialized_source_breakpoint->hitCondition);
169 EXPECT_EQ(source_breakpoint.logMessage,
170 deserialized_source_breakpoint->logMessage);
171 EXPECT_EQ(source_breakpoint.mode, deserialized_source_breakpoint->mode);
172}
173
174TEST(ProtocolTypesTest, FunctionBreakpoint) {
175 FunctionBreakpoint function_breakpoint;
176 function_breakpoint.name = "myFunction";
177 function_breakpoint.condition = "x == 0";
178 function_breakpoint.hitCondition = "3";
179
180 llvm::Expected<FunctionBreakpoint> deserialized_function_breakpoint =
181 roundtrip(input: function_breakpoint);
182 ASSERT_THAT_EXPECTED(deserialized_function_breakpoint, llvm::Succeeded());
183
184 EXPECT_EQ(function_breakpoint.name, deserialized_function_breakpoint->name);
185 EXPECT_EQ(function_breakpoint.condition,
186 deserialized_function_breakpoint->condition);
187 EXPECT_EQ(function_breakpoint.hitCondition,
188 deserialized_function_breakpoint->hitCondition);
189}
190
191TEST(ProtocolTypesTest, DataBreakpoint) {
192 DataBreakpoint data_breakpoint_info;
193 data_breakpoint_info.dataId = "variable1";
194 data_breakpoint_info.accessType = eDataBreakpointAccessTypeReadWrite;
195 data_breakpoint_info.condition = "x > 100";
196 data_breakpoint_info.hitCondition = "10";
197
198 llvm::Expected<DataBreakpoint> deserialized_data_breakpoint_info =
199 roundtrip(input: data_breakpoint_info);
200 ASSERT_THAT_EXPECTED(deserialized_data_breakpoint_info, llvm::Succeeded());
201
202 EXPECT_EQ(data_breakpoint_info.dataId,
203 deserialized_data_breakpoint_info->dataId);
204 EXPECT_EQ(data_breakpoint_info.accessType,
205 deserialized_data_breakpoint_info->accessType);
206 EXPECT_EQ(data_breakpoint_info.condition,
207 deserialized_data_breakpoint_info->condition);
208 EXPECT_EQ(data_breakpoint_info.hitCondition,
209 deserialized_data_breakpoint_info->hitCondition);
210}
211
212TEST(ProtocolTypesTest, Capabilities) {
213 Capabilities capabilities;
214
215 // Populate supported features.
216 capabilities.supportedFeatures.insert(V: eAdapterFeatureANSIStyling);
217 capabilities.supportedFeatures.insert(
218 V: eAdapterFeatureBreakpointLocationsRequest);
219
220 // Populate optional fields.
221 capabilities.exceptionBreakpointFilters = {
222 {{.filter: "filter1", .label: "Filter 1", .description: "Description 1", .defaultState: true, .supportsCondition: true, .conditionDescription: "Condition 1"},
223 {.filter: "filter2", .label: "Filter 2", .description: "Description 2", .defaultState: false, .supportsCondition: false, .conditionDescription: "Condition 2"}}};
224
225 capabilities.completionTriggerCharacters = {".", "->"};
226 capabilities.additionalModuleColumns = {
227 {.attributeName: "moduleName", .label: "Module Name", .format: "uppercase", .type: eColumnTypeString, .width: 20}};
228 capabilities.supportedChecksumAlgorithms = {eChecksumAlgorithmMD5,
229 eChecksumAlgorithmSHA256};
230 capabilities.breakpointModes = {{.mode: "hardware",
231 .label: "Hardware Breakpoint",
232 .description: "Description",
233 .appliesTo: {eBreakpointModeApplicabilitySource}}};
234 capabilities.lldbExtVersion = "1.0.0";
235
236 // Perform roundtrip serialization and deserialization.
237 llvm::Expected<Capabilities> deserialized_capabilities =
238 roundtrip(input: capabilities);
239 ASSERT_THAT_EXPECTED(deserialized_capabilities, llvm::Succeeded());
240
241 // Verify supported features.
242 EXPECT_EQ(capabilities.supportedFeatures,
243 deserialized_capabilities->supportedFeatures);
244
245 // Verify exception breakpoint filters.
246 ASSERT_TRUE(
247 deserialized_capabilities->exceptionBreakpointFilters.has_value());
248 EXPECT_EQ(capabilities.exceptionBreakpointFilters->size(),
249 deserialized_capabilities->exceptionBreakpointFilters->size());
250 for (size_t i = 0; i < capabilities.exceptionBreakpointFilters->size(); ++i) {
251 const auto &original = capabilities.exceptionBreakpointFilters->at(n: i);
252 const auto &deserialized =
253 deserialized_capabilities->exceptionBreakpointFilters->at(n: i);
254 EXPECT_EQ(original.filter, deserialized.filter);
255 EXPECT_EQ(original.label, deserialized.label);
256 EXPECT_EQ(original.description, deserialized.description);
257 EXPECT_EQ(original.defaultState, deserialized.defaultState);
258 EXPECT_EQ(original.supportsCondition, deserialized.supportsCondition);
259 EXPECT_EQ(original.conditionDescription, deserialized.conditionDescription);
260 }
261
262 // Verify completion trigger characters.
263 ASSERT_TRUE(
264 deserialized_capabilities->completionTriggerCharacters.has_value());
265 EXPECT_EQ(capabilities.completionTriggerCharacters,
266 deserialized_capabilities->completionTriggerCharacters);
267
268 // Verify additional module columns.
269 ASSERT_TRUE(deserialized_capabilities->additionalModuleColumns.has_value());
270 EXPECT_EQ(capabilities.additionalModuleColumns->size(),
271 deserialized_capabilities->additionalModuleColumns->size());
272 for (size_t i = 0; i < capabilities.additionalModuleColumns->size(); ++i) {
273 const auto &original = capabilities.additionalModuleColumns->at(n: i);
274 const auto &deserialized =
275 deserialized_capabilities->additionalModuleColumns->at(n: i);
276 EXPECT_EQ(original.attributeName, deserialized.attributeName);
277 EXPECT_EQ(original.label, deserialized.label);
278 EXPECT_EQ(original.format, deserialized.format);
279 EXPECT_EQ(original.type, deserialized.type);
280 EXPECT_EQ(original.width, deserialized.width);
281 }
282
283 // Verify supported checksum algorithms.
284 ASSERT_TRUE(
285 deserialized_capabilities->supportedChecksumAlgorithms.has_value());
286 EXPECT_EQ(capabilities.supportedChecksumAlgorithms,
287 deserialized_capabilities->supportedChecksumAlgorithms);
288
289 // Verify breakpoint modes.
290 ASSERT_TRUE(deserialized_capabilities->breakpointModes.has_value());
291 EXPECT_EQ(capabilities.breakpointModes->size(),
292 deserialized_capabilities->breakpointModes->size());
293 for (size_t i = 0; i < capabilities.breakpointModes->size(); ++i) {
294 const auto &original = capabilities.breakpointModes->at(n: i);
295 const auto &deserialized =
296 deserialized_capabilities->breakpointModes->at(n: i);
297 EXPECT_EQ(original.mode, deserialized.mode);
298 EXPECT_EQ(original.label, deserialized.label);
299 EXPECT_EQ(original.description, deserialized.description);
300 EXPECT_EQ(original.appliesTo, deserialized.appliesTo);
301 }
302
303 // Verify lldb extension version.
304 ASSERT_TRUE(deserialized_capabilities->lldbExtVersion.has_value());
305 EXPECT_EQ(capabilities.lldbExtVersion,
306 deserialized_capabilities->lldbExtVersion);
307}
308
309TEST(ProtocolTypesTest, Scope) {
310 Scope scope;
311 scope.name = "Locals";
312 scope.presentationHint = Scope::eScopePresentationHintLocals;
313 scope.variablesReference = 1;
314 scope.namedVariables = 2;
315 scope.indexedVariables = std::nullopt;
316 scope.expensive = false;
317 scope.line = 2;
318 scope.column = 3;
319 scope.endLine = 10;
320 scope.endColumn = 20;
321
322 Source source;
323 source.name = "testName";
324 source.path = "/path/to/source";
325 source.sourceReference = 12345;
326 source.presentationHint = Source::eSourcePresentationHintNormal;
327 scope.source = source;
328
329 llvm::Expected<Scope> deserialized_scope = roundtrip(input: scope);
330 ASSERT_THAT_EXPECTED(deserialized_scope, llvm::Succeeded());
331 EXPECT_EQ(scope.name, deserialized_scope->name);
332 EXPECT_EQ(scope.presentationHint, deserialized_scope->presentationHint);
333 EXPECT_EQ(scope.variablesReference, deserialized_scope->variablesReference);
334 EXPECT_EQ(scope.namedVariables, deserialized_scope->namedVariables);
335 EXPECT_EQ(scope.indexedVariables, deserialized_scope->indexedVariables);
336 EXPECT_EQ(scope.expensive, deserialized_scope->expensive);
337 EXPECT_EQ(scope.line, deserialized_scope->line);
338 EXPECT_EQ(scope.column, deserialized_scope->column);
339 EXPECT_EQ(scope.endLine, deserialized_scope->endLine);
340 EXPECT_EQ(scope.endColumn, deserialized_scope->endColumn);
341
342 EXPECT_THAT(deserialized_scope->source.has_value(), true);
343 const Source &deserialized_source = deserialized_scope->source.value();
344
345 EXPECT_EQ(source.path, deserialized_source.path);
346 EXPECT_EQ(source.sourceReference, deserialized_source.sourceReference);
347 EXPECT_EQ(source.presentationHint, deserialized_source.presentationHint);
348}
349
350TEST(ProtocolTypesTest, PresentationHint) {
351 // Test all PresentationHint values.
352 std::vector<std::pair<Source::PresentationHint, llvm::StringRef>> test_cases =
353 {{Source::eSourcePresentationHintNormal, "normal"},
354 {Source::eSourcePresentationHintEmphasize, "emphasize"},
355 {Source::eSourcePresentationHintDeemphasize, "deemphasize"}};
356
357 for (const auto &test_case : test_cases) {
358 // Serialize the PresentationHint to JSON.
359 llvm::json::Value serialized = toJSON(test_case.first);
360 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
361 EXPECT_EQ(serialized.getAsString(), test_case.second);
362
363 // Deserialize the JSON back to PresentationHint.
364 Source::PresentationHint deserialized;
365 llvm::json::Path::Root root;
366 ASSERT_TRUE(fromJSON(serialized, deserialized, root))
367 << llvm::toString(E: root.getError());
368 EXPECT_EQ(deserialized, test_case.first);
369 }
370
371 // Test invalid value.
372 llvm::json::Value invalid_value = "invalid_hint";
373 Source::PresentationHint deserialized_invalid;
374 llvm::json::Path::Root root;
375 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
376}
377
378TEST(ProtocolTypesTest, SteppingGranularity) {
379 // Test all SteppingGranularity values.
380 std::vector<std::pair<SteppingGranularity, llvm::StringRef>> test_cases = {
381 {eSteppingGranularityStatement, "statement"},
382 {eSteppingGranularityLine, "line"},
383 {eSteppingGranularityInstruction, "instruction"}};
384
385 for (const auto &test_case : test_cases) {
386 // Serialize the SteppingGranularity to JSON.
387 llvm::json::Value serialized = toJSON(test_case.first);
388 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
389 EXPECT_EQ(serialized.getAsString(), test_case.second);
390
391 // Deserialize the JSON back to SteppingGranularity.
392 SteppingGranularity deserialized;
393 llvm::json::Path::Root root;
394 ASSERT_TRUE(fromJSON(serialized, deserialized, root))
395 << llvm::toString(E: root.getError());
396 EXPECT_EQ(deserialized, test_case.first);
397 }
398
399 // Test invalid value.
400 llvm::json::Value invalid_value = "invalid_granularity";
401 SteppingGranularity deserialized_invalid;
402 llvm::json::Path::Root root;
403 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
404}
405
406TEST(ProtocolTypesTest, BreakpointReason) {
407 // Test all BreakpointReason values.
408 std::vector<std::pair<BreakpointReason, llvm::StringRef>> test_cases = {
409 {BreakpointReason::eBreakpointReasonPending, "pending"},
410 {BreakpointReason::eBreakpointReasonFailed, "failed"}};
411
412 for (const auto &test_case : test_cases) {
413 // Serialize the BreakpointReason to JSON.
414 llvm::json::Value serialized = toJSON(test_case.first);
415 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
416 EXPECT_EQ(serialized.getAsString(), test_case.second);
417
418 // Deserialize the JSON back to BreakpointReason.
419 BreakpointReason deserialized;
420 llvm::json::Path::Root root;
421 ASSERT_TRUE(fromJSON(serialized, deserialized, root))
422 << llvm::toString(E: root.getError());
423 EXPECT_EQ(deserialized, test_case.first);
424 }
425
426 // Test invalid value.
427 llvm::json::Value invalid_value = "invalid_reason";
428 BreakpointReason deserialized_invalid;
429 llvm::json::Path::Root root;
430 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
431}
432
433TEST(ProtocolTypesTest, DataBreakpointAccessType) {
434 // Test all DataBreakpointAccessType values.
435 std::vector<std::pair<DataBreakpointAccessType, llvm::StringRef>> test_cases =
436 {{eDataBreakpointAccessTypeRead, "read"},
437 {eDataBreakpointAccessTypeWrite, "write"},
438 {eDataBreakpointAccessTypeReadWrite, "readWrite"}};
439
440 for (const auto &test_case : test_cases) {
441 // Serialize the DataBreakpointAccessType to JSON.
442 llvm::json::Value serialized = toJSON(test_case.first);
443 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
444 EXPECT_EQ(serialized.getAsString(), test_case.second);
445
446 // Deserialize the JSON back to DataBreakpointAccessType.
447 DataBreakpointAccessType deserialized;
448 llvm::json::Path::Root root;
449 ASSERT_TRUE(fromJSON(serialized, deserialized, root))
450 << llvm::toString(E: root.getError());
451 EXPECT_EQ(deserialized, test_case.first);
452 }
453
454 // Test invalid value
455 llvm::json::Value invalid_value = "invalid_access_type";
456 DataBreakpointAccessType deserialized_invalid;
457 llvm::json::Path::Root root;
458 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
459}
460
461TEST(ProtocolTypesTest, ColumnType) {
462 // Test all ColumnType values.
463 std::vector<std::pair<ColumnType, llvm::StringRef>> test_cases = {
464 {eColumnTypeString, "string"},
465 {eColumnTypeNumber, "number"},
466 {eColumnTypeBoolean, "boolean"},
467 {eColumnTypeTimestamp, "unixTimestampUTC"}};
468
469 for (const auto &test_case : test_cases) {
470 // Serialize the ColumnType to JSON.
471 llvm::json::Value serialized = toJSON(test_case.first);
472 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
473 EXPECT_EQ(serialized.getAsString(), test_case.second);
474
475 // Deserialize the JSON back to ColumnType.
476 ColumnType deserialized;
477 llvm::json::Path::Root root;
478 ASSERT_TRUE(fromJSON(serialized, deserialized, root))
479 << llvm::toString(E: root.getError());
480 EXPECT_EQ(deserialized, test_case.first);
481 }
482
483 // Test invalid value.
484 llvm::json::Value invalid_value = "invalid_column_type";
485 ColumnType deserialized_invalid;
486 llvm::json::Path::Root root;
487 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
488}
489
490TEST(ProtocolTypesTest, BreakpointModeApplicability) {
491 // Test all BreakpointModeApplicability values.
492 std::vector<std::pair<BreakpointModeApplicability, llvm::StringRef>>
493 test_cases = {{eBreakpointModeApplicabilitySource, "source"},
494 {eBreakpointModeApplicabilityException, "exception"},
495 {eBreakpointModeApplicabilityData, "data"},
496 {eBreakpointModeApplicabilityInstruction, "instruction"}};
497
498 for (const auto &test_case : test_cases) {
499 // Serialize the BreakpointModeApplicability to JSON.
500 llvm::json::Value serialized = toJSON(test_case.first);
501 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
502 EXPECT_EQ(serialized.getAsString(), test_case.second);
503
504 // Deserialize the JSON back to BreakpointModeApplicability.
505 BreakpointModeApplicability deserialized;
506 llvm::json::Path::Root root;
507 ASSERT_TRUE(fromJSON(serialized, deserialized, root))
508 << llvm::toString(E: root.getError());
509 EXPECT_EQ(deserialized, test_case.first);
510 }
511
512 // Test invalid value.
513 llvm::json::Value invalid_value = "invalid_applicability";
514 BreakpointModeApplicability deserialized_invalid;
515 llvm::json::Path::Root root;
516 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
517}
518
519TEST(ProtocolTypesTest, ChecksumAlgorithm) {
520 // Test all ChecksumAlgorithm values.
521 std::vector<std::pair<ChecksumAlgorithm, llvm::StringRef>> test_cases = {
522 {eChecksumAlgorithmMD5, "MD5"},
523 {eChecksumAlgorithmSHA1, "SHA1"},
524 {eChecksumAlgorithmSHA256, "SHA256"},
525 {eChecksumAlgorithmTimestamp, "timestamp"}};
526
527 for (const auto &test_case : test_cases) {
528 // Serialize the ChecksumAlgorithm to JSON.
529 llvm::json::Value serialized = toJSON(test_case.first);
530 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
531 EXPECT_EQ(serialized.getAsString(), test_case.second);
532
533 // Deserialize the JSON back to ChecksumAlgorithm.
534 ChecksumAlgorithm deserialized;
535 llvm::json::Path::Root root;
536 ASSERT_TRUE(fromJSON(serialized, deserialized, root))
537 << llvm::toString(E: root.getError());
538 EXPECT_EQ(deserialized, test_case.first);
539 }
540
541 // Test invalid value.
542 llvm::json::Value invalid_value = "invalid_algorithm";
543 ChecksumAlgorithm deserialized_invalid;
544 llvm::json::Path::Root root;
545 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
546}
547
548TEST(ProtocolTypesTest, DisassembledInstructionPresentationHint) {
549 // Test all PresentationHint values.
550 std::vector<
551 std::pair<DisassembledInstruction::PresentationHint, llvm::StringRef>>
552 test_cases = {{DisassembledInstruction::
553 eDisassembledInstructionPresentationHintNormal,
554 "normal"},
555 {DisassembledInstruction::
556 eDisassembledInstructionPresentationHintInvalid,
557 "invalid"}};
558
559 for (const auto &test_case : test_cases) {
560 // Serialize the PresentationHint to JSON.
561 llvm::json::Value serialized = toJSON(test_case.first);
562 ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
563 EXPECT_EQ(serialized.getAsString(), test_case.second);
564
565 // Deserialize the JSON back to PresentationHint.
566 DisassembledInstruction::PresentationHint deserialized;
567 llvm::json::Path::Root root;
568 ASSERT_TRUE(fromJSON(serialized, deserialized, root))
569 << llvm::toString(E: root.getError());
570 EXPECT_EQ(deserialized, test_case.first);
571 }
572
573 // Test invalid value.
574 llvm::json::Value invalid_value = "invalid_hint";
575 DisassembledInstruction::PresentationHint deserialized_invalid;
576 llvm::json::Path::Root root;
577 EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
578}
579
580TEST(ProtocolTypesTest, DisassembledInstruction) {
581 DisassembledInstruction instruction;
582 instruction.address = 0x12345678;
583 instruction.instructionBytes = "0F 1F 00";
584 instruction.instruction = "mov eax, ebx";
585 instruction.symbol = "main";
586 instruction.location = Source{.name: "test.cpp", .path: "/path/to/test.cpp", .sourceReference: 123,
587 .presentationHint: Source::eSourcePresentationHintNormal};
588 instruction.line = 10;
589 instruction.column = 5;
590 instruction.endLine = 15;
591 instruction.endColumn = 10;
592 instruction.presentationHint =
593 DisassembledInstruction::eDisassembledInstructionPresentationHintNormal;
594
595 StringLiteral json = R"({
596 "address": "0x12345678",
597 "column": 5,
598 "endColumn": 10,
599 "endLine": 15,
600 "instruction": "mov eax, ebx",
601 "instructionBytes": "0F 1F 00",
602 "line": 10,
603 "location": {
604 "name": "test.cpp",
605 "path": "/path/to/test.cpp",
606 "presentationHint": "normal",
607 "sourceReference": 123
608 },
609 "presentationHint": "normal",
610 "symbol": "main"
611})";
612
613 // Validate toJSON
614 EXPECT_EQ(json, pp(instruction));
615
616 // Validate fromJSON
617 EXPECT_THAT_EXPECTED(parse<DisassembledInstruction>(json),
618 HasValue(Value(instruction)));
619 // Validate parsing errors
620 EXPECT_THAT_EXPECTED(
621 parse<DisassembledInstruction>(R"({"address":1})",
622 "disassemblyInstruction"),
623 FailedWithMessage("expected string at disassemblyInstruction.address"));
624 EXPECT_THAT_EXPECTED(parse<DisassembledInstruction>(R"({"address":"-1"})",
625 "disassemblyInstruction"),
626 FailedWithMessage("expected string encoded uint64_t at "
627 "disassemblyInstruction.address"));
628 EXPECT_THAT_EXPECTED(parse<DisassembledInstruction>(
629 R"({"address":"0xfffffffffffffffffffffffffff"})",
630 "disassemblyInstruction"),
631 FailedWithMessage("expected string encoded uint64_t at "
632 "disassemblyInstruction.address"));
633}
634
635TEST(ProtocolTypesTest, Thread) {
636 const Thread thread{.id: 1, .name: "thr1"};
637 const StringRef json = R"({
638 "id": 1,
639 "name": "thr1"
640})";
641 // Validate toJSON
642 EXPECT_EQ(json, pp(thread));
643 // Validate fromJSON
644 EXPECT_THAT_EXPECTED(parse<Thread>(json), HasValue(Value(thread)));
645 // Validate parsing errors
646 EXPECT_THAT_EXPECTED(parse<Thread>(R"({"id":1})", "thread"),
647 FailedWithMessage("missing value at thread.name"));
648 EXPECT_THAT_EXPECTED(parse<Thread>(R"({"id":"one"})", "thread"),
649 FailedWithMessage("expected uint64_t at thread.id"));
650 EXPECT_THAT_EXPECTED(parse<Thread>(R"({"id":1,"name":false})", "thread"),
651 FailedWithMessage("expected string at thread.name"));
652}
653
654TEST(ProtocolTypesTest, ThreadResponseBody) {
655 const ThreadsResponseBody body{.threads: {{.id: 1, .name: "thr1"}, {.id: 2, .name: "thr2"}}};
656 const StringRef json = R"({
657 "threads": [
658 {
659 "id": 1,
660 "name": "thr1"
661 },
662 {
663 "id": 2,
664 "name": "thr2"
665 }
666 ]
667})";
668 // Validate toJSON
669 EXPECT_EQ(json, pp(body));
670}
671
672TEST(ProtocolTypesTest, CapabilitiesEventBody) {
673 Capabilities capabilities;
674 capabilities.supportedFeatures = {
675 eAdapterFeatureANSIStyling,
676 eAdapterFeatureBreakpointLocationsRequest,
677 };
678 CapabilitiesEventBody body;
679 body.capabilities = capabilities;
680 StringRef json = R"({
681 "capabilities": {
682 "supportsANSIStyling": true,
683 "supportsBreakpointLocationsRequest": true
684 }
685})";
686 // Validate toJSON
687 EXPECT_EQ(json, pp(body));
688}
689

source code of lldb/unittests/DAP/ProtocolTypesTest.cpp