Files
whetstone_DSL/editor/tests/step1923_test.cpp
Bill 3808caa1d5 Sprint 279: DAP Orchestration Core (steps 1923-1927)
- DAPProxyServer: DAP JSON dispatcher, routes by command, default handlers for
  all standard DAP commands, response envelope with seq/type/request_seq/success
- DebugAdapterRouter: per-language adapter capability registry; routeCommand gates
  on active language AND adapter support
- PolyglotStackTraceDecoder: infers language from source extension, marks boundary
  frames where adjacent frames differ in language, sets astNodeId per frame
- LanguageSeamFrameDetector: detectSeams/primarySeam/seamCount/frameLanguages/
  crossesBoundary over decoded polyglot stacks
- Sprint279IntegrationSummary: poly-sort (Python+Rust) end-to-end DAP pipeline

26/26 tests passing (5+5+5+5+6). All new headers well under 600 lines.
LoRA recorded: sprint279-2026-03-01 (7 calls, 5535 tokens).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 21:08:37 -07:00

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;
}