Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions internal/logger/rpc_logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,42 @@ func TestFormatRPCMessage(t *testing.T) {
},
want: []string{"client←tools/call", "200b"},
},
{
name: "empty server ID omits server prefix",
info: &RPCMessageInfo{
Direction: RPCDirectionOutbound,
MessageType: RPCMessageRequest,
ServerID: "",
Method: "tools/list",
PayloadSize: 30,
Payload: `{"method":"tools/list"}`,
},
want: []string{"30b", `{"method":"tools/list"}`},
},
Comment on lines +58 to +69
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case name says the server prefix is omitted, but it only asserts positive substrings ("30b" and the payload). If the formatter ever starts emitting a direction/method prefix even when ServerID is empty (e.g. "→tools/list"), this test would still pass. Add a negative assertion (e.g., ensure the result does not contain "→"/"←", or assert it starts with the size token) so the test actually guards the intended behavior.

Copilot uses AI. Check for mistakes.
{
name: "empty payload omits payload from output",
info: &RPCMessageInfo{
Direction: RPCDirectionOutbound,
MessageType: RPCMessageRequest,
ServerID: "github",
Method: "tools/list",
PayloadSize: 0,
Payload: "",
},
want: []string{"github→tools/list", "0b"},
},
{
name: "response with error and no payload",
info: &RPCMessageInfo{
Direction: RPCDirectionInbound,
MessageType: RPCMessageResponse,
ServerID: "backend",
PayloadSize: 0,
Payload: "",
Error: "connection reset",
},
want: []string{"backend←resp", "0b", "err:connection reset"},
},
}

for _, tt := range tests {
Expand Down Expand Up @@ -177,6 +213,46 @@ func TestFormatRPCMessageMarkdown(t *testing.T) {
want: []string{"**github**→`tools/call`", "```json", `"params"`},
notWant: []string{`"jsonrpc"`, `"method"`},
},
{
name: "tools/call with non-string name in params does not append tool name",
info: &RPCMessageInfo{
Direction: RPCDirectionOutbound,
MessageType: RPCMessageRequest,
ServerID: "github",
Method: "tools/call",
PayloadSize: 60,
Payload: `{"jsonrpc":"2.0","method":"tools/call","params":{"name":42,"arguments":{}}}`,
},
// name is not a string so tool name extraction should not add backtick-wrapped name
want: []string{"**github**→`tools/call`"},
notWant: []string{"**github**→`tools/call` `"},
},
{
name: "empty server ID produces no server prefix",
info: &RPCMessageInfo{
Direction: RPCDirectionOutbound,
MessageType: RPCMessageRequest,
ServerID: "",
Method: "tools/list",
PayloadSize: 40,
Payload: `{"jsonrpc":"2.0","method":"tools/list","params":{"key":"val"}}`,
},
want: []string{"```json", `"params"`},
notWant: []string{"**"},
},
{
name: "empty payload produces no code block",
info: &RPCMessageInfo{
Direction: RPCDirectionOutbound,
MessageType: RPCMessageRequest,
ServerID: "github",
Method: "tools/list",
PayloadSize: 0,
Payload: "",
},
want: []string{"**github**→`tools/list`"},
notWant: []string{"```json"},
},
}

for _, tt := range tests {
Expand Down Expand Up @@ -258,6 +334,24 @@ func TestFormatJSONWithoutFields(t *testing.T) {
wantValid: true,
wantEmpty: false,
},
{
name: "nil fields to remove leaves all fields",
input: `{"jsonrpc":"2.0","method":"tools/list","id":1}`,
fieldsToRemove: nil,
wantContains: []string{`"jsonrpc"`, `"method"`, `"id"`},
wantNotContain: []string{},
wantValid: true,
wantEmpty: false,
},
{
name: "removing non-existent field is a no-op",
input: `{"id":1,"result":{}}`,
fieldsToRemove: []string{"jsonrpc", "method"},
wantContains: []string{`"id"`, `"result"`},
wantNotContain: []string{`"jsonrpc"`, `"method"`},
wantValid: true,
wantEmpty: false,
},
}

for _, tt := range tests {
Expand Down
Loading