From 73d697eac43c1c4add3d7ffc103e59a00994dfe1 Mon Sep 17 00:00:00 2001 From: kuafuwang <731784510@qq.com> Date: Wed, 1 Jan 2020 04:58:33 +0800 Subject: [PATCH] Fix Response type info, make response 'body' field optional The `body` field of the Response is optional. Do not error if it is missing. If the typeinfo of the response. This was incorrectly using the Request type. Authored by kuafuwang, squashed by ben-clayton. --- include/dap/session.h | 9 +++++---- src/session.cpp | 20 ++++++++++---------- src/session_test.cpp | 32 ++++++++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/include/dap/session.h b/include/dap/session.h index f6cbb8b..b37d297 100644 --- a/include/dap/session.h +++ b/include/dap/session.h @@ -201,7 +201,8 @@ class Session { virtual void registerHandler(const TypeInfo* typeinfo, const GenericResponseSentHandler& handler) = 0; - virtual bool send(const dap::TypeInfo* typeinfo, + virtual bool send(const dap::TypeInfo* requestTypeInfo, + const dap::TypeInfo* responseTypeInfo, const void* request, const GenericResponseHandler& responseHandler) = 0; @@ -251,9 +252,9 @@ template future> Session::send(const T& request) { using Response = typename T::Response; promise> promise; - const TypeInfo* typeinfo = TypeOf::type(); - auto sent = - send(typeinfo, &request, [=](const void* result, const Error* error) { + auto sent = send( + TypeOf::type(), TypeOf::type(), &request, + [=](const void* result, const Error* error) { if (error != nullptr) { promise.set_value(ResponseOrError(*error)); } else { diff --git a/src/session.cpp b/src/session.cpp index 57c8c9a..78b0a57 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -80,19 +80,20 @@ class Impl : public dap::Session { }); } - bool send(const dap::TypeInfo* typeinfo, + bool send(const dap::TypeInfo* requestTypeInfo, + const dap::TypeInfo* responseTypeInfo, const void* request, const GenericResponseHandler& responseHandler) override { int seq = nextSeq++; - handlers.put(seq, typeinfo, responseHandler); + handlers.put(seq, responseTypeInfo, responseHandler); dap::json::Serializer s; s.field("seq", dap::integer(seq)); s.field("type", "request"); - s.field("command", typeinfo->name()); + s.field("command", requestTypeInfo->name()); s.field("arguments", [&](dap::Serializer* s) { - return typeinfo->serialize(s, request); + return requestTypeInfo->serialize(s, request); }); return send(s.dump()); } @@ -411,12 +412,11 @@ class Impl : public dap::Session { auto data = std::unique_ptr(new uint8_t[typeinfo->size()]); typeinfo->construct(data.get()); - if (!d->field("body", [&](const dap::Deserializer* d) { - return typeinfo->deserialize(d, data.get()); - })) { - handlers.error("Failed to deserialize request"); - return; - } + // "body" field in Response is an optional field. + d->field("body", [&](const dap::Deserializer* d) { + return typeinfo->deserialize(d, data.get()); + }); + handler(data.get(), nullptr); typeinfo->destruct(data.get()); diff --git a/src/session_test.cpp b/src/session_test.cpp index 66974fa..6b072e2 100644 --- a/src/session_test.cpp +++ b/src/session_test.cpp @@ -54,7 +54,7 @@ DAP_STRUCT_TYPEINFO(TestResponse, struct TestRequest : public Request { using Response = TestResponse; - boolean b; + boolean req_b; integer i; number n; array a; @@ -66,7 +66,7 @@ struct TestRequest : public Request { DAP_STRUCT_TYPEINFO(TestRequest, "test-request", - DAP_FIELD(b, "b"), + DAP_FIELD(req_b, "req_b"), DAP_FIELD(i, "i"), DAP_FIELD(n, "n"), DAP_FIELD(a, "a"), @@ -103,7 +103,7 @@ namespace { dap::TestRequest createRequest() { dap::TestRequest request; - request.b = false; + request.req_b = false; request.i = 72; request.n = 9.87; request.a = {2, 5, 7, 8}; @@ -177,7 +177,7 @@ TEST_F(SessionTest, Request) { client->send(request).get(); // Check request was received correctly. - ASSERT_EQ(received.b, request.b); + ASSERT_EQ(received.req_b, request.req_b); ASSERT_EQ(received.i, request.i); ASSERT_EQ(received.n, request.n); ASSERT_EQ(received.a, request.a); @@ -219,6 +219,30 @@ TEST_F(SessionTest, RequestResponseSuccess) { ASSERT_FALSE(got.response.o2.has_value()); } +TEST_F(SessionTest, BreakPointRequestResponseSuccess) { + server->registerHandler( + [&](const dap::SetBreakpointsRequest&) { + dap::SetBreakpointsResponse rsp; + dap::array breakpoints; + dap::Breakpoint bpItem; + bpItem.line = 2; + breakpoints.emplace_back(std::move(bpItem)); + rsp.breakpoints.swap(breakpoints); + return rsp; + }); + + bind(); + + dap::SetBreakpointsRequest request; + auto response = client->send(request); + + auto got = response.get(); + + // Check response was received correctly. + ASSERT_EQ(got.error, false); + ASSERT_EQ(got.response.breakpoints.size(), 1); + +} TEST_F(SessionTest, RequestResponseOrError) { server->registerHandler( [&](const dap::TestRequest&) -> dap::ResponseOrError {