Skip to content

[lldb-dap] Splitting ProtocolTypesTest into parts. #144595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

ashgti
Copy link
Contributor

@ashgti ashgti commented Jun 17, 2025

Splitting ProtocolTypesTest into separate files for ProtocolBase, ProtocolEvent, ProtocolRequests and ProtocolTypes.

Splitting ProtocolTypesTest into separate files for ProtocolBase, ProtocolEvent, ProtocolRequests and ProtocolTypes.
@llvmbot
Copy link
Member

llvmbot commented Jun 17, 2025

@llvm/pr-subscribers-lldb

Author: John Harrison (ashgti)

Changes

Splitting ProtocolTypesTest into separate files for ProtocolBase, ProtocolEvent, ProtocolRequests and ProtocolTypes.


Patch is 20.32 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144595.diff

11 Files Affected:

  • (modified) lldb/tools/lldb-dap/DAPError.cpp (+1-2)
  • (modified) lldb/tools/lldb-dap/DAPError.h (+6-6)
  • (modified) lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp (+8-8)
  • (modified) lldb/tools/lldb-dap/Protocol/ProtocolBase.h (+3-3)
  • (modified) lldb/unittests/DAP/CMakeLists.txt (+3)
  • (added) lldb/unittests/DAP/ProtocolBaseTest.cpp (+131)
  • (added) lldb/unittests/DAP/ProtocolEventsTest.cpp (+37)
  • (added) lldb/unittests/DAP/ProtocolRequestsTest.cpp (+82)
  • (modified) lldb/unittests/DAP/ProtocolTypesTest.cpp (+3-93)
  • (modified) lldb/unittests/TestingSupport/TestUtilities.cpp (+5)
  • (modified) lldb/unittests/TestingSupport/TestUtilities.h (+15)
diff --git a/lldb/tools/lldb-dap/DAPError.cpp b/lldb/tools/lldb-dap/DAPError.cpp
index 60347d577f821..c60e8bcc11fa4 100644
--- a/lldb/tools/lldb-dap/DAPError.cpp
+++ b/lldb/tools/lldb-dap/DAPError.cpp
@@ -16,8 +16,7 @@ namespace lldb_dap {
 char DAPError::ID;
 
 DAPError::DAPError(std::string message, std::error_code EC, bool show_user,
-                   std::optional<std::string> url,
-                   std::optional<std::string> url_label)
+                   std::string url, std::string url_label)
     : m_message(message), m_ec(EC), m_show_user(show_user), m_url(url),
       m_url_label(url_label) {}
 
diff --git a/lldb/tools/lldb-dap/DAPError.h b/lldb/tools/lldb-dap/DAPError.h
index 4c94bdd6ac3d6..f44361f7be641 100644
--- a/lldb/tools/lldb-dap/DAPError.h
+++ b/lldb/tools/lldb-dap/DAPError.h
@@ -21,23 +21,23 @@ class DAPError : public llvm::ErrorInfo<DAPError> {
 
   DAPError(std::string message,
            std::error_code EC = llvm::inconvertibleErrorCode(),
-           bool show_user = true, std::optional<std::string> url = std::nullopt,
-           std::optional<std::string> url_label = std::nullopt);
+           bool show_user = true, std::string url = "",
+           std::string url_label = "");
 
   void log(llvm::raw_ostream &OS) const override;
   std::error_code convertToErrorCode() const override;
 
   const std::string &getMessage() const { return m_message; }
   bool getShowUser() const { return m_show_user; }
-  const std::optional<std::string> &getURL() const { return m_url; }
-  const std::optional<std::string> &getURLLabel() const { return m_url; }
+  const std::string &getURL() const { return m_url; }
+  const std::string &getURLLabel() const { return m_url; }
 
 private:
   std::string m_message;
   std::error_code m_ec;
   bool m_show_user;
-  std::optional<std::string> m_url;
-  std::optional<std::string> m_url_label;
+  std::string m_url;
+  std::string m_url_label;
 };
 
 /// An error that indicates the current request handler cannot execute because
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp
index bc4fee4aa8b8d..2b23d9c43aadc 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp
@@ -180,9 +180,9 @@ bool fromJSON(json::Value const &Params, Response &R, json::Path P) {
 json::Value toJSON(const ErrorMessage &EM) {
   json::Object Result{{"id", EM.id}, {"format", EM.format}};
 
-  if (EM.variables) {
+  if (!EM.variables.empty()) {
     json::Object variables;
-    for (auto &var : *EM.variables)
+    for (auto &var : EM.variables)
       variables[var.first] = var.second;
     Result.insert({"variables", std::move(variables)});
   }
@@ -190,9 +190,9 @@ json::Value toJSON(const ErrorMessage &EM) {
     Result.insert({"sendTelemetry", EM.sendTelemetry});
   if (EM.showUser)
     Result.insert({"showUser", EM.showUser});
-  if (EM.url)
+  if (!EM.url.empty())
     Result.insert({"url", EM.url});
-  if (EM.urlLabel)
+  if (!EM.urlLabel.empty())
     Result.insert({"urlLabel", EM.urlLabel});
 
   return std::move(Result);
@@ -201,10 +201,10 @@ json::Value toJSON(const ErrorMessage &EM) {
 bool fromJSON(json::Value const &Params, ErrorMessage &EM, json::Path P) {
   json::ObjectMapper O(Params, P);
   return O && O.map("id", EM.id) && O.map("format", EM.format) &&
-         O.map("variables", EM.variables) &&
-         O.map("sendTelemetry", EM.sendTelemetry) &&
-         O.map("showUser", EM.showUser) && O.map("url", EM.url) &&
-         O.map("urlLabel", EM.urlLabel);
+         O.mapOptional("variables", EM.variables) &&
+         O.mapOptional("sendTelemetry", EM.sendTelemetry) &&
+         O.mapOptional("showUser", EM.showUser) &&
+         O.mapOptional("url", EM.url) && O.mapOptional("urlLabel", EM.urlLabel);
 }
 
 json::Value toJSON(const Event &E) {
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolBase.h b/lldb/tools/lldb-dap/Protocol/ProtocolBase.h
index 81496380d412f..2017258b72618 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolBase.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolBase.h
@@ -119,7 +119,7 @@ struct ErrorMessage {
 
   /// An object used as a dictionary for looking up the variables in the format
   /// string.
-  std::optional<std::map<std::string, std::string>> variables;
+  std::map<std::string, std::string> variables;
 
   /// If true send to telemetry.
   bool sendTelemetry = false;
@@ -128,10 +128,10 @@ struct ErrorMessage {
   bool showUser = false;
 
   /// A url where additional information about this message can be found.
-  std::optional<std::string> url;
+  std::string url;
 
   /// A label that is presented to the user as the UI for opening the url.
-  std::optional<std::string> urlLabel;
+  std::string urlLabel;
 };
 bool fromJSON(const llvm::json::Value &, ErrorMessage &, llvm::json::Path);
 llvm::json::Value toJSON(const ErrorMessage &);
diff --git a/lldb/unittests/DAP/CMakeLists.txt b/lldb/unittests/DAP/CMakeLists.txt
index ee623d341ec69..0806e1a28eb85 100644
--- a/lldb/unittests/DAP/CMakeLists.txt
+++ b/lldb/unittests/DAP/CMakeLists.txt
@@ -5,6 +5,9 @@ add_lldb_unittest(DAPTests
   Handler/ContinueTest.cpp
   JSONUtilsTest.cpp
   LLDBUtilsTest.cpp
+  ProtocolBaseTest.cpp
+  ProtocolEventsTest.cpp
+  ProtocolRequestsTest.cpp
   ProtocolTypesTest.cpp
   TestBase.cpp
   VariablesTest.cpp
diff --git a/lldb/unittests/DAP/ProtocolBaseTest.cpp b/lldb/unittests/DAP/ProtocolBaseTest.cpp
new file mode 100644
index 0000000000000..1fc095d325049
--- /dev/null
+++ b/lldb/unittests/DAP/ProtocolBaseTest.cpp
@@ -0,0 +1,131 @@
+//===-- 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/ProtocolBase.h"
+#include "TestingSupport/TestUtilities.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+// using namespace lldb;
+using namespace lldb_dap;
+using namespace lldb_dap::protocol;
+using lldb_private::pp;
+using llvm::json::parse;
+using llvm::json::Value;
+
+TEST(ProtocolBaseTest, Request) {
+  // Validate toJSON
+  EXPECT_EQ(pp(Request{/*seq=*/42, /*command=*/"hello_world",
+                       /*arguments=*/std::nullopt}),
+            R"({
+  "command": "hello_world",
+  "seq": 42,
+  "type": "request"
+})");
+
+  // Validate fromJSON
+  EXPECT_THAT_EXPECTED(
+      parse<Request>(R"({"type":"request","seq":42,"command":"hello_world"})"),
+      HasValue(Value(Request{/*seq=*/42, /*command=*/"hello_world",
+                             /*arguments*/ std::nullopt})));
+
+  // Validate parsing errors
+  EXPECT_THAT_EXPECTED(parse<Request>(R"({})"),
+                       FailedWithMessage("missing value at (root).type"));
+  EXPECT_THAT_EXPECTED(parse<Request>(R"({"type":"request"})"),
+                       FailedWithMessage("missing value at (root).command"));
+}
+
+TEST(ProtocolBaseTest, Response) {
+  // Validate toJSON
+  EXPECT_EQ(pp(Response{/*request_seq=*/42, /*command=*/"hello_world",
+                        /*success=*/true,
+                        /*message=*/std::nullopt, /*body=*/std::nullopt}),
+            R"({
+  "command": "hello_world",
+  "request_seq": 42,
+  "seq": 0,
+  "success": true,
+  "type": "response"
+})");
+
+  // Validate fromJSON
+  EXPECT_THAT_EXPECTED(
+      parse<Response>(
+          R"({"type":"response","seq":0,"request_seq":42,"command":"hello_world","success":true})"),
+      HasValue(
+          Value(Response{/*seq=*/42, /*command=*/"hello_world",
+                         /*success=*/true,
+                         /*message*/ std::nullopt, /*body=*/std::nullopt})));
+
+  // Validate parsing errors
+  EXPECT_THAT_EXPECTED(parse<Response>(R"({})"),
+                       FailedWithMessage("missing value at (root).type"));
+  EXPECT_THAT_EXPECTED(parse<Response>(R"({"type":"response"})"),
+                       FailedWithMessage("missing value at (root).seq"));
+}
+
+TEST(ProtocolBaseTest, Event) {
+  // Validate toJSON
+  EXPECT_EQ(pp(Event{/*event=*/"hello_world", /*body=*/std::nullopt}),
+            R"({
+  "event": "hello_world",
+  "seq": 0,
+  "type": "event"
+})");
+
+  // Validate fromJSON
+  EXPECT_THAT_EXPECTED(
+      parse<Event>(R"({"type":"event","seq":0,"event":"hello_world"})"),
+      HasValue(Value(Event{/*command=*/"hello_world", /*body=*/std::nullopt})));
+
+  // Validate parsing errors
+  EXPECT_THAT_EXPECTED(parse<Response>(R"({})"),
+                       FailedWithMessage("missing value at (root).type"));
+}
+
+TEST(ProtocolBaseTest, ErrorMessage) {
+  // Validate toJSON
+  EXPECT_EQ(pp(ErrorMessage{/*id=*/42,
+                            /*format=*/"Hello world!",
+                            /*variables=*/{{"name", "value"}},
+                            /*sendTelemetry=*/true,
+                            /*showUser=*/true,
+                            /*url=*/"http://example.com/error/42",
+                            /*urlLabel*/ "ErrorLabel"}),
+            R"({
+  "format": "Hello world!",
+  "id": 42,
+  "sendTelemetry": true,
+  "showUser": true,
+  "url": "http://example.com/error/42",
+  "urlLabel": "ErrorLabel",
+  "variables": {
+    "name": "value"
+  }
+})");
+
+  // Validate fromJSON
+  EXPECT_THAT_EXPECTED(
+      parse<ErrorMessage>(
+          R"({"format":"Hello world!","id":42,"sendTelemetry":true,"showUser":true,"url":"http://example.com/error/42","urlLabel":"ErrorLabel","variables":{"name": "value"}})"),
+      HasValue(Value(ErrorMessage{/*id=*/42,
+                                  /*format=*/"Hello world!",
+                                  /*variables=*/{{"name", "value"}},
+                                  /*sendTelemetry=*/true,
+                                  /*showUser=*/true,
+                                  /*url=*/"http://example.com/error/42",
+                                  /*urlLabel*/ "ErrorLabel"})));
+
+  // Validate parsing errors
+  EXPECT_THAT_EXPECTED(parse<ErrorMessage>(R"({})"),
+                       FailedWithMessage("missing value at (root).id"));
+  EXPECT_THAT_EXPECTED(parse<ErrorMessage>(R"({"id":42})"),
+                       FailedWithMessage("missing value at (root).format"));
+}
diff --git a/lldb/unittests/DAP/ProtocolEventsTest.cpp b/lldb/unittests/DAP/ProtocolEventsTest.cpp
new file mode 100644
index 0000000000000..d9666e06fcac5
--- /dev/null
+++ b/lldb/unittests/DAP/ProtocolEventsTest.cpp
@@ -0,0 +1,37 @@
+//===-- 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/ProtocolEvents.h"
+#include "Protocol/ProtocolTypes.h"
+#include "TestingSupport/TestUtilities.h"
+#include "llvm/ADT/StringRef.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace lldb;
+using namespace lldb_dap;
+using namespace lldb_dap::protocol;
+using lldb_private::pp;
+
+TEST(ProtocolEventsTest, CapabilitiesEventBody) {
+  Capabilities capabilities;
+  capabilities.supportedFeatures = {
+      eAdapterFeatureANSIStyling,
+      eAdapterFeatureBreakpointLocationsRequest,
+  };
+  CapabilitiesEventBody body;
+  body.capabilities = capabilities;
+  StringRef json = R"({
+  "capabilities": {
+    "supportsANSIStyling": true,
+    "supportsBreakpointLocationsRequest": true
+  }
+})";
+  // Validate toJSON
+  EXPECT_EQ(json, pp(body));
+}
diff --git a/lldb/unittests/DAP/ProtocolRequestsTest.cpp b/lldb/unittests/DAP/ProtocolRequestsTest.cpp
new file mode 100644
index 0000000000000..bee34cbad9239
--- /dev/null
+++ b/lldb/unittests/DAP/ProtocolRequestsTest.cpp
@@ -0,0 +1,82 @@
+//===-- 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/ProtocolRequests.h"
+#include "Protocol/ProtocolTypes.h"
+#include "TestingSupport/TestUtilities.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <optional>
+
+using namespace llvm;
+using namespace lldb;
+using namespace lldb_dap;
+using namespace lldb_dap::protocol;
+using lldb_private::pp;
+using llvm::json::parse;
+
+TEST(ProtocolRequestsTest, ThreadResponseBody) {
+  const ThreadsResponseBody body{{{1, "thr1"}, {2, "thr2"}}};
+  const StringRef json = R"({
+  "threads": [
+    {
+      "id": 1,
+      "name": "thr1"
+    },
+    {
+      "id": 2,
+      "name": "thr2"
+    }
+  ]
+})";
+  // Validate toJSON
+  EXPECT_EQ(json, pp(body));
+}
+
+TEST(ProtocolRequestsTest, SetExceptionBreakpointsArguments) {
+  EXPECT_THAT_EXPECTED(
+      parse<SetExceptionBreakpointsArguments>(R"({"filters":[]})"),
+      HasValue(testing::FieldsAre(/*filters=*/testing::IsEmpty(),
+                                  /*filterOptions=*/testing::IsEmpty())));
+  EXPECT_THAT_EXPECTED(
+      parse<SetExceptionBreakpointsArguments>(R"({"filters":["abc"]})"),
+      HasValue(testing::FieldsAre(/*filters=*/std::vector<std::string>{"abc"},
+                                  /*filterOptions=*/testing::IsEmpty())));
+  EXPECT_THAT_EXPECTED(
+      parse<SetExceptionBreakpointsArguments>(
+          R"({"filters":[],"filterOptions":[{"filterId":"abc"}]})"),
+      HasValue(testing::FieldsAre(
+          /*filters=*/testing::IsEmpty(),
+          /*filterOptions=*/testing::Contains(testing::FieldsAre(
+              /*filterId=*/"abc", /*condition=*/"", /*mode=*/"")))));
+
+  // Validate parse errors
+  EXPECT_THAT_EXPECTED(parse<SetExceptionBreakpointsArguments>(R"({})"),
+                       FailedWithMessage("missing value at (root).filters"));
+  EXPECT_THAT_EXPECTED(
+      parse<SetExceptionBreakpointsArguments>(R"({"filters":false})"),
+      FailedWithMessage("expected array at (root).filters"));
+}
+
+TEST(ProtocolRequestsTest, SetExceptionBreakpointsResponseBody) {
+  SetExceptionBreakpointsResponseBody body;
+  Breakpoint bp;
+  bp.id = 12, bp.verified = true;
+  body.breakpoints = {bp};
+  EXPECT_EQ(R"({
+  "breakpoints": [
+    {
+      "id": 12,
+      "verified": true
+    }
+  ]
+})",
+            pp(body));
+}
diff --git a/lldb/unittests/DAP/ProtocolTypesTest.cpp b/lldb/unittests/DAP/ProtocolTypesTest.cpp
index 46a09f090fea2..825c259b5134e 100644
--- a/lldb/unittests/DAP/ProtocolTypesTest.cpp
+++ b/lldb/unittests/DAP/ProtocolTypesTest.cpp
@@ -7,8 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Protocol/ProtocolTypes.h"
-#include "Protocol/ProtocolEvents.h"
-#include "Protocol/ProtocolRequests.h"
+#include "TestingSupport/TestUtilities.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/JSON.h"
 #include "llvm/Testing/Support/Error.h"
@@ -20,23 +19,11 @@ using namespace llvm;
 using namespace lldb;
 using namespace lldb_dap;
 using namespace lldb_dap::protocol;
+using lldb_private::pp;
+using lldb_private::roundtrip;
 using llvm::json::parse;
 using llvm::json::Value;
 
-/// Returns a pretty printed json string of a `llvm::json::Value`.
-static std::string pp(const json::Value &E) {
-  return formatv("{0:2}", E).str();
-}
-
-template <typename T> static llvm::Expected<T> roundtrip(const T &input) {
-  llvm::json::Value value = toJSON(input);
-  llvm::json::Path::Root root;
-  T output;
-  if (!fromJSON(value, output, root))
-    return root.getError();
-  return output;
-}
-
 TEST(ProtocolTypesTest, ExceptionBreakpointsFilter) {
   ExceptionBreakpointsFilter filter;
   filter.filter = "testFilter";
@@ -641,42 +628,6 @@ TEST(ProtocolTypesTest, Thread) {
                        FailedWithMessage("expected string at thread.name"));
 }
 
-TEST(ProtocolTypesTest, ThreadResponseBody) {
-  const ThreadsResponseBody body{{{1, "thr1"}, {2, "thr2"}}};
-  const StringRef json = R"({
-  "threads": [
-    {
-      "id": 1,
-      "name": "thr1"
-    },
-    {
-      "id": 2,
-      "name": "thr2"
-    }
-  ]
-})";
-  // Validate toJSON
-  EXPECT_EQ(json, pp(body));
-}
-
-TEST(ProtocolTypesTest, CapabilitiesEventBody) {
-  Capabilities capabilities;
-  capabilities.supportedFeatures = {
-      eAdapterFeatureANSIStyling,
-      eAdapterFeatureBreakpointLocationsRequest,
-  };
-  CapabilitiesEventBody body;
-  body.capabilities = capabilities;
-  StringRef json = R"({
-  "capabilities": {
-    "supportsANSIStyling": true,
-    "supportsBreakpointLocationsRequest": true
-  }
-})";
-  // Validate toJSON
-  EXPECT_EQ(json, pp(body));
-}
-
 TEST(ProtocolTypesTest, ExceptionFilterOptions) {
   EXPECT_THAT_EXPECTED(parse<ExceptionFilterOptions>(R"({"filterId":"id"})"),
                        HasValue(Value(ExceptionFilterOptions{
@@ -705,47 +656,6 @@ TEST(ProtocolTypesTest, ExceptionFilterOptions) {
       FailedWithMessage("expected string at exceptionFilterOptions.mode"));
 }
 
-TEST(ProtocolTypesTest, SetExceptionBreakpointsArguments) {
-  EXPECT_THAT_EXPECTED(
-      parse<SetExceptionBreakpointsArguments>(R"({"filters":[]})"),
-      HasValue(testing::FieldsAre(/*filters=*/testing::IsEmpty(),
-                                  /*filterOptions=*/testing::IsEmpty())));
-  EXPECT_THAT_EXPECTED(
-      parse<SetExceptionBreakpointsArguments>(R"({"filters":["abc"]})"),
-      HasValue(testing::FieldsAre(/*filters=*/std::vector<std::string>{"abc"},
-                                  /*filterOptions=*/testing::IsEmpty())));
-  EXPECT_THAT_EXPECTED(
-      parse<SetExceptionBreakpointsArguments>(
-          R"({"filters":[],"filterOptions":[{"filterId":"abc"}]})"),
-      HasValue(testing::FieldsAre(
-          /*filters=*/testing::IsEmpty(),
-          /*filterOptions=*/testing::Contains(testing::FieldsAre(
-              /*filterId=*/"abc", /*condition=*/"", /*mode=*/"")))));
-
-  // Validate parse errors
-  EXPECT_THAT_EXPECTED(parse<SetExceptionBreakpointsArguments>(R"({})"),
-                       FailedWithMessage("missing value at (root).filters"));
-  EXPECT_THAT_EXPECTED(
-      parse<SetExceptionBreakpointsArguments>(R"({"filters":false})"),
-      FailedWithMessage("expected array at (root).filters"));
-}
-
-TEST(ProtocolTypesTest, SetExceptionBreakpointsResponseBody) {
-  SetExceptionBreakpointsResponseBody body;
-  Breakpoint bp;
-  bp.id = 12, bp.verified = true;
-  body.breakpoints = {bp};
-  EXPECT_EQ(R"({
-  "breakpoints": [
-    {
-      "id": 12,
-      "verified": true
-    }
-  ]
-})",
-            pp(body));
-}
-
 TEST(ProtocolTypesTest, StepInTarget) {
   StepInTarget target;
   target.id = 230;
diff --git a/lldb/unittests/TestingSupport/TestUtilities.cpp b/lldb/unittests/TestingSupport/TestUtilities.cpp
index b53822e38324b..0c9860f479449 100644
--- a/lldb/unittests/TestingSupport/TestUtilities.cpp
+++ b/lldb/unittests/TestingSupport/TestUtilities.cpp
@@ -20,6 +20,11 @@ using namespace lldb_private;
 extern const char *TestMainArgv0;
 
 std::once_flag TestUtilities::g_debugger_initialize_flag;
+
+std::string lldb_private::pp(const llvm::json::Value &E) {
+  return llvm::formatv("{0:2}", E).str();
+}
+
 std::string lldb_private::GetInputFilePath(const llvm::Twine &name) {
   llvm::SmallString<128> result = llvm::sys::path::parent_path(TestMainArgv0);
   llvm::sys::fs::make_absolute(result);
diff --git a/lldb/unittests/TestingSupport/TestUtilities.h b/lldb/unittests/TestingSupport/TestUtilities.h
index 65994384059fb..a77a16b0812ec 100644
--- a/lldb/unittests/TestingSupport/TestUtilities.h
+++ b/lldb/unittests/TestingSupport/TestUtilities.h
@@ -30,6 +30,20 @@
   }
 
 namespace lldb_private {
+
+/// Returns a pretty printed json string of a `llvm::json::Value`.
+std::string pp(const llvm::json::Value &E);
+
+/// Converts the given value into JSON and back into the same type.
+template <typename T> static llvm::Expected<T> roundtrip(const T &input) {
+  llvm::json::Value value = toJSON(inpu...
[truncated]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants