Files
LearnGO/go/pkg/mod/github.com/google/go-dap@v0.12.0/codec_test.go
T
2024-09-19 21:38:24 -04:00

1087 lines
44 KiB
Go

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dap
import (
"encoding/json"
"reflect"
"testing"
)
// -------- Responses & Requests --------
var errorResponseString = `{"seq":11,"type":"response","request_seq":9,"command":"stackTrace","success":false,"message":"Unable to produce stack trace: \"{e}\"","body":{"error":{"id":2004,"format":"Unable to produce stack trace: \"{e}\"","variables":{"e":"Unknown goroutine 1"},"showUser":true}}}`
var errorResponseStruct = ErrorResponse{
Response: Response{
ProtocolMessage: ProtocolMessage{
Seq: 11,
Type: "response",
},
Command: "stackTrace",
RequestSeq: 9,
Success: false,
Message: "Unable to produce stack trace: \"{e}\"",
},
Body: ErrorResponseBody{
Error: &ErrorMessage{
Id: 2004,
Format: "Unable to produce stack trace: \"{e}\"",
Variables: map[string]string{"e": "Unknown goroutine 1"},
ShowUser: true,
},
},
}
// -------- CancelRequest
var cancelRequestString = `{"seq":25,"type":"request","command":"cancel","arguments":{"requestId":24}}`
var cancelRequestStruct = CancelRequest{
Request: *newRequest(25, "cancel"),
Arguments: &CancelArguments{RequestId: 24},
}
var cancelResponseString = `{"seq":25,"type":"response","request_seq":26,"command":"cancel","success":true}`
var cancelResponseStruct = CancelResponse{Response: *newResponse(25, 26, "cancel", true)}
// -------- RunInTerminalRequest
var runInTerminalRequestString = `{"seq":45,"type":"request","command":"runInTerminal","arguments":{"kind":"integrated","title":"Some Title","cwd":"/working/dir","args":["mycommand","arg1","arg2"]}}`
var runInTerminalRequestStruct = RunInTerminalRequest{
Request: *newRequest(45, "runInTerminal"),
Arguments: RunInTerminalRequestArguments{
Kind: "integrated",
Title: "Some Title",
Cwd: "/working/dir",
Args: []string{"mycommand", "arg1", "arg2"},
},
}
var runInTerminalResponseString = `{"seq":45,"type":"response","request_seq":46,"command":"runInTerminal","success":true,"body":{"processId":123456}}`
var runInTerminalResponseStruct = RunInTerminalResponse{
Response: *newResponse(45, 46, "runInTerminal", true),
Body: RunInTerminalResponseBody{ProcessId: 123456},
}
// -------- Initialize
var initializeRequestString = `{"seq":1,"type":"request","command":"initialize","arguments":{"clientID":"vscode","clientName":"Visual Studio Code","adapterID":"go","pathFormat":"path","linesStartAt1":true,"columnsStartAt1":true,"supportsVariableType":true,"supportsVariablePaging":true,"supportsRunInTerminalRequest":true,"locale":"en-us"}}`
var initializeRequestOmitDefaultsString = `{"seq":1,"type":"request","command":"initialize","arguments":{"clientID":"vscode","clientName":"Visual Studio Code","adapterID":"go","supportsVariableType":true,"supportsVariablePaging":true,"supportsRunInTerminalRequest":true,"locale":"en-us"}}`
var initializeRequestStruct = InitializeRequest{
Request: *newRequest(1, "initialize"),
Arguments: InitializeRequestArguments{
ClientID: "vscode",
ClientName: "Visual Studio Code",
AdapterID: "go",
PathFormat: "path",
LinesStartAt1: true,
ColumnsStartAt1: true,
SupportsVariableType: true,
SupportsVariablePaging: true,
SupportsRunInTerminalRequest: true,
Locale: "en-us",
},
}
var initializeRequestNotDefaultsString = `{"seq":1,"type":"request","command":"initialize","arguments":{"clientID":"vscode","clientName":"Visual Studio Code","adapterID":"go","pathFormat":"url","linesStartAt1":false,"columnsStartAt1":false,"supportsVariableType":true,"supportsVariablePaging":true,"supportsRunInTerminalRequest":true,"locale":"en-us"}}`
var initializeRequestNotDefaultsStruct = InitializeRequest{
Request: *newRequest(1, "initialize"),
Arguments: InitializeRequestArguments{
ClientID: "vscode",
ClientName: "Visual Studio Code",
AdapterID: "go",
PathFormat: "url",
LinesStartAt1: false,
ColumnsStartAt1: false,
SupportsVariableType: true,
SupportsVariablePaging: true,
SupportsRunInTerminalRequest: true,
Locale: "en-us",
},
}
var initializeResponseString = `{"seq":1,"type":"response","request_seq":2,"command":"initialize","success":true,"body":{"supportsConfigurationDoneRequest":true,"supportsSetVariable":true}}`
var initializeResponseStruct = InitializeResponse{
Response: *newResponse(1, 2, "initialize", true),
Body: Capabilities{
SupportsConfigurationDoneRequest: true,
SupportsSetVariable: true,
},
}
// -------- ConfigurationDone
var configurationDoneRequestString = `{"seq":2,"type":"request","command":"configurationDone"}`
var configurationDoneRequestStruct = ConfigurationDoneRequest{
Request: *newRequest(2, "configurationDone"),
Arguments: nil,
}
var configurationDoneResponseString = `{"seq":2,"type":"response","request_seq":3,"command":"configurationDone","success":true}`
var configurationDoneResponseStruct = ConfigurationDoneResponse{Response: *newResponse(2, 3, "configurationDone", true)}
// -------- Launch
var launchRequestString = `{"seq":3,"type":"request","command":"launch","arguments":{"noDebug":true,"name":"Launch"}}`
var launchRequestStruct = LaunchRequest{
Request: *newRequest(3, "launch"),
Arguments: json.RawMessage(`{"noDebug":true,"name":"Launch"}`),
}
var launchResponseString = `{"seq":3,"type":"response","request_seq":4,"command":"launch","success":true}`
var launchResponseStruct = LaunchResponse{Response: *newResponse(3, 4, "launch", true)}
// -------- Attach
var attachRequestString = `{"seq":4,"type":"request","command":"attach","arguments":{}}`
var attachRequestStruct = AttachRequest{
Request: *newRequest(4, "attach"),
Arguments: json.RawMessage(`{}`),
}
var attachResponseString = `{"seq":4,"type":"response","request_seq":5,"command":"attach","success":true}`
var attachResponseStruct = AttachResponse{Response: *newResponse(4, 5, "attach", true)}
// -------- Restart
var restartRequestString = `{"seq":5,"type":"request","command":"restart"}`
var restartRequestStruct = RestartRequest{
Request: *newRequest(5, "restart"),
Arguments: nil,
}
var restartResponseString = `{"seq":5,"type":"response","request_seq":6,"command":"restart","success":true}`
var restartResponseStruct = RestartResponse{Response: *newResponse(5, 6, "restart", true)}
// -------- Disconnect
var disconnectRequestString = `{"seq":6,"type":"request","command":"disconnect","arguments":{"restart":true}}`
var disconnectRequestStruct = DisconnectRequest{
Request: *newRequest(6, "disconnect"),
Arguments: &DisconnectArguments{Restart: true},
}
var disconnectResponseString = `{"seq":6,"type":"response","request_seq":7,"command":"disconnect","success":true}`
var disconnectResponseStruct = DisconnectResponse{Response: *newResponse(6, 7, "disconnect", true)}
// -------- Terminate
var terminateRequestString = `{"seq":7,"type":"request","command":"terminate","arguments":{"restart":true}}`
var terminateRequestStruct = TerminateRequest{
Request: *newRequest(7, "terminate"),
Arguments: &TerminateArguments{Restart: true},
}
var terminateResponseString = `{"seq":7,"type":"response","request_seq":8,"command":"terminate","success":true}`
var terminateResponseStruct = TerminateResponse{Response: *newResponse(7, 8, "terminate", true)}
// -------- BreakpointLocations
var breakpointLocationsRequestString = `{"seq":8,"type":"request","command":"breakpointLocations","arguments":{"source":{"name":"hello.go","path":"/Users/foo/go/src/hello/hello.go"},"line":10}}`
var breakpointLocationsRequestStruct = BreakpointLocationsRequest{
Request: *newRequest(8, "breakpointLocations"),
Arguments: &BreakpointLocationsArguments{
Source: Source{Name: "hello.go", Path: "/Users/foo/go/src/hello/hello.go"},
Line: 10,
},
}
var breakpointLocationsResponseString = `{"seq":8,"type":"response","request_seq":9,"command":"breakpointLocations","success":true,"body":{"breakpoints":[{"line":14}]}}`
var breakpointLocationsResponseStruct = BreakpointLocationsResponse{
Response: *newResponse(8, 9, "breakpointLocations", true),
Body: BreakpointLocationsResponseBody{
Breakpoints: []BreakpointLocation{{Line: 14}},
},
}
// -------- SetBreakpoints
var setBreakpointsRequestString = `{"seq":9,"type":"request","command":"setBreakpoints","arguments":{"source":{"name":"hello.go","path":"/Users/foo/go/src/hello/hello.go"},"lines":[14],"breakpoints":[{"line":14}],"sourceModified":false}}`
var setBreakpointsRequestStruct = SetBreakpointsRequest{
Request: *newRequest(9, "setBreakpoints"),
Arguments: SetBreakpointsArguments{
Source: Source{Name: "hello.go", Path: "/Users/foo/go/src/hello/hello.go"},
Breakpoints: []SourceBreakpoint{{Line: 14}},
Lines: []int{14},
SourceModified: false,
},
}
var setBreakpointsResponseString = `{"seq":9,"type":"response","request_seq":10,"command":"setBreakpoints","success":true,"body":{"breakpoints":[{"verified":true,"line":14}]}}`
var setBreakpointsResponseStruct = SetBreakpointsResponse{
Response: *newResponse(9, 10, "setBreakpoints", true),
Body: SetBreakpointsResponseBody{
Breakpoints: []Breakpoint{{Verified: true, Line: 14}},
},
}
// -------- SetFunctionBreakpoints
var setFunctionBreakpointsRequestString = `{"seq":10,"type":"request","command":"setFunctionBreakpoints","arguments":{"breakpoints":[{"name":"blah"}]}}`
var setFunctionBreakpointsRequestStruct = SetFunctionBreakpointsRequest{
Request: *newRequest(10, "setFunctionBreakpoints"),
Arguments: SetFunctionBreakpointsArguments{
Breakpoints: []FunctionBreakpoint{{Name: "blah"}},
},
}
var setFunctionBreakpointsResponseString = `{"seq":10,"type":"response","request_seq":11,"command":"setFunctionBreakpoints","success":true, "body":{"breakpoints":[{"verified":true,"line":20}]}}`
var setFunctionBreakpointsResponseStruct = SetFunctionBreakpointsResponse{
Response: *newResponse(10, 11, "setFunctionBreakpoints", true),
Body: SetFunctionBreakpointsResponseBody{
Breakpoints: []Breakpoint{{Verified: true, Line: 20}},
},
}
// -------- SetExceptionBreakpoints
var setExceptionBreakpointsRequestString = `{"seq":11,"type":"request","command":"setExceptionBreakpoints","arguments":{"filters":[]}}`
var setExceptionBreakpointsRequestStruct = SetExceptionBreakpointsRequest{
Request: *newRequest(11, "setExceptionBreakpoints"),
Arguments: SetExceptionBreakpointsArguments{Filters: []string{}},
}
var setExceptionBreakpointsResponseString = `{"seq":11,"type":"response","request_seq":12,"command":"setExceptionBreakpoints","success":true}`
var setExceptionBreakpointsResponseStruct = SetExceptionBreakpointsResponse{Response: *newResponse(11, 12, "setExceptionBreakpoints", true)}
// -------- DataBreakpointInfo
var dataBreakpointInfoRequestString = `{"seq":12,"type":"request","command":"dataBreakpointInfo","arguments":{"name":"fuzzybunny"}}`
var dataBreakpointInfoRequestStruct = DataBreakpointInfoRequest{
Request: *newRequest(12, "dataBreakpointInfo"),
Arguments: DataBreakpointInfoArguments{Name: "fuzzybunny"},
}
var dataBreakpointInfoResponseString = `{"seq":12,"type":"response","request_seq":13,"command":"dataBreakpointInfo","success":true, "body":{"dataId":null,"description":"some description"}}`
var dataBreakpointInfoResponseStruct = DataBreakpointInfoResponse{
Response: *newResponse(12, 13, "dataBreakpointInfo", true),
Body: DataBreakpointInfoResponseBody{
DataId: nil,
Description: "some description",
},
}
// -------- SetDataBreakpoints
var setDataBreakpointsRequestString = `{"seq":13,"type":"request","command":"setDataBreakpoints","arguments":{"breakpoints":[{"dataId":"dataid"}]}}`
var setDataBreakpointsRequestStruct = SetDataBreakpointsRequest{
Request: *newRequest(13, "setDataBreakpoints"),
Arguments: SetDataBreakpointsArguments{
Breakpoints: []DataBreakpoint{{DataId: "dataid"}},
},
}
var setDataBreakpointsResponseString = `{"seq":13,"type":"response","request_seq":14,"command":"setDataBreakpoints","success":true, "body":{"breakpoints":[{"verified":true,"line":100}]}}`
var setDataBreakpointsResponseStruct = SetDataBreakpointsResponse{
Response: *newResponse(13, 14, "setDataBreakpoints", true),
Body: SetDataBreakpointsResponseBody{
Breakpoints: []Breakpoint{{Verified: true, Line: 100}},
},
}
// -------- Continue
var continueRequestString = `{"seq":14,"type":"request","command":"continue","arguments":{"threadId":1}}`
var continueRequestStruct = ContinueRequest{
Request: *newRequest(14, "continue"),
Arguments: ContinueArguments{ThreadId: 1},
}
var continueResponseString = `{"seq":14,"type":"response","request_seq":15,"command":"continue","success":true, "body":{"allThreadsContinued": true}}`
var continueResponseStruct = ContinueResponse{
Response: *newResponse(14, 15, "continue", true),
Body: ContinueResponseBody{AllThreadsContinued: true},
}
// -------- Next
var nextRequestString = `{"seq":15,"type":"request","command":"next","arguments":{"threadId":1}}`
var nextRequestStruct = NextRequest{
Request: *newRequest(15, "next"),
Arguments: NextArguments{ThreadId: 1},
}
var nextResponseString = `{"seq":15,"type":"response","request_seq":16,"command":"next","success":true}`
var nextResponseStruct = NextResponse{Response: *newResponse(15, 16, "next", true)}
// -------- StepIn
var stepInRequestString = `{"seq":16,"type":"request","command":"stepIn","arguments":{"threadId":1}}`
var stepInRequestStruct = StepInRequest{
Request: *newRequest(16, "stepIn"),
Arguments: StepInArguments{ThreadId: 1},
}
var stepInResponseString = `{"seq":16,"type":"response","request_seq":17,"command":"stepIn","success":true}`
var stepInResponseStruct = StepInResponse{Response: *newResponse(16, 17, "stepIn", true)}
// -------- StepOut
var stepOutRequestString = `{"seq":17,"type":"request","command":"stepOut","arguments":{"threadId":1}}`
var stepOutRequestStruct = StepOutRequest{
Request: *newRequest(17, "stepOut"),
Arguments: StepOutArguments{ThreadId: 1},
}
var stepOutResponseString = `{"seq":17,"type":"response","request_seq":18,"command":"stepOut","success":true}`
var stepOutResponseStruct = StepOutResponse{Response: *newResponse(17, 18, "stepOut", true)}
// -------- StepBack
var stepBackRequestString = `{"seq":18,"type":"request","command":"stepBack","arguments":{"threadId":1}}`
var stepBackRequestStruct = StepBackRequest{
Request: *newRequest(18, "stepBack"),
Arguments: StepBackArguments{ThreadId: 1},
}
var stepBackResponseString = `{"seq":18,"type":"response","request_seq":19,"command":"stepBack","success":true}`
var stepBackResponseStruct = StepBackResponse{Response: *newResponse(18, 19, "stepBack", true)}
// -------- ReverseContinue
var reverseContinueRequestString = `{"seq":19,"type":"request","command":"reverseContinue","arguments":{"threadId":1}}`
var reverseContinueRequestStruct = ReverseContinueRequest{
Request: *newRequest(19, "reverseContinue"),
Arguments: ReverseContinueArguments{ThreadId: 1},
}
var reverseContinueResponseString = `{"seq":19,"type":"response","request_seq":20,"command":"reverseContinue","success":true}`
var reverseContinueResponseStruct = ReverseContinueResponse{Response: *newResponse(19, 20, "reverseContinue", true)}
// -------- RestartFrame
var restartFrameRequestString = `{"seq":20,"type":"request","command":"restartFrame","arguments":{"frameId":5}}`
var restartFrameRequestStruct = RestartFrameRequest{
Request: *newRequest(20, "restartFrame"),
Arguments: RestartFrameArguments{FrameId: 5},
}
var restartFrameResponseString = `{"seq":20,"type":"response","request_seq":21,"command":"restartFrame","success":true}`
var restartFrameResponseStruct = RestartFrameResponse{Response: *newResponse(20, 21, "restartFrame", true)}
// -------- Goto
var gotoRequestString = `{"seq":21,"type":"request","command":"goto","arguments":{"threadId":1,"targetId":2}}`
var gotoRequestStruct = GotoRequest{
Request: *newRequest(21, "goto"),
Arguments: GotoArguments{ThreadId: 1, TargetId: 2},
}
var gotoResponseString = `{"seq":21,"type":"response","request_seq":22,"command":"goto","success":true}`
var gotoResponseStruct = GotoResponse{Response: *newResponse(21, 22, "goto", true)}
// -------- Pause
var pauseRequestString = `{"seq":22,"type":"request","command":"pause","arguments":{"threadId":1}}`
var pauseRequestStruct = PauseRequest{
Request: *newRequest(22, "pause"),
Arguments: PauseArguments{ThreadId: 1},
}
var pauseResponseString = `{"seq":22,"type":"response","request_seq":23,"command":"pause","success":true}`
var pauseResponseStruct = PauseResponse{Response: *newResponse(22, 23, "pause", true)}
// -------- StackTrace
var stackTraceRequestString = `{"seq":23,"type":"request","command":"stackTrace","arguments":{"threadId":1,"startFrame":0,"levels":20}}`
var stackTraceRequestStruct = StackTraceRequest{
Request: *newRequest(23, "stackTrace"),
Arguments: StackTraceArguments{
ThreadId: 1,
StartFrame: 0,
Levels: 20,
},
}
var stackTraceResponseString = `{"seq":23,"type":"response","request_seq":24,"command":"stackTrace","success":true,"body":{"stackFrames":[{"id":1000,"source":{"name":"hello.go","path":"/Users/foo/go/src/hello/hello.go","sourceReference":0},"line":6,"column":0,"name":"main.main"},{"id":1001,"source":{"name":"proc.go","path":"/usr/local/go/src/runtime/proc.go","sourceReference":0},"line":203,"column":0,"name":"runtime.main"},{"id":1002,"source":{"name":"asm_amd64.s","path":"/usr/local/go/src/runtime/asm_amd64.s","sourceReference":0},"line":1357,"column":0,"name":"runtime.goexit"}],"totalFrames":3}}`
var stackTraceResponseStruct = StackTraceResponse{
Response: *newResponse(23, 24, "stackTrace", true),
Body: StackTraceResponseBody{
StackFrames: []StackFrame{
{
Id: 1000,
Source: &Source{
Name: "hello.go",
Path: "/Users/foo/go/src/hello/hello.go",
SourceReference: 0,
},
Line: 6,
Column: 0,
Name: "main.main",
},
{
Id: 1001,
Source: &Source{
Name: "proc.go",
Path: "/usr/local/go/src/runtime/proc.go",
SourceReference: 0,
},
Line: 203,
Column: 0,
Name: "runtime.main",
},
{
Id: 1002,
Source: &Source{
Name: "asm_amd64.s",
Path: "/usr/local/go/src/runtime/asm_amd64.s",
SourceReference: 0,
},
Line: 1357,
Column: 0,
Name: "runtime.goexit",
},
},
TotalFrames: 3,
},
}
// -------- Scopes
var scopesRequestString = `{"seq":24,"type":"request","command":"scopes","arguments":{"frameId":1000}}`
var scopesRequestStruct = ScopesRequest{
Request: *newRequest(24, "scopes"),
Arguments: ScopesArguments{FrameId: 1000},
}
var scopesResponseString = `{"seq":24,"type":"response","request_seq":25,"command":"scopes","success":true,"body":{"scopes":[{"name":"Local","variablesReference":1000,"expensive":false},{"name":"Global","variablesReference":1001,"expensive":false}]}}`
var scopesResponseStruct = ScopesResponse{
Response: *newResponse(24, 25, "scopes", true),
Body: ScopesResponseBody{
Scopes: []Scope{
{
Name: "Local",
VariablesReference: 1000,
Expensive: false,
},
{
Name: "Global",
VariablesReference: 1001,
Expensive: false,
},
},
},
}
// -------- Variables
var variablesRequestString = `{"seq":25,"type":"request","command":"variables","arguments":{"variablesReference":1001}}`
var variablesRequestStruct = VariablesRequest{
Request: *newRequest(25, "variables"),
Arguments: VariablesArguments{VariablesReference: 1001},
}
var variablesResponseString = `{"seq":25,"type":"response","request_seq":26,"command":"variables","success":true,"body":{"variables":[{"name":"x","value":"824634220368","evaluateName":"x","variablesReference":0}]}}`
var variablesResponseStruct = VariablesResponse{
Response: *newResponse(25, 26, "variables", true),
Body: VariablesResponseBody{
Variables: []Variable{
{
Name: "x",
Value: "824634220368",
EvaluateName: "x",
VariablesReference: 0,
},
},
},
}
// -------- SetVariable
var setVariableRequestString = `{"seq":26,"type":"request","command":"setVariable","arguments":{"variablesReference":1008,"name":"x","value":"55"}}`
var setVariableRequestStruct = SetVariableRequest{
Request: *newRequest(26, "setVariable"),
Arguments: SetVariableArguments{
VariablesReference: 1008,
Name: "x",
Value: "55",
},
}
var setVariableResponseString = `{"seq":26,"type":"response","request_seq":27,"command":"setVariable","success":true,"body":{"value":"55"}}`
var setVariableResponseStruct = SetVariableResponse{
Response: *newResponse(26, 27, "setVariable", true),
Body: SetVariableResponseBody{Value: "55"},
}
// -------- Source
var sourceRequestString = `{"seq":27,"type":"request","command":"source","arguments":{"sourceReference":123}}`
var sourceRequestStruct = SourceRequest{
Request: *newRequest(27, "source"),
Arguments: SourceArguments{SourceReference: 123},
}
var sourceResponseString = `{"seq":27,"type":"response","request_seq":28,"command":"source","success":true,"body":{"content":"somecontent"}}`
var sourceResponseStruct = SourceResponse{
Response: *newResponse(27, 28, "source", true),
Body: SourceResponseBody{Content: "somecontent"},
}
// -------- Threads
var threadsRequestString = `{"seq":28,"type":"request","command":"threads","arguments":{}}`
var threadsRequestStruct = ThreadsRequest{Request: *newRequest(28, "threads")}
var threadsResponseString = `{"seq":28,"type":"response","request_seq":29,"command":"threads","success":true,"body":{"threads":[{"id":1,"name":"Dummy"}]}}`
var threadsResponseStruct = ThreadsResponse{
Response: *newResponse(28, 29, "threads", true),
Body: ThreadsResponseBody{Threads: []Thread{{Id: 1, Name: "Dummy"}}},
}
// -------- TerminateThreads
var terminateThreadsRequestString = `{"seq":29,"type":"request","command":"terminateThreads","arguments":{"threadIds":[1]}}`
var terminateThreadsRequestStruct = TerminateThreadsRequest{
Request: *newRequest(29, "terminateThreads"),
Arguments: TerminateThreadsArguments{ThreadIds: []int{1}},
}
var terminateThreadsResponseString = `{"seq":29,"type":"response","request_seq":30,"command":"terminateThreads","success":true}`
var terminateThreadsResponseStruct = TerminateThreadsResponse{Response: *newResponse(29, 30, "terminateThreads", true)}
// -------- Modules
var modulesRequestString = `{"seq":30,"type":"request","command":"modules","arguments":{"startModule":1,"moduleCount":3}}`
var modulesRequestStruct = ModulesRequest{
Request: *newRequest(30, "modules"),
Arguments: ModulesArguments{
StartModule: 1,
ModuleCount: 3,
},
}
var modulesResponseString = `{"seq":30,"type":"response","request_seq":31,"command":"modules","success":true,"body":{"totalModules":2,"modules":[{"id":1,"name":"one"}]}}`
var modulesResponseStruct = ModulesResponse{
Response: *newResponse(30, 31, "modules", true),
Body: ModulesResponseBody{
TotalModules: 2,
Modules: []Module{{Id: 1.0, Name: "one"}},
},
}
// -------- LoadedSources
var loadedSourcesRequestString = `{"seq":31,"type":"request","command":"loadedSources"}`
var loadedSourcesRequestStruct = LoadedSourcesRequest{
Request: *newRequest(31, "loadedSources"),
Arguments: nil,
}
var loadedSourcesResponseString = `{"seq":31,"type":"response","request_seq":32,"command":"loadedSources","success":true,"body":{"sources":[{"name":"hello.go","path":"/Users/foo/go/src/hello/hello.go"}]}}`
var loadedSourcesResponseStruct = LoadedSourcesResponse{
Response: *newResponse(31, 32, "loadedSources", true),
Body: LoadedSourcesResponseBody{
Sources: []Source{
{
Name: "hello.go",
Path: "/Users/foo/go/src/hello/hello.go",
},
},
},
}
// -------- Evaluate
var evaluateRequestString = `{"seq":32,"type":"request","command":"evaluate","arguments":{"expression":"x==1","frameId":1000,"context":"repl"}}`
var evaluateRequestStruct = EvaluateRequest{
Request: *newRequest(32, "evaluate"),
Arguments: EvaluateArguments{
Expression: "x==1",
FrameId: 1000,
Context: "repl",
},
}
var evaluateResponseString = `{"seq":32,"type":"response","request_seq":33,"command":"evaluate","success":true,"body":{"result":"false","variablesReference":1}}`
var evaluateResponseStruct = EvaluateResponse{
Response: *newResponse(32, 33, "evaluate", true),
Body: EvaluateResponseBody{
Result: "false",
VariablesReference: 1,
},
}
// -------- SetExpression
var setExpressionRequestString = `{"seq":33,"type":"request","command":"setExpression","arguments":{"expression":"x==1","value":"true"}}`
var setExpressionRequestStruct = SetExpressionRequest{
Request: *newRequest(33, "setExpression"),
Arguments: SetExpressionArguments{
Expression: "x==1",
Value: "true",
},
}
var setExpressionResponseString = `{"seq":33,"type":"response","request_seq":34,"command":"setExpression","success":true,"body":{"value":"true"}}`
var setExpressionResponseStruct = SetExpressionResponse{
Response: *newResponse(33, 34, "setExpression", true),
Body: SetExpressionResponseBody{Value: "true"},
}
// -------- StepInTargets
var stepInTargetsRequestString = `{"seq":34,"type":"request","command":"stepInTargets","arguments":{"frameId":1000}}`
var stepInTargetsRequestStruct = StepInTargetsRequest{
Request: *newRequest(34, "stepInTargets"),
Arguments: StepInTargetsArguments{
FrameId: 1000,
},
}
var stepInTargetsResponseString = `{"seq":34,"type":"response","request_seq":35,"command":"stepInTargets","success":true,"body":{"targets":[{"id":123,"label":"somelabel"}]}}`
var stepInTargetsResponseStruct = StepInTargetsResponse{
Response: *newResponse(34, 35, "stepInTargets", true),
Body: StepInTargetsResponseBody{
Targets: []StepInTarget{
{Id: 123, Label: "somelabel"},
},
},
}
// -------- GotoTargets
var gotoTargetsRequestString = `{"seq":35,"type":"request","command":"gotoTargets","arguments":{"source":{"name":"hello.go","path":"/Users/foo/go/src/hello/hello.go"},"line":10}}`
var gotoTargetsRequestStruct = GotoTargetsRequest{
Request: *newRequest(35, "gotoTargets"),
Arguments: GotoTargetsArguments{
Source: Source{Name: "hello.go", Path: "/Users/foo/go/src/hello/hello.go"},
Line: 10,
},
}
var gotoTargetsResponseString = `{"seq":35,"type":"response","request_seq":36,"command":"gotoTargets","success":true,"body":{"targets":[{"id":123,"label":"somelabel","line":10}]}}`
var gotoTargetsResponseStruct = GotoTargetsResponse{
Response: *newResponse(35, 36, "gotoTargets", true),
Body: GotoTargetsResponseBody{
Targets: []GotoTarget{
{Id: 123, Label: "somelabel", Line: 10},
},
},
}
// -------- Completions
var completionsRequestString = `{"seq": 36,"type":"request","command":"completions","arguments":{"text":"sometext","column":123}}`
var completionsRequestStruct = CompletionsRequest{
Request: *newRequest(36, "completions"),
Arguments: CompletionsArguments{Text: "sometext", Column: 123},
}
var completionsResponseString = `{"seq":36,"type":"response","request_seq":37,"command":"completions","success":true,"body":{"targets":[{"label":"somelabel"}]}}`
var completionsResponseStruct = CompletionsResponse{
Response: *newResponse(36, 37, "completions", true),
Body: CompletionsResponseBody{
Targets: []CompletionItem{
{Label: "somelabel"},
},
},
}
// -------- ExceptionInfo
var exceptionInfoRequestString = `{"seq":36,"type":"request","command":"exceptionInfo","arguments":{"threadId":1}}`
var exceptionInfoRequestStruct = ExceptionInfoRequest{
Request: *newRequest(36, "exceptionInfo"),
Arguments: ExceptionInfoArguments{ThreadId: 1},
}
var exceptionInfoResponseString = `{"seq":36,"type":"response","request_seq":37,"command":"exceptionInfo","success":true,"body":{"exceptionId":"someid","breakMode":"somebreakmode"}}`
var exceptionInfoResponseStruct = ExceptionInfoResponse{
Response: *newResponse(36, 37, "exceptionInfo", true),
Body: ExceptionInfoResponseBody{
ExceptionId: "someid",
BreakMode: "somebreakmode",
},
}
// -------- ReadMemory
var readMemoryRequestString = `{"seq":37,"type":"request","command":"readMemory","arguments":{"memoryReference":"someref","count":123}}`
var readMemoryRequestStruct = ReadMemoryRequest{
Request: *newRequest(37, "readMemory"),
Arguments: ReadMemoryArguments{
MemoryReference: "someref",
Count: 123,
},
}
var readMemoryResponseString = `{"seq":37,"type":"response","request_seq":38,"command":"readMemory","success":true,"body":{"address":"someaddr"}}`
var readMemoryResponseStruct = ReadMemoryResponse{
Response: *newResponse(37, 38, "readMemory", true),
Body: ReadMemoryResponseBody{Address: "someaddr"},
}
// -------- Disassemble
var disassembleRequestString = `{"seq":38,"type":"request","command":"disassemble","arguments":{"memoryReference":"someref","instructionCount":123}}`
var disassembleRequestStruct = DisassembleRequest{
Request: *newRequest(38, "disassemble"),
Arguments: DisassembleArguments{
MemoryReference: "someref",
InstructionCount: 123,
},
}
var disassembleResponseString = `{"seq":38,"type":"response","request_seq":39,"command":"disassemble","success":true,"body":{"instructions":[{"address":"someaddr","instruction":"someinstr"}]}}`
var disassembleResponseStruct = DisassembleResponse{
Response: *newResponse(38, 39, "disassemble", true),
Body: DisassembleResponseBody{
Instructions: []DisassembledInstruction{
{
Address: "someaddr",
Instruction: "someinstr",
},
},
},
}
// -------- StartDebugging
var startDebuggingRequestString = `{"seq":39,"type":"request","command":"startDebugging","arguments":{"request":"launch","configuration":{"any":true}}}`
var startDebuggingRequestStruct = StartDebuggingRequest{
Request: *newRequest(39, "startDebugging"),
Arguments: StartDebuggingRequestArguments{
Request: "launch",
Configuration: map[string]interface{}{"any": true},
},
}
var startDebuggingResponseString = `{"seq":39,"type":"response","request_seq":40,"command":"startDebugging","success":true}`
var startDebuggingResponseStruct = StartDebuggingResponse{
Response: *newResponse(39, 40, "startDebugging", true),
}
// -------- Events --------
var initializedEventString = `{"seq":1,"type":"event","event":"initialized"}`
var initializedEventStruct = InitializedEvent{
Event: *newEvent(1, "initialized"),
}
var stoppedEventString = `{"seq":2,"type":"event","event":"stopped","body":{"reason":"breakpoint","threadId":1,"allThreadsStopped":true}}`
var stoppedEventStruct = StoppedEvent{
Event: *newEvent(2, "stopped"),
Body: StoppedEventBody{Reason: "breakpoint", ThreadId: 1, AllThreadsStopped: true},
}
var continuedEventString = `{"seq":3,"type":"event","event":"continued","body":{"threadId":123}}`
var continuedEventStruct = ContinuedEvent{
Event: *newEvent(3, "continued"),
Body: ContinuedEventBody{ThreadId: 123},
}
var exitedEventString = `{"seq":4,"type":"event","event":"exited","body":{"exitCode":123}}`
var exitedEventStruct = ExitedEvent{
Event: *newEvent(4, "exited"),
Body: ExitedEventBody{ExitCode: 123},
}
var terminatedEventString = `{"seq":5,"type":"event","event":"terminated","body":{"restart":true}}`
var terminatedEventStruct = TerminatedEvent{
Event: *newEvent(5, "terminated"),
Body: TerminatedEventBody{Restart: json.RawMessage(`true`)},
}
var threadEventString = `{"seq":6,"type":"event","event":"thread","body":{"reason":"started","threadId":18}}`
var threadEventStruct = ThreadEvent{
Event: *newEvent(6, "thread"),
Body: ThreadEventBody{Reason: "started", ThreadId: 18},
}
var outputEventString = `{"seq":7,"type":"event","event":"output","body":{"category":"stdout","output":"something that got logged"}}`
var outputEventStruct = OutputEvent{
Event: *newEvent(7, "output"),
Body: OutputEventBody{Category: "stdout", Output: "something that got logged"},
}
var breakpointEventString = `{"seq":8,"type":"event","event":"breakpoint","body":{"reason":"new","breakpoint":{"verified":true}}}`
var breakpointEventStruct = BreakpointEvent{
Event: *newEvent(8, "breakpoint"),
Body: BreakpointEventBody{Reason: "new", Breakpoint: Breakpoint{Verified: true}},
}
var moduleEventString = `{"seq":9,"type":"event","event":"module","body":{"reason":"removed","module":{"id":"id"}}}`
var moduleEventStruct = ModuleEvent{
Event: *newEvent(9, "module"),
Body: ModuleEventBody{Reason: "removed", Module: Module{Id: "id"}},
}
var loadedSourceEventString = `{"seq":10,"type":"event","event":"loadedSource","body":{"reason":"changed","source":{"name":"hello.go","path":"/Users/foo/go/src/hello/hello.go"}}}`
var loadedSourceEventStruct = LoadedSourceEvent{
Event: *newEvent(10, "loadedSource"),
Body: LoadedSourceEventBody{Reason: "changed", Source: Source{Name: "hello.go", Path: "/Users/foo/go/src/hello/hello.go"}},
}
var processEventString = `{"seq":11,"type":"event","event":"process","body":{"name":"/home/example/myproj/program.js"}}`
var processEventStruct = ProcessEvent{
Event: *newEvent(11, "process"),
Body: ProcessEventBody{Name: "/home/example/myproj/program.js"},
}
var capabilitiesEventString = `{"seq":12,"type":"event","event":"capabilities","body":{"capabilities":{"supportsFunctionBreakpoints":true}}}`
var capabilitiesEventStruct = CapabilitiesEvent{
Event: *newEvent(12, "capabilities"),
Body: CapabilitiesEventBody{Capabilities: Capabilities{SupportsFunctionBreakpoints: true}},
}
func TestDecodeProtocolMessage(t *testing.T) {
// Sometimes partial messages can be returned on error, but
// the user should not rely on those and just check err itself.
// Hence the test will not check those.
var msgIgnoredOnError Message
const noError = ""
tests := []struct {
data string
wantMsg Message
wantErr string
}{
// ProtocolMessage
{``, msgIgnoredOnError, "unexpected end of JSON input"},
{`,`, msgIgnoredOnError, "invalid character ',' looking for beginning of value"},
{`{}`, msgIgnoredOnError, "ProtocolMessage type '' is not supported (seq: 0)"},
{`{"a": 1}`, msgIgnoredOnError, "ProtocolMessage type '' is not supported (seq: 0)"},
{`{"type":"foo", "seq": 2}`, msgIgnoredOnError, "ProtocolMessage type 'foo' is not supported (seq: 2)"},
// Request
{`{"type":"request"}`, msgIgnoredOnError, "Request command '' is not supported (seq: 0)"},
{cancelRequestString, &cancelRequestStruct, noError},
{runInTerminalRequestString, &runInTerminalRequestStruct, noError},
{initializeRequestString, &initializeRequestStruct, noError},
{initializeRequestOmitDefaultsString, &initializeRequestStruct, noError},
{initializeRequestNotDefaultsString, &initializeRequestNotDefaultsStruct, noError},
{configurationDoneRequestString, &configurationDoneRequestStruct, noError},
{launchRequestString, &launchRequestStruct, noError},
{attachRequestString, &attachRequestStruct, noError},
{restartRequestString, &restartRequestStruct, noError},
{disconnectRequestString, &disconnectRequestStruct, noError},
{terminateRequestString, &terminateRequestStruct, noError},
{breakpointLocationsRequestString, &breakpointLocationsRequestStruct, noError},
{setBreakpointsRequestString, &setBreakpointsRequestStruct, noError},
{setFunctionBreakpointsRequestString, &setFunctionBreakpointsRequestStruct, noError},
{setExceptionBreakpointsRequestString, &setExceptionBreakpointsRequestStruct, noError},
{dataBreakpointInfoRequestString, &dataBreakpointInfoRequestStruct, noError},
{setDataBreakpointsRequestString, &setDataBreakpointsRequestStruct, noError},
{continueRequestString, &continueRequestStruct, noError},
{nextRequestString, &nextRequestStruct, noError},
{stepInRequestString, &stepInRequestStruct, noError},
{stepOutRequestString, &stepOutRequestStruct, noError},
{stepBackRequestString, &stepBackRequestStruct, noError},
{reverseContinueRequestString, &reverseContinueRequestStruct, noError},
{restartFrameRequestString, &restartFrameRequestStruct, noError},
{gotoRequestString, &gotoRequestStruct, noError},
{pauseRequestString, &pauseRequestStruct, noError},
{stackTraceRequestString, &stackTraceRequestStruct, noError},
{scopesRequestString, &scopesRequestStruct, noError},
{variablesRequestString, &variablesRequestStruct, noError},
{setVariableRequestString, &setVariableRequestStruct, noError},
{sourceRequestString, &sourceRequestStruct, noError},
{threadsRequestString, &threadsRequestStruct, noError},
{terminateThreadsRequestString, &terminateThreadsRequestStruct, noError},
{modulesRequestString, &modulesRequestStruct, noError},
{loadedSourcesRequestString, &loadedSourcesRequestStruct, noError},
{evaluateRequestString, &evaluateRequestStruct, noError},
{setExpressionRequestString, &setExpressionRequestStruct, noError},
{stepInTargetsRequestString, &stepInTargetsRequestStruct, noError},
{gotoTargetsRequestString, &gotoTargetsRequestStruct, noError},
{completionsRequestString, &completionsRequestStruct, noError},
{exceptionInfoRequestString, &exceptionInfoRequestStruct, noError},
{readMemoryRequestString, &readMemoryRequestStruct, noError},
{disassembleRequestString, &disassembleRequestStruct, noError},
{startDebuggingRequestString, &startDebuggingRequestStruct, noError},
// Response
{`{"type":"response","success":true, "seq": 77}`, msgIgnoredOnError, "Response command '' is not supported (seq: 77)"},
{errorResponseString, &errorResponseStruct, noError},
{cancelResponseString, &cancelResponseStruct, noError},
{runInTerminalResponseString, &runInTerminalResponseStruct, noError},
{initializeResponseString, &initializeResponseStruct, noError},
{configurationDoneResponseString, &configurationDoneResponseStruct, noError},
{launchResponseString, &launchResponseStruct, noError},
{attachResponseString, &attachResponseStruct, noError},
{restartResponseString, &restartResponseStruct, noError},
{disconnectResponseString, &disconnectResponseStruct, noError},
{terminateResponseString, &terminateResponseStruct, noError},
{breakpointLocationsResponseString, &breakpointLocationsResponseStruct, noError},
{setBreakpointsResponseString, &setBreakpointsResponseStruct, noError},
{setFunctionBreakpointsResponseString, &setFunctionBreakpointsResponseStruct, noError},
{setExceptionBreakpointsResponseString, &setExceptionBreakpointsResponseStruct, noError},
{dataBreakpointInfoResponseString, &dataBreakpointInfoResponseStruct, noError},
{setDataBreakpointsResponseString, &setDataBreakpointsResponseStruct, noError},
{continueResponseString, &continueResponseStruct, noError},
{nextResponseString, &nextResponseStruct, noError},
{stepInResponseString, &stepInResponseStruct, noError},
{stepOutResponseString, &stepOutResponseStruct, noError},
{stepBackResponseString, &stepBackResponseStruct, noError},
{reverseContinueResponseString, &reverseContinueResponseStruct, noError},
{restartFrameResponseString, &restartFrameResponseStruct, noError},
{gotoResponseString, &gotoResponseStruct, noError},
{pauseResponseString, &pauseResponseStruct, noError},
{stackTraceResponseString, &stackTraceResponseStruct, noError},
{scopesResponseString, &scopesResponseStruct, noError},
{variablesResponseString, &variablesResponseStruct, noError},
{setVariableResponseString, &setVariableResponseStruct, noError},
{sourceResponseString, &sourceResponseStruct, noError},
{threadsResponseString, &threadsResponseStruct, noError},
{terminateThreadsResponseString, &terminateThreadsResponseStruct, noError},
{modulesResponseString, &modulesResponseStruct, noError},
{loadedSourcesResponseString, &loadedSourcesResponseStruct, noError},
{evaluateResponseString, &evaluateResponseStruct, noError},
{setExpressionResponseString, &setExpressionResponseStruct, noError},
{stepInTargetsResponseString, &stepInTargetsResponseStruct, noError},
{gotoTargetsResponseString, &gotoTargetsResponseStruct, noError},
{completionsResponseString, &completionsResponseStruct, noError},
{exceptionInfoResponseString, &exceptionInfoResponseStruct, noError},
{readMemoryResponseString, &readMemoryResponseStruct, noError},
{disassembleResponseString, &disassembleResponseStruct, noError},
{startDebuggingResponseString, &startDebuggingResponseStruct, noError},
// Event
{`{"type":"event", "seq": 8}`, msgIgnoredOnError, "Event event '' is not supported (seq: 8)"},
{initializedEventString, &initializedEventStruct, noError},
{stoppedEventString, &stoppedEventStruct, noError},
{continuedEventString, &continuedEventStruct, noError},
{exitedEventString, &exitedEventStruct, noError},
{terminatedEventString, &terminatedEventStruct, noError},
{threadEventString, &threadEventStruct, noError},
{outputEventString, &outputEventStruct, noError},
{breakpointEventString, &breakpointEventStruct, noError},
{moduleEventString, &moduleEventStruct, noError},
{loadedSourceEventString, &loadedSourceEventStruct, noError},
{processEventString, &processEventStruct, noError},
{capabilitiesEventString, &capabilitiesEventStruct, noError},
}
for _, test := range tests {
t.Run(test.data, func(t *testing.T) {
msg, err := DecodeProtocolMessage([]byte(test.data))
if err != nil { // Decoding error
if err.Error() != test.wantErr { // Was it the right error?
t.Errorf("got error=%#v, want %q", err, test.wantErr)
}
} else { // No decoding error
if test.wantErr != "" { // Did we expect one?
t.Errorf("got error=nil, want %#q", test.wantErr)
}
got, _ := json.Marshal(msg)
want, _ := json.Marshal(test.wantMsg)
if !reflect.DeepEqual(msg, test.wantMsg) { // Check result
t.Errorf("\ngot message\n%s\nwant\n%s", got, want)
}
}
})
}
}
// -------- Custom Request/Response and Event --------
type customRequest struct {
Request
Body string `json:"body"`
}
func (r *customRequest) GetRequest() *Request { return &r.Request }
type customResponse struct {
Response
Body string `json:"body"`
}
func (r *customResponse) GetResponse() *Response { return &r.Response }
var customRequestString = `{"seq":40,"type":"request","command":"customReq","body":"242424"}`
var customRequestStruct = customRequest{
Request: *newRequest(40, "customReq"),
Body: "242424",
}
var customResponseString = `{"seq":40,"type":"response","request_seq":41,"command":"customReq","success":true,"body":"424242"}`
var customResponseStruct = customResponse{
Response: *newResponse(40, 41, "customReq", true),
Body: "424242",
}
type customEvent struct {
Event
Body int `json:"body"`
}
func (e *customEvent) GetEvent() *Event { return &e.Event }
var customEventString = `{"seq":13,"type":"event","event":"customEvt","body":42}`
var customEventStruct = customEvent{
Event: *newEvent(13, "customEvt"),
Body: 42,
}
func TestDecodeProtocolMessage_Custom(t *testing.T) {
tests := []struct {
data string
wantMsg Message
}{
{customRequestString, &customRequestStruct},
{customResponseString, &customResponseStruct},
{customEventString, &customEventStruct},
}
codec := NewCodec()
codec.RegisterRequest("customReq", func() Message { return new(customRequest) }, func() Message { return new(customResponse) })
codec.RegisterEvent("customEvt", func() Message { return new(customEvent) })
for _, test := range tests {
t.Run(test.data, func(t *testing.T) {
msg, err := codec.DecodeMessage([]byte(test.data))
if err != nil { // Decoding error
t.Fatalf("codec.DecodeMessage() failed with %v", err)
}
got, _ := json.Marshal(msg)
want, _ := json.Marshal(test.wantMsg)
if !reflect.DeepEqual(msg, test.wantMsg) { // Check result
t.Errorf("\ngot message\n%s\nwant\n%s", got, want)
}
})
}
}
// newRequest builds a Request struct with the specified fields.
func newRequest(seq int, command string) *Request {
return &Request{
ProtocolMessage: ProtocolMessage{
Type: "request",
Seq: seq,
},
Command: command,
}
}
// newEvent builds an Event struct with the specified fields.
func newEvent(seq int, event string) *Event {
return &Event{
ProtocolMessage: ProtocolMessage{
Seq: seq,
Type: "event",
},
Event: event,
}
}
// newResponse builds a Response struct with the specified fields.
func newResponse(seq int, requestSeq int, command string, success bool) *Response {
return &Response{
ProtocolMessage: ProtocolMessage{
Seq: seq,
Type: "response",
},
Command: command,
RequestSeq: requestSeq,
Success: success,
}
}