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