215 lines
4.8 KiB
Go
215 lines
4.8 KiB
Go
package bridge
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func messageID(id uint64) *uint64 {
|
|
return &id
|
|
}
|
|
|
|
func TestMessageValidate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
message Message
|
|
wantErr string
|
|
}{
|
|
{
|
|
name: "request",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Request,
|
|
RequestId: messageID(1),
|
|
Name: "locals/get",
|
|
},
|
|
},
|
|
{
|
|
name: "successful response",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Response,
|
|
RequestId: messageID(1),
|
|
Name: "locals/get",
|
|
Body: json.RawMessage(`{"variables":{}}`),
|
|
},
|
|
},
|
|
{
|
|
name: "error response",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Response,
|
|
RequestId: messageID(1),
|
|
Name: "locals/get",
|
|
Error: &ProtocolError{
|
|
Code: "not_paused",
|
|
Message: "execution is not paused",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "event",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Event,
|
|
Name: "execution/stopped",
|
|
Body: json.RawMessage(`{"reason":"step","file":"test.py","line":1}`),
|
|
},
|
|
},
|
|
{
|
|
name: "unsupported version",
|
|
message: Message{
|
|
Version: ProtocolVersion + 1,
|
|
Type: Request,
|
|
RequestId: messageID(1),
|
|
Name: "locals/get",
|
|
},
|
|
wantErr: "unsupported protocol version",
|
|
},
|
|
{
|
|
name: "missing name",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Request,
|
|
RequestId: messageID(1),
|
|
},
|
|
wantErr: "message name is required",
|
|
},
|
|
{
|
|
name: "request without ID",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Request,
|
|
Name: "locals/get",
|
|
},
|
|
wantErr: "request ID is required",
|
|
},
|
|
{
|
|
name: "request with error",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Request,
|
|
RequestId: messageID(1),
|
|
Name: "locals/get",
|
|
Error: &ProtocolError{Code: "invalid"},
|
|
},
|
|
wantErr: "request cannot contain an error",
|
|
},
|
|
{
|
|
name: "response without ID",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Response,
|
|
Name: "locals/get",
|
|
},
|
|
wantErr: "response ID is required",
|
|
},
|
|
{
|
|
name: "response with body and error",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Response,
|
|
RequestId: messageID(1),
|
|
Name: "locals/get",
|
|
Body: json.RawMessage(`{}`),
|
|
Error: &ProtocolError{Code: "invalid"},
|
|
},
|
|
wantErr: "response cannot contain both body and error",
|
|
},
|
|
{
|
|
name: "event with ID",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Event,
|
|
RequestId: messageID(1),
|
|
Name: "execution/stopped",
|
|
},
|
|
wantErr: "event cannot contain a request ID",
|
|
},
|
|
{
|
|
name: "event with error",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: Event,
|
|
Name: "execution/stopped",
|
|
Error: &ProtocolError{Code: "invalid"},
|
|
},
|
|
wantErr: "event cannot contain an error",
|
|
},
|
|
{
|
|
name: "unknown type",
|
|
message: Message{
|
|
Version: ProtocolVersion,
|
|
Type: MessageType("notification"),
|
|
RequestId: messageID(1),
|
|
Name: "locals/get",
|
|
},
|
|
wantErr: "unknown message type",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := tt.message.Validate()
|
|
if tt.wantErr == "" {
|
|
if err != nil {
|
|
t.Fatalf("Validate() error = %v", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err == nil {
|
|
t.Fatalf("Validate() error = nil, want error containing %q", tt.wantErr)
|
|
}
|
|
if !strings.Contains(err.Error(), tt.wantErr) {
|
|
t.Fatalf("Validate() error = %q, want error containing %q", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewMessageEncodesTypedBody(t *testing.T) {
|
|
id := uint64(7)
|
|
msg, err := newMessage(Request, &id, "breakpoint/set", SetBreakpointRequest{
|
|
File: "example.py",
|
|
Line: 42,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("newMessage() error = %v", err)
|
|
}
|
|
|
|
if err := msg.Validate(); err != nil {
|
|
t.Fatalf("Validate() error = %v", err)
|
|
}
|
|
|
|
var body SetBreakpointRequest
|
|
if err := json.Unmarshal(msg.Body, &body); err != nil {
|
|
t.Fatalf("unmarshal body: %v", err)
|
|
}
|
|
|
|
if body.File != "example.py" || body.Line != 42 {
|
|
t.Fatalf("decoded body = %+v", body)
|
|
}
|
|
}
|
|
|
|
func TestProtocolErrorString(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
err *ProtocolError
|
|
want string
|
|
}{
|
|
{name: "code and message", err: &ProtocolError{Code: "not_paused", Message: "execution is not paused"}, want: "not_paused: execution is not paused"},
|
|
{name: "message only", err: &ProtocolError{Message: "execution is not paused"}, want: "execution is not paused"},
|
|
{name: "nil", err: nil, want: ""},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := tt.err.Error(); got != tt.want {
|
|
t.Fatalf("Error() = %q, want %q", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|