235 lines
5.6 KiB
Go
235 lines
5.6 KiB
Go
package ipc
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
)
|
|
|
|
func TestJSONRPCRequestParsing(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected JSONRPCRequest
|
|
}{
|
|
{
|
|
name: "initialize request",
|
|
input: `{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05"}}`,
|
|
expected: JSONRPCRequest{
|
|
JSONRPC: "2.0",
|
|
ID: float64(1), // JSON numbers are float64
|
|
Method: "initialize",
|
|
},
|
|
},
|
|
{
|
|
name: "tools/list request",
|
|
input: `{"jsonrpc":"2.0","id":2,"method":"tools/list"}`,
|
|
expected: JSONRPCRequest{
|
|
JSONRPC: "2.0",
|
|
ID: float64(2),
|
|
Method: "tools/list",
|
|
},
|
|
},
|
|
{
|
|
name: "tools/call request",
|
|
input: `{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"test","arguments":{}}}`,
|
|
expected: JSONRPCRequest{
|
|
JSONRPC: "2.0",
|
|
ID: float64(3),
|
|
Method: "tools/call",
|
|
},
|
|
},
|
|
{
|
|
name: "notification (no id)",
|
|
input: `{"jsonrpc":"2.0","method":"initialized"}`,
|
|
expected: JSONRPCRequest{
|
|
JSONRPC: "2.0",
|
|
Method: "initialized",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
var req JSONRPCRequest
|
|
if err := json.Unmarshal([]byte(tt.input), &req); err != nil {
|
|
t.Fatalf("failed to parse: %v", err)
|
|
}
|
|
|
|
if req.JSONRPC != tt.expected.JSONRPC {
|
|
t.Errorf("JSONRPC = %s, want %s", req.JSONRPC, tt.expected.JSONRPC)
|
|
}
|
|
if req.Method != tt.expected.Method {
|
|
t.Errorf("Method = %s, want %s", req.Method, tt.expected.Method)
|
|
}
|
|
if tt.expected.ID != nil && req.ID != tt.expected.ID {
|
|
t.Errorf("ID = %v, want %v", req.ID, tt.expected.ID)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestJSONRPCResponseSerialization(t *testing.T) {
|
|
// Success response
|
|
resp := JSONRPCResponse{
|
|
JSONRPC: "2.0",
|
|
ID: 1,
|
|
Result: map[string]interface{}{
|
|
"protocolVersion": "2024-11-05",
|
|
},
|
|
}
|
|
|
|
data, err := json.Marshal(resp)
|
|
if err != nil {
|
|
t.Fatalf("failed to marshal: %v", err)
|
|
}
|
|
|
|
// Verify it can be parsed back
|
|
var parsed JSONRPCResponse
|
|
if err := json.Unmarshal(data, &parsed); err != nil {
|
|
t.Fatalf("failed to unmarshal: %v", err)
|
|
}
|
|
|
|
if parsed.JSONRPC != "2.0" {
|
|
t.Errorf("JSONRPC = %s, want 2.0", parsed.JSONRPC)
|
|
}
|
|
if parsed.Error != nil {
|
|
t.Errorf("Error should be nil")
|
|
}
|
|
}
|
|
|
|
func TestJSONRPCErrorResponse(t *testing.T) {
|
|
resp := JSONRPCResponse{
|
|
JSONRPC: "2.0",
|
|
ID: 1,
|
|
Error: &JSONRPCError{
|
|
Code: ErrCodeMethodNotFound,
|
|
Message: "Method not found",
|
|
},
|
|
}
|
|
|
|
data, err := json.Marshal(resp)
|
|
if err != nil {
|
|
t.Fatalf("failed to marshal: %v", err)
|
|
}
|
|
|
|
var parsed JSONRPCResponse
|
|
if err := json.Unmarshal(data, &parsed); err != nil {
|
|
t.Fatalf("failed to unmarshal: %v", err)
|
|
}
|
|
|
|
if parsed.Error == nil {
|
|
t.Fatal("Error should not be nil")
|
|
}
|
|
if parsed.Error.Code != ErrCodeMethodNotFound {
|
|
t.Errorf("Error.Code = %d, want %d", parsed.Error.Code, ErrCodeMethodNotFound)
|
|
}
|
|
if parsed.Error.Message != "Method not found" {
|
|
t.Errorf("Error.Message = %s, want 'Method not found'", parsed.Error.Message)
|
|
}
|
|
}
|
|
|
|
func TestToolCallParams(t *testing.T) {
|
|
input := `{"name":"my_tool","arguments":{"key":"value","num":42}}`
|
|
|
|
var params ToolCallParams
|
|
if err := json.Unmarshal([]byte(input), ¶ms); err != nil {
|
|
t.Fatalf("failed to parse: %v", err)
|
|
}
|
|
|
|
if params.Name != "my_tool" {
|
|
t.Errorf("Name = %s, want my_tool", params.Name)
|
|
}
|
|
if params.Arguments["key"] != "value" {
|
|
t.Errorf("Arguments[key] = %v, want value", params.Arguments["key"])
|
|
}
|
|
if params.Arguments["num"] != float64(42) {
|
|
t.Errorf("Arguments[num] = %v, want 42", params.Arguments["num"])
|
|
}
|
|
}
|
|
|
|
func TestToolResult(t *testing.T) {
|
|
result := ToolResult{
|
|
Content: []ToolContent{
|
|
{Type: "text", Text: "Hello, world!"},
|
|
},
|
|
}
|
|
|
|
data, err := json.Marshal(result)
|
|
if err != nil {
|
|
t.Fatalf("failed to marshal: %v", err)
|
|
}
|
|
|
|
var parsed ToolResult
|
|
if err := json.Unmarshal(data, &parsed); err != nil {
|
|
t.Fatalf("failed to unmarshal: %v", err)
|
|
}
|
|
|
|
if len(parsed.Content) != 1 {
|
|
t.Fatalf("expected 1 content item, got %d", len(parsed.Content))
|
|
}
|
|
if parsed.Content[0].Type != "text" {
|
|
t.Errorf("Content[0].Type = %s, want text", parsed.Content[0].Type)
|
|
}
|
|
if parsed.Content[0].Text != "Hello, world!" {
|
|
t.Errorf("Content[0].Text = %s, want 'Hello, world!'", parsed.Content[0].Text)
|
|
}
|
|
}
|
|
|
|
func TestToolsListResult(t *testing.T) {
|
|
result := ToolsListResult{
|
|
Tools: []Tool{
|
|
{
|
|
Name: "tool1",
|
|
Description: "Test tool",
|
|
InputSchema: json.RawMessage(`{"type":"object"}`),
|
|
},
|
|
},
|
|
}
|
|
|
|
data, err := json.Marshal(result)
|
|
if err != nil {
|
|
t.Fatalf("failed to marshal: %v", err)
|
|
}
|
|
|
|
var parsed ToolsListResult
|
|
if err := json.Unmarshal(data, &parsed); err != nil {
|
|
t.Fatalf("failed to unmarshal: %v", err)
|
|
}
|
|
|
|
if len(parsed.Tools) != 1 {
|
|
t.Fatalf("expected 1 tool, got %d", len(parsed.Tools))
|
|
}
|
|
if parsed.Tools[0].Name != "tool1" {
|
|
t.Errorf("Tools[0].Name = %s, want tool1", parsed.Tools[0].Name)
|
|
}
|
|
}
|
|
|
|
func TestInitializeResult(t *testing.T) {
|
|
result := InitializeResult{
|
|
ProtocolVersion: "2024-11-05",
|
|
Capabilities: Capabilities{
|
|
Tools: &ToolsCapability{},
|
|
},
|
|
ServerInfo: ServerInfo{
|
|
Name: "yao-sandbox",
|
|
Version: "1.0.0",
|
|
},
|
|
}
|
|
|
|
data, err := json.Marshal(result)
|
|
if err != nil {
|
|
t.Fatalf("failed to marshal: %v", err)
|
|
}
|
|
|
|
var parsed InitializeResult
|
|
if err := json.Unmarshal(data, &parsed); err != nil {
|
|
t.Fatalf("failed to unmarshal: %v", err)
|
|
}
|
|
|
|
if parsed.ProtocolVersion != "2024-11-05" {
|
|
t.Errorf("ProtocolVersion = %s, want 2024-11-05", parsed.ProtocolVersion)
|
|
}
|
|
if parsed.ServerInfo.Name != "yao-sandbox" {
|
|
t.Errorf("ServerInfo.Name = %s, want yao-sandbox", parsed.ServerInfo.Name)
|
|
}
|
|
}
|