98 lines
3.3 KiB
C++
98 lines
3.3 KiB
C++
|
|
// Step 1923: DAPProxyServer
|
||
|
|
// DAP protocol message dispatcher.
|
||
|
|
//
|
||
|
|
// t1: default request handlers return success response with empty body
|
||
|
|
// t2: response envelope has correct fields (seq, type, request_seq, command, success)
|
||
|
|
// t3: registerHandler overrides default; custom body returned
|
||
|
|
// t4: event messages return empty (no response)
|
||
|
|
// t5: unknown command still returns success response (no crash)
|
||
|
|
|
||
|
|
#include "DAPProxyServer.h"
|
||
|
|
#include <iostream>
|
||
|
|
#include <nlohmann/json.hpp>
|
||
|
|
|
||
|
|
using json = nlohmann::json;
|
||
|
|
namespace ws = whetstone;
|
||
|
|
|
||
|
|
static int p=0,f=0;
|
||
|
|
#define T(n) { std::cout<<" "<<#n<<"... "; }
|
||
|
|
#define P() { std::cout<<"PASS\n"; ++p; }
|
||
|
|
#define F(m) { std::cout<<"FAIL: "<<m<<"\n"; ++f; }
|
||
|
|
#define C(c,m) if(!(c)){F(m);return;}
|
||
|
|
|
||
|
|
static json makeReq(int seq, const std::string& cmd, json args = json::object()) {
|
||
|
|
return {{"seq",seq},{"type","request"},{"command",cmd},{"arguments",args}};
|
||
|
|
}
|
||
|
|
|
||
|
|
void t1(){
|
||
|
|
T(default_handlers_return_success);
|
||
|
|
ws::DAPProxyServer srv;
|
||
|
|
for (auto& cmd : {"initialize","launch","stackTrace","continue","next","disconnect"}) {
|
||
|
|
auto resp = srv.handle(makeReq(1, cmd));
|
||
|
|
C(resp["success"] == true, std::string(cmd) + " success");
|
||
|
|
C(resp["type"] == "response", std::string(cmd) + " type response");
|
||
|
|
}
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t2(){
|
||
|
|
T(response_envelope_fields);
|
||
|
|
ws::DAPProxyServer srv;
|
||
|
|
auto resp = srv.handle(makeReq(5, "stackTrace"));
|
||
|
|
C(resp.contains("seq"), "has seq");
|
||
|
|
C(resp.contains("type"), "has type");
|
||
|
|
C(resp.contains("request_seq"), "has request_seq");
|
||
|
|
C(resp.contains("command"), "has command");
|
||
|
|
C(resp.contains("success"), "has success");
|
||
|
|
C(resp.contains("body"), "has body");
|
||
|
|
C(resp["request_seq"] == 5, "request_seq matches");
|
||
|
|
C(resp["command"] == "stackTrace", "command matches");
|
||
|
|
// seq increments
|
||
|
|
auto resp2 = srv.handle(makeReq(6, "next"));
|
||
|
|
C(resp2["seq"].get<int>() > resp["seq"].get<int>(), "seq increments");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t3(){
|
||
|
|
T(registerHandler_overrides_default);
|
||
|
|
ws::DAPProxyServer srv;
|
||
|
|
srv.registerHandler("stackTrace", [](const json&) -> json {
|
||
|
|
return {{"stackFrames", json::array({
|
||
|
|
{{"id",1},{"name","main"},{"source","file:///main.py"},{"line",10}}
|
||
|
|
})}};
|
||
|
|
});
|
||
|
|
auto resp = srv.handle(makeReq(1, "stackTrace"));
|
||
|
|
C(resp["success"] == true, "success");
|
||
|
|
C(resp["body"].contains("stackFrames"), "body has stackFrames");
|
||
|
|
C(resp["body"]["stackFrames"].size() == 1, "one frame");
|
||
|
|
C(resp["body"]["stackFrames"][0]["name"] == "main", "frame name");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t4(){
|
||
|
|
T(event_returns_empty);
|
||
|
|
ws::DAPProxyServer srv;
|
||
|
|
json evt = {{"seq",1},{"type","event"},{"event","stopped"},
|
||
|
|
{"body",{{"reason","breakpoint"}}}};
|
||
|
|
auto resp = srv.handle(evt);
|
||
|
|
C(resp.is_null() || resp.empty(), "event returns no response");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t5(){
|
||
|
|
T(unknown_command_returns_success_no_crash);
|
||
|
|
ws::DAPProxyServer srv;
|
||
|
|
auto resp = srv.handle(makeReq(1, "customCommand"));
|
||
|
|
C(resp["type"] == "response", "type response");
|
||
|
|
C(resp["success"] == true, "success true");
|
||
|
|
C(resp["command"] == "customCommand", "command echoed");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(){
|
||
|
|
std::cout << "Step 1923: DAPProxyServer\n";
|
||
|
|
t1(); t2(); t3(); t4(); t5();
|
||
|
|
std::cout << "\n" << p << "/" << (p+f) << " passed\n";
|
||
|
|
return f > 0 ? 1 : 0;
|
||
|
|
}
|