77 lines
2.5 KiB
Go
77 lines
2.5 KiB
Go
package agent
|
||
|
||
import (
|
||
"path/filepath"
|
||
"runtime"
|
||
"testing"
|
||
)
|
||
|
||
// TestPathWithin 验证路径越界校验:read_file / write_file / run_coop 的 blackboard
|
||
// 都依赖该函数拦截指向项目根目录之外的路径,是核心安全边界。
|
||
func TestPathWithin(t *testing.T) {
|
||
var parent string
|
||
if runtime.GOOS == "windows" {
|
||
parent = `e:\proj`
|
||
} else {
|
||
parent = "/proj"
|
||
}
|
||
|
||
cases := []struct {
|
||
name string
|
||
child string
|
||
expect bool
|
||
}{
|
||
{"自身", parent, true},
|
||
{"直接子文件", filepath.Join(parent, "a.txt"), true},
|
||
{"嵌套子目录", filepath.Join(parent, "sub", "deep", "f.txt"), true},
|
||
{"上级目录", filepath.Join(parent, "..", "secret"), false},
|
||
{"同级兄弟目录", filepath.Join(filepath.Dir(parent), "other"), false},
|
||
}
|
||
for _, tc := range cases {
|
||
t.Run(tc.name, func(t *testing.T) {
|
||
if got := pathWithin(tc.child, parent); got != tc.expect {
|
||
t.Fatalf("pathWithin(%q, %q) = %v, want %v", tc.child, parent, got, tc.expect)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// TestMergeToolCall 验证 SSE 流式 tool_call 增量合并:
|
||
// 跨多个 chunk 按 index 聚合 id / name / arguments,是 LLM 工具调用协议正确性的关键。
|
||
func TestMergeToolCall(t *testing.T) {
|
||
var calls []ToolCall
|
||
// 第一个 chunk:声明 index 0 的调用(id + name)
|
||
calls = mergeToolCall(calls, ToolCallDelta{Index: 0, ID: "call_1", Name: "run_bash"})
|
||
// 同一调用的参数分片到达
|
||
calls = mergeToolCall(calls, ToolCallDelta{Index: 0, ArgumentsDelta: `{"comm`})
|
||
calls = mergeToolCall(calls, ToolCallDelta{Index: 0, ArgumentsDelta: `and":"ls"}`})
|
||
|
||
if len(calls) != 1 {
|
||
t.Fatalf("应合并为 1 个调用,got %d", len(calls))
|
||
}
|
||
c := calls[0]
|
||
if c.ID != "call_1" || c.Function.Name != "run_bash" {
|
||
t.Fatalf("id/name 不匹配: %+v", c)
|
||
}
|
||
if c.Function.Arguments != `{"command":"ls"}` {
|
||
t.Fatalf("arguments 拼接错误: %q", c.Function.Arguments)
|
||
}
|
||
|
||
// 第二个调用在 index 1
|
||
calls = mergeToolCall(calls, ToolCallDelta{Index: 1, ID: "call_2", Name: "read_file"})
|
||
calls = mergeToolCall(calls, ToolCallDelta{Index: 1, ArgumentsDelta: `{"path":"a"}`})
|
||
if len(calls) != 2 {
|
||
t.Fatalf("应有 2 个调用,got %d", len(calls))
|
||
}
|
||
if calls[1].Function.Name != "read_file" {
|
||
t.Fatalf("第二个调用名错误: %+v", calls[1])
|
||
}
|
||
|
||
// index 为负时回退为追加新调用
|
||
prev := len(calls)
|
||
calls = mergeToolCall(calls, ToolCallDelta{Index: -1, ID: "call_3", Name: "list_directory"})
|
||
if len(calls) != prev+1 {
|
||
t.Fatalf("负 index 应追加新调用,got %d", len(calls))
|
||
}
|
||
}
|