Author: Jonas Devlieghere
Date: 2025-05-13T12:23:22-07:00
New Revision: 81932945d76a49a4dd222da39afbc18435e66fb0

URL: 
https://github.com/llvm/llvm-project/commit/81932945d76a49a4dd222da39afbc18435e66fb0
DIFF: 
https://github.com/llvm/llvm-project/commit/81932945d76a49a4dd222da39afbc18435e66fb0.diff

LOG: [lldb-dap] Add unit test for ColumnDescriptor, BreakpointMode and 
Breakpoint (#139627)

Implement `fromJSON` for `ColumnDescriptor`, `BreakpointMode` and
`Breakpoint` and use it to implement the corresponding unit tests.

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 c9cab350f9f12..7c2f4b20f4956 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -94,6 +94,28 @@ json::Value toJSON(const ExceptionBreakpointsFilter &EBF) {
   return result;
 }
 
+bool fromJSON(const json::Value &Params, ColumnType &CT, json::Path P) {
+  auto rawColumnType = Params.getAsString();
+  if (!rawColumnType) {
+    P.report("expected a string");
+    return false;
+  }
+  std::optional<ColumnType> columnType =
+      StringSwitch<std::optional<ColumnType>>(*rawColumnType)
+          .Case("string", eColumnTypeString)
+          .Case("number", eColumnTypeNumber)
+          .Case("boolean", eColumnTypeBoolean)
+          .Case("unixTimestampUTC ", eColumnTypeTimestamp)
+          .Default(std::nullopt);
+  if (!columnType) {
+    P.report("unexpected value, expected 'string', 'number',  'boolean', or "
+             "'unixTimestampUTC'");
+    return false;
+  }
+  CT = *columnType;
+  return true;
+}
+
 json::Value toJSON(const ColumnType &T) {
   switch (T) {
   case eColumnTypeString:
@@ -108,6 +130,14 @@ json::Value toJSON(const ColumnType &T) {
   llvm_unreachable("unhandled column type.");
 }
 
+bool fromJSON(const llvm::json::Value &Params, ColumnDescriptor &CD,
+              llvm::json::Path P) {
+  llvm::json::ObjectMapper O(Params, P);
+  return O && O.map("attributeName", CD.attributeName) &&
+         O.map("label", CD.label) && O.mapOptional("format", CD.format) &&
+         O.mapOptional("type", CD.type) && O.mapOptional("width", CD.width);
+}
+
 json::Value toJSON(const ColumnDescriptor &CD) {
   json::Object result{{"attributeName", CD.attributeName}, {"label", 
CD.label}};
 
@@ -149,6 +179,30 @@ json::Value toJSON(const BreakpointModeApplicability &BMA) 
{
   llvm_unreachable("unhandled breakpoint mode applicability.");
 }
 
+bool fromJSON(const llvm::json::Value &Params, BreakpointModeApplicability 
&BMA,
+              llvm::json::Path P) {
+  auto rawApplicability = Params.getAsString();
+  if (!rawApplicability) {
+    P.report("expected a string");
+    return false;
+  }
+  std::optional<BreakpointModeApplicability> applicability =
+      llvm::StringSwitch<std::optional<BreakpointModeApplicability>>(
+          *rawApplicability)
+          .Case("source", eBreakpointModeApplicabilitySource)
+          .Case("exception", eBreakpointModeApplicabilityException)
+          .Case("data", eBreakpointModeApplicabilityData)
+          .Case("instruction", eBreakpointModeApplicabilityInstruction)
+          .Default(std::nullopt);
+  if (!applicability) {
+    P.report("unexpected value, expected 'source', 'exception', 'data', or "
+             "'instruction'");
+    return false;
+  }
+  BMA = *applicability;
+  return true;
+}
+
 json::Value toJSON(const BreakpointMode &BM) {
   json::Object result{
       {"mode", BM.mode},
@@ -162,6 +216,14 @@ json::Value toJSON(const BreakpointMode &BM) {
   return result;
 }
 
+bool fromJSON(const llvm::json::Value &Params, BreakpointMode &BM,
+              llvm::json::Path P) {
+  llvm::json::ObjectMapper O(Params, P);
+  return O && O.map("mode", BM.mode) && O.map("label", BM.label) &&
+         O.mapOptional("description", BM.description) &&
+         O.map("appliesTo", BM.appliesTo);
+}
+
 static llvm::StringLiteral ToString(AdapterFeature feature) {
   switch (feature) {
   case eAdapterFeatureANSIStyling:
@@ -320,6 +382,26 @@ llvm::json::Value toJSON(const BreakpointReason &BR) {
   llvm_unreachable("unhandled breakpoint reason.");
 }
 
+bool fromJSON(const llvm::json::Value &Params, BreakpointReason &BR,
+              llvm::json::Path P) {
+  auto rawReason = Params.getAsString();
+  if (!rawReason) {
+    P.report("expected a string");
+    return false;
+  }
+  std::optional<BreakpointReason> reason =
+      llvm::StringSwitch<std::optional<BreakpointReason>>(*rawReason)
+          .Case("pending", BreakpointReason::eBreakpointReasonPending)
+          .Case("failed", BreakpointReason::eBreakpointReasonFailed)
+          .Default(std::nullopt);
+  if (!reason) {
+    P.report("unexpected value, expected 'pending' or 'failed'");
+    return false;
+  }
+  BR = *reason;
+  return true;
+}
+
 json::Value toJSON(const Breakpoint &BP) {
   json::Object result{{"verified", BP.verified}};
 
@@ -348,6 +430,20 @@ json::Value toJSON(const Breakpoint &BP) {
   return result;
 }
 
+bool fromJSON(const llvm::json::Value &Params, Breakpoint &BP,
+              llvm::json::Path P) {
+  llvm::json::ObjectMapper O(Params, P);
+  return O && O.mapOptional("id", BP.id) && O.map("verified", BP.verified) &&
+         O.mapOptional("message", BP.message) &&
+         O.mapOptional("source", BP.source) && O.mapOptional("line", BP.line) 
&&
+         O.mapOptional("column", BP.column) &&
+         O.mapOptional("endLine", BP.endLine) &&
+         O.mapOptional("endColumn", BP.endColumn) &&
+         O.mapOptional("instructionReference", BP.instructionReference) &&
+         O.mapOptional("offset", BP.offset) &&
+         O.mapOptional("reason", BP.reason);
+}
+
 bool fromJSON(const llvm::json::Value &Params, SourceBreakpoint &SB,
               llvm::json::Path P) {
   json::ObjectMapper O(Params, P);

diff  --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h 
b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index d1e86b0897675..cab188637acd5 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -65,6 +65,8 @@ enum ColumnType : unsigned {
   eColumnTypeBoolean,
   eColumnTypeTimestamp
 };
+bool fromJSON(const llvm::json::Value &, ColumnType &, llvm::json::Path);
+llvm::json::Value toJSON(const ColumnType &);
 
 /// A ColumnDescriptor specifies what module attribute to show in a column of
 /// the modules view, how to format it, and what the column’s label should be.
@@ -89,6 +91,7 @@ struct ColumnDescriptor {
   /// Width of this column in characters (hint only).
   std::optional<int> width;
 };
+bool fromJSON(const llvm::json::Value &, ColumnDescriptor &, llvm::json::Path);
 llvm::json::Value toJSON(const ColumnDescriptor &);
 
 /// Names of checksum algorithms that may be supported by a debug adapter.
@@ -114,6 +117,8 @@ enum BreakpointModeApplicability : unsigned {
   /// In `InstructionBreakpoint`'s.
   eBreakpointModeApplicabilityInstruction
 };
+bool fromJSON(const llvm::json::Value &, BreakpointModeApplicability &,
+              llvm::json::Path);
 llvm::json::Value toJSON(const BreakpointModeApplicability &);
 
 /// A `BreakpointMode` is provided as a option when setting breakpoints on
@@ -133,6 +138,7 @@ struct BreakpointMode {
   /// Describes one or more type of breakpoint this mode applies to.
   std::vector<BreakpointModeApplicability> appliesTo;
 };
+bool fromJSON(const llvm::json::Value &, BreakpointMode &, llvm::json::Path);
 llvm::json::Value toJSON(const BreakpointMode &);
 
 /// Debug Adapter Features flags supported by lldb-dap.
@@ -364,6 +370,7 @@ enum class BreakpointReason : unsigned {
   /// adapter does not believe it can be verified without intervention.
   eBreakpointReasonFailed,
 };
+bool fromJSON(const llvm::json::Value &, BreakpointReason &, llvm::json::Path);
 llvm::json::Value toJSON(const BreakpointReason &);
 
 /// Information about a breakpoint created in `setBreakpoints`,
@@ -415,6 +422,7 @@ struct Breakpoint {
   /// should omit this property.
   std::optional<BreakpointReason> reason;
 };
+bool fromJSON(const llvm::json::Value &, Breakpoint &, llvm::json::Path);
 llvm::json::Value toJSON(const Breakpoint &);
 
 /// Properties of a breakpoint or logpoint passed to the `setBreakpoints`

diff  --git a/lldb/unittests/DAP/ProtocolTypesTest.cpp 
b/lldb/unittests/DAP/ProtocolTypesTest.cpp
index fa46816ca4a10..56b21f18fa7cd 100644
--- a/lldb/unittests/DAP/ProtocolTypesTest.cpp
+++ b/lldb/unittests/DAP/ProtocolTypesTest.cpp
@@ -60,3 +60,75 @@ TEST(ProtocolTypesTest, Source) {
   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);
+}


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to