https://github.com/JDevlieghere created 
https://github.com/llvm/llvm-project/pull/139502

Add unit tests for serializing and deserializing protocol types.

>From 5fdd0d606262254f7363a55fd5ad38fe726b2dab Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jo...@devlieghere.com>
Date: Sun, 11 May 2025 23:28:21 -0700
Subject: [PATCH] [lldb-dap] Add unit tests for protocol types

Add unit tests for serializing and deserializing protocol types.
---
 lldb/unittests/DAP/CMakeLists.txt        |   1 +
 lldb/unittests/DAP/ProtocolTypesTest.cpp | 268 +++++++++++++++++++++++
 2 files changed, 269 insertions(+)
 create mode 100644 lldb/unittests/DAP/ProtocolTypesTest.cpp

diff --git a/lldb/unittests/DAP/CMakeLists.txt 
b/lldb/unittests/DAP/CMakeLists.txt
index 4bbb552be9f34..62318d2ecbad3 100644
--- a/lldb/unittests/DAP/CMakeLists.txt
+++ b/lldb/unittests/DAP/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_lldb_unittest(DAPTests
   JSONUtilsTest.cpp
   LLDBUtilsTest.cpp
+  ProtocolTypesTest.cpp
 
   LINK_LIBS
     lldbDAP
diff --git a/lldb/unittests/DAP/ProtocolTypesTest.cpp 
b/lldb/unittests/DAP/ProtocolTypesTest.cpp
new file mode 100644
index 0000000000000..b64810dc713af
--- /dev/null
+++ b/lldb/unittests/DAP/ProtocolTypesTest.cpp
@@ -0,0 +1,268 @@
+//===-- 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 "gtest/gtest.h"
+
+using namespace llvm;
+using namespace lldb;
+using namespace lldb_dap;
+using namespace lldb_dap::protocol;
+
+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::json::Value value = toJSON(filter);
+  const json::Object *obj = value.getAsObject();
+  ASSERT_NE(obj, nullptr);
+
+  EXPECT_EQ(obj->getString("filter"), "testFilter");
+  EXPECT_EQ(obj->getString("label"), "Test Filter");
+  EXPECT_EQ(obj->getString("description"), "This is a test filter");
+  EXPECT_EQ(obj->getBoolean("default"), true);
+  EXPECT_EQ(obj->getBoolean("supportsCondition"), true);
+  EXPECT_EQ(obj->getString("conditionDescription"),
+            "Condition for test filter");
+}
+
+TEST(ProtocolTypesTest, ColumnDescriptor) {
+  ColumnDescriptor column;
+  column.attributeName = "testAttribute";
+  column.label = "Test Label";
+  column.format = "testFormat";
+  column.type = eColumnTypeString;
+  column.width = 20;
+
+  llvm::json::Value value = toJSON(column);
+  const json::Object *obj = value.getAsObject();
+  ASSERT_NE(obj, nullptr);
+
+  EXPECT_EQ(obj->getString("attributeName"), "testAttribute");
+  EXPECT_EQ(obj->getString("label"), "Test Label");
+  EXPECT_EQ(obj->getString("format"), "testFormat");
+  EXPECT_EQ(obj->getString("type"), "string");
+  EXPECT_EQ(obj->getInteger("width"), 20);
+}
+
+TEST(ProtocolTypesTest, BreakpointMode) {
+  BreakpointMode mode;
+  mode.mode = "testMode";
+  mode.label = "Test Label";
+  mode.description = "This is a test description";
+  mode.appliesTo = {eBreakpointModeApplicabilitySource,
+                    eBreakpointModeApplicabilityException};
+
+  llvm::json::Value value = toJSON(mode);
+  const json::Object *obj = value.getAsObject();
+  ASSERT_NE(obj, nullptr);
+
+  EXPECT_EQ(obj->getString("mode"), "testMode");
+  EXPECT_EQ(obj->getString("label"), "Test Label");
+  EXPECT_EQ(obj->getString("description"), "This is a test description");
+
+  const auto *appliesToArray = obj->getArray("appliesTo");
+  ASSERT_NE(appliesToArray, nullptr);
+  ASSERT_EQ(appliesToArray->size(), 2UL);
+  EXPECT_EQ(appliesToArray->front().getAsString(), "source");
+  EXPECT_EQ(appliesToArray->back().getAsString(), "exception");
+}
+
+TEST(ProtocolTypesTest, Capabilities) {
+  Capabilities capabilities;
+  capabilities.supportedFeatures = {eAdapterFeatureANSIStyling,
+                                    eAdapterFeatureTerminateRequest};
+  capabilities.exceptionBreakpointFilters = {
+      {"filter1", "Filter 1", "Description 1", true, true, "Condition 1"},
+      {"filter2", "Filter 2", "Description 2", false, false, "Condition 2"}};
+  capabilities.completionTriggerCharacters = {"."};
+  capabilities.additionalModuleColumns = {
+      {"attribute1", "Label 1", "Format 1", eColumnTypeString, 10},
+      {"attribute2", "Label 2", "Format 2", eColumnTypeNumber, 20}};
+  capabilities.supportedChecksumAlgorithms = {eChecksumAlgorithmMD5,
+                                              eChecksumAlgorithmSHA256};
+  capabilities.breakpointModes = {{"mode1",
+                                   "Mode 1",
+                                   "Description 1",
+                                   {eBreakpointModeApplicabilitySource}},
+                                  {"mode2",
+                                   "Mode 2",
+                                   "Description 2",
+                                   {eBreakpointModeApplicabilityException}}};
+  capabilities.lldbExtVersion = "1.0.0";
+
+  llvm::json::Value value = toJSON(capabilities);
+  const json::Object *obj = value.getAsObject();
+  ASSERT_NE(obj, nullptr);
+
+  // Verify supported features.
+  EXPECT_EQ(obj->getBoolean("supportsANSIStyling"), true);
+  EXPECT_EQ(obj->getBoolean("supportsTerminateRequest"), true);
+
+  // Verify exception breakpoint filters.
+  const auto *filtersArray = obj->getArray("exceptionBreakpointFilters");
+  ASSERT_NE(filtersArray, nullptr);
+  ASSERT_EQ(filtersArray->size(), 2UL);
+  const auto *filter1 = filtersArray->front().getAsObject();
+  ASSERT_NE(filter1, nullptr);
+  EXPECT_EQ(filter1->getString("filter"), "filter1");
+  EXPECT_EQ(filter1->getString("label"), "Filter 1");
+  EXPECT_EQ(filter1->getString("description"), "Description 1");
+  EXPECT_EQ(filter1->getBoolean("default"), true);
+  EXPECT_EQ(filter1->getBoolean("supportsCondition"), true);
+  EXPECT_EQ(filter1->getString("conditionDescription"), "Condition 1");
+
+  const auto *filter2 = filtersArray->back().getAsObject();
+  ASSERT_NE(filter2, nullptr);
+  EXPECT_EQ(filter2->getString("filter"), "filter2");
+  EXPECT_EQ(filter2->getString("label"), "Filter 2");
+  EXPECT_EQ(filter2->getString("description"), "Description 2");
+  EXPECT_EQ(filter2->getBoolean("default"), false);
+  EXPECT_EQ(filter2->getBoolean("supportsCondition"), false);
+  EXPECT_EQ(filter2->getString("conditionDescription"), "Condition 2");
+
+  // Verify completion trigger characters.
+  const auto *completionArray = obj->getArray("completionTriggerCharacters");
+  ASSERT_NE(completionArray, nullptr);
+  ASSERT_EQ(completionArray->size(), 1UL);
+  EXPECT_EQ(completionArray->front().getAsString(), ".");
+
+  // Verify additional module columns.
+  const auto *columnsArray = obj->getArray("additionalModuleColumns");
+  ASSERT_NE(columnsArray, nullptr);
+  ASSERT_EQ(columnsArray->size(), 2UL);
+  const auto *column1 = columnsArray->front().getAsObject();
+  ASSERT_NE(column1, nullptr);
+  EXPECT_EQ(column1->getString("attributeName"), "attribute1");
+  EXPECT_EQ(column1->getString("label"), "Label 1");
+  EXPECT_EQ(column1->getString("format"), "Format 1");
+  EXPECT_EQ(column1->getString("type"), "string");
+  EXPECT_EQ(column1->getInteger("width"), 10);
+
+  const auto *column2 = columnsArray->back().getAsObject();
+  ASSERT_NE(column2, nullptr);
+  EXPECT_EQ(column2->getString("attributeName"), "attribute2");
+  EXPECT_EQ(column2->getString("label"), "Label 2");
+  EXPECT_EQ(column2->getString("format"), "Format 2");
+  EXPECT_EQ(column2->getString("type"), "number");
+  EXPECT_EQ(column2->getInteger("width"), 20);
+
+  // Verify supported checksum algorithms.
+  const auto *checksumArray = obj->getArray("supportedChecksumAlgorithms");
+  ASSERT_NE(checksumArray, nullptr);
+  ASSERT_EQ(checksumArray->size(), 2UL);
+  EXPECT_EQ(checksumArray->front().getAsString(), "MD5");
+  EXPECT_EQ(checksumArray->back().getAsString(), "SHA256");
+
+  // Verify breakpoint modes.
+  const auto *modesArray = obj->getArray("breakpointModes");
+  ASSERT_NE(modesArray, nullptr);
+  ASSERT_EQ(modesArray->size(), 2UL);
+  const auto *mode1 = modesArray->front().getAsObject();
+  ASSERT_NE(mode1, nullptr);
+  EXPECT_EQ(mode1->getString("mode"), "mode1");
+  EXPECT_EQ(mode1->getString("label"), "Mode 1");
+  EXPECT_EQ(mode1->getString("description"), "Description 1");
+  const auto *appliesTo1 = mode1->getArray("appliesTo");
+  ASSERT_NE(appliesTo1, nullptr);
+  ASSERT_EQ(appliesTo1->size(), 1UL);
+  EXPECT_EQ(appliesTo1->front().getAsString(), "source");
+
+  const auto *mode2 = modesArray->back().getAsObject();
+  ASSERT_NE(mode2, nullptr);
+  EXPECT_EQ(mode2->getString("mode"), "mode2");
+  EXPECT_EQ(mode2->getString("label"), "Mode 2");
+  EXPECT_EQ(mode2->getString("description"), "Description 2");
+  const auto *appliesTo2 = mode2->getArray("appliesTo");
+  ASSERT_NE(appliesTo2, nullptr);
+  ASSERT_EQ(appliesTo2->size(), 1UL);
+  EXPECT_EQ(appliesTo2->front().getAsString(), "exception");
+
+  // Verify lldb extension version.
+  EXPECT_EQ(obj->getString("$__lldb_version"), "1.0.0");
+}
+
+TEST(ProtocolTypesTest, Source) {
+  Source source;
+  source.name = "testName";
+  source.path = "/path/to/source";
+  source.sourceReference = 12345;
+  source.presentationHint = ePresentationHintEmphasize;
+
+  llvm::json::Value value = toJSON(source);
+
+  Source deserialized_source;
+  llvm::json::Path::Root root;
+  ASSERT_TRUE(fromJSON(value, deserialized_source, root));
+
+  ASSERT_EQ(source.name, deserialized_source.name);
+  ASSERT_EQ(source.path, deserialized_source.path);
+  ASSERT_EQ(source.sourceReference, deserialized_source.sourceReference);
+  ASSERT_EQ(source.presentationHint, deserialized_source.presentationHint);
+}
+
+TEST(ProtocolTypesTest, BreakpointLocation) {
+  BreakpointLocation location;
+  location.line = 42;
+  location.column = 5;
+  location.endLine = 50;
+  location.endColumn = 10;
+
+  llvm::json::Value value = toJSON(location);
+  const json::Object *obj = value.getAsObject();
+  ASSERT_NE(obj, nullptr);
+
+  EXPECT_EQ(obj->getInteger("line"), 42);
+  EXPECT_EQ(obj->getInteger("column"), 5);
+  EXPECT_EQ(obj->getInteger("endLine"), 50);
+  EXPECT_EQ(obj->getInteger("endColumn"), 10);
+}
+
+TEST(ProtocolTypesTest, Breakpoint) {
+  Breakpoint breakpoint;
+  breakpoint.id = 1;
+  breakpoint.verified = true;
+  breakpoint.message = "Breakpoint set successfully";
+  breakpoint.source = {"testSource", "/path/to/source", 12345,
+                       ePresentationHintNormal};
+  breakpoint.line = 42;
+  breakpoint.column = 5;
+  breakpoint.endLine = 50;
+  breakpoint.endColumn = 10;
+  breakpoint.instructionReference = "0x1234";
+  breakpoint.offset = -4;
+  breakpoint.reason = BreakpointReason::eBreakpointReasonPending;
+
+  llvm::json::Value value = toJSON(breakpoint);
+  const json::Object *obj = value.getAsObject();
+  ASSERT_NE(obj, nullptr);
+
+  EXPECT_EQ(obj->getInteger("id"), 1);
+  EXPECT_EQ(obj->getBoolean("verified"), true);
+  EXPECT_EQ(obj->getString("message"), "Breakpoint set successfully");
+
+  const auto *source_obj = obj->getObject("source");
+  ASSERT_NE(source_obj, nullptr);
+  EXPECT_EQ(source_obj->getString("name"), "testSource");
+  EXPECT_EQ(source_obj->getString("path"), "/path/to/source");
+  EXPECT_EQ(source_obj->getInteger("sourceReference"), 12345);
+  EXPECT_EQ(source_obj->getString("presentationHint"), "normal");
+
+  EXPECT_EQ(obj->getInteger("line"), 42);
+  EXPECT_EQ(obj->getInteger("column"), 5);
+  EXPECT_EQ(obj->getInteger("endLine"), 50);
+  EXPECT_EQ(obj->getInteger("endColumn"), 10);
+  EXPECT_EQ(obj->getString("instructionReference"), "0x1234");
+  EXPECT_EQ(obj->getInteger("offset"), -4);
+  EXPECT_EQ(obj->getString("reason"), "pending");
+}
\ No newline at end of file

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

Reply via email to