[Lldb-commits] [lldb] [lldb-dap] Add unit tests for protocol types (PR #139502)
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Sun May 11 23:29:30 PDT 2025
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 <jonas at 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
More information about the lldb-commits
mailing list