mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-12 04:07:34 +00:00
4 个文件全部在 `<module>/test/`,源码目录仍零 `_test.go`。
共 21 条判据,只调导出接口,输入 → 可观察输出。
## internal/promptsec —— NewRegistry/Declare/Render/Snapshot/Names
TestDeclareThenRender 声明两段,按 Order 输出且含正文
TestDeclareRejectsMismatchedOwner 段名前缀与 Owner 不符必须报错
TestDeclareIsIdempotent 同段名覆盖,不产生两份
TestEmptyContentRemovesSection 空正文 = 撤销声明
TestRemoveOwnerOnlyDropsThatOwner 撤销一个 owner 不影响其他
TestSnapshotReturnsAllSections 快照反映当前声明
## internal/toolroute —— Dispatch
TestDispatchRoutesEachPrefix 15 种工具前缀 → 对应族处理器
TestDispatchGetPluginToolsExtractsArg plugin_name 参数透传
TestDispatchUnknownIsNotSwallowed 未知工具 handled=false(插件工具不能消失)
TestDispatchNilHandlers nil handlers 不 panic
用 recordingHandlers 记录哪个族被调用,不断言内部 switch 结构。
## internal/pluginview —— 事件 → Snapshot
TestFreshViewIsEmpty 新视图为空
TestCmdRunEventAppearsInSnapshot cmd_run → 命令历史
TestTerminalCreateThenOutput terminal_create + 输出 → 终端状态
TestUnknownToolIsIgnored 未知工具不造记录
**判据写错过一次**:`OnTerminalOutput` 的 payload 键是 `terminal_id`
不是 `id`,第一版按 `id` 写 ⇒ 输出没进 Snapshot。按真实输入契约修正。
## internal/meta —— 版本元信息
TestFullVersionContainsKernelAndVersion
TestSourceURLLooksLikeHTTPS
TestLicenseMetadataNotEmpty
TestSDKCompatibleVersionIsSemverLike
## 变异验证(改回旧实现必须红)
promptsec Declare 直接 return nil → ★ Render 缺正文
toolroute 未知工具 handled=true → ★ 未知工具被吞掉
pluginview cmd_run 不记录 → ★ cmd_run 未进命令历史
meta FullVersion 丢版本 → ★ 不含 "1.4.0"
第一版 promptsec 变异改的是条件中的一段 token、没改变行为(空变异),
重做后确认判据有效。
## 验证
go build ./... PASS
go vet ./... PASS
gofmt -l 干净
python3 .github/scripts/check-ci-gates.py PASS
go test ./... -count=1 24 个测试包 / 100 包无测试 / 0 FAIL
4 个新包 -race 全绿
源码目录 _test.go 0
121 lines
4.3 KiB
Go
121 lines
4.3 KiB
Go
package test
|
||
|
||
// internal/toolroute 的黑盒判据:Dispatch(handlers, ToolCall) → (输出, handled)。
|
||
// 只调导出函数,不读源码、不碰内部 switch 以外的任何状态。
|
||
|
||
import (
|
||
"testing"
|
||
|
||
"github.com/JianFeeeee/HologramAgent/internal/agent/api"
|
||
"github.com/JianFeeeee/HologramAgent/internal/toolroute"
|
||
)
|
||
|
||
// recordingHandlers 记录每个族处理器被调用的次数。
|
||
type recordingHandlers struct {
|
||
calls map[string]int
|
||
}
|
||
|
||
func newHandlers() *recordingHandlers {
|
||
return &recordingHandlers{calls: map[string]int{}}
|
||
}
|
||
func (h *recordingHandlers) hit(name string) string {
|
||
h.calls[name]++
|
||
return "out:" + name
|
||
}
|
||
func (h *recordingHandlers) ExecutePersonaTool(tc api.ToolCall) string { return h.hit("persona") }
|
||
func (h *recordingHandlers) ExecuteMemoryTool(tc api.ToolCall, s []string) string {
|
||
return h.hit("memory")
|
||
}
|
||
func (h *recordingHandlers) ExecuteSocialTool(tc api.ToolCall) string { return h.hit("social") }
|
||
func (h *recordingHandlers) ExecuteKnowledgeTool(tc api.ToolCall) string {
|
||
return h.hit("knowledge")
|
||
}
|
||
func (h *recordingHandlers) ExecuteColdContextTool(tc api.ToolCall) string {
|
||
return h.hit("coldcontext")
|
||
}
|
||
func (h *recordingHandlers) ExecuteSecretTool(tc api.ToolCall) string { return h.hit("secret") }
|
||
func (h *recordingHandlers) ExecuteOutputSendHelp(tc api.ToolCall) string {
|
||
return h.hit("output_help")
|
||
}
|
||
func (h *recordingHandlers) ExecuteOutputSend(tc api.ToolCall) string { return h.hit("output_send") }
|
||
func (h *recordingHandlers) ExecuteOutputListChannels() string { return h.hit("output_list") }
|
||
func (h *recordingHandlers) ExecuteInputChannels(tc api.ToolCall) string {
|
||
return h.hit("input_channels")
|
||
}
|
||
func (h *recordingHandlers) ExecuteResidentAgents(tc api.ToolCall) string {
|
||
return h.hit("resident")
|
||
}
|
||
func (h *recordingHandlers) ExecuteNotifyParent(tc api.ToolCall) string {
|
||
return h.hit("notify_parent")
|
||
}
|
||
func (h *recordingHandlers) ExecuteInputchNote(tc api.ToolCall) string {
|
||
return h.hit("inputch_note")
|
||
}
|
||
func (h *recordingHandlers) ExecutePluginReload() string { return h.hit("plgreload") }
|
||
func (h *recordingHandlers) ExecuteGetPluginTools(name string) string {
|
||
return h.hit("get_plugin_tools:" + name)
|
||
}
|
||
|
||
// TestDispatchRoutesEachPrefix:每种工具前缀路由到对应族处理器。
|
||
func TestDispatchRoutesEachPrefix(t *testing.T) {
|
||
cases := []struct {
|
||
name, family string
|
||
}{
|
||
{"persona_set", "persona"},
|
||
{"stablemem_commit", "memory"},
|
||
{"social_note", "social"},
|
||
{"knowledge_search", "knowledge"},
|
||
{"coldcontext_query", "coldcontext"},
|
||
{"doc_query", "coldcontext"}, // 旧前缀兼容
|
||
{"secret_get", "secret"},
|
||
{"output_send__qq", "output_send"},
|
||
{"output_send__qq_help", "output_help"},
|
||
{"output_list_channels", "output_list"},
|
||
{"input_channels", "input_channels"},
|
||
{"resident_agents", "resident"},
|
||
{"notify_parent", "notify_parent"},
|
||
{"inputch_note", "inputch_note"},
|
||
{"plgreload", "plgreload"},
|
||
}
|
||
for _, c := range cases {
|
||
h := newHandlers()
|
||
out, handled := toolroute.Dispatch(h, api.ToolCall{Name: c.name}, nil)
|
||
if !handled {
|
||
t.Fatalf("★ %q 未被认作内置工具", c.name)
|
||
}
|
||
if out == "" || h.calls[c.family] != 1 {
|
||
t.Fatalf("★ %q 路由错:out=%q calls=%v", c.name, out, h.calls)
|
||
}
|
||
}
|
||
}
|
||
|
||
// TestDispatchGetPluginToolsExtractsArg:plugin_name 参数必须传给处理器。
|
||
func TestDispatchGetPluginToolsExtractsArg(t *testing.T) {
|
||
h := newHandlers()
|
||
out, handled := toolroute.Dispatch(h, api.ToolCall{
|
||
Name: "get_plugin_tools", Arguments: map[string]interface{}{"plugin_name": "qq"},
|
||
}, nil)
|
||
if !handled || out != "out:get_plugin_tools:qq" {
|
||
t.Fatalf("★ plugin_name 未透传:handled=%v out=%q", handled, out)
|
||
}
|
||
}
|
||
|
||
// TestDispatchUnknownIsNotSwallowed:未知工具 handled=false(插件工具不能消失)。
|
||
func TestDispatchUnknownIsNotSwallowed(t *testing.T) {
|
||
h := newHandlers()
|
||
out, handled := toolroute.Dispatch(h, api.ToolCall{Name: "my_plugin_custom_tool"}, nil)
|
||
if handled || out != "" {
|
||
t.Fatalf("★ 未知工具被吞掉:handled=%v out=%q", handled, out)
|
||
}
|
||
if len(h.calls) != 0 {
|
||
t.Fatalf("★ 未知工具却调了处理器:%v", h.calls)
|
||
}
|
||
}
|
||
|
||
// TestDispatchNilHandlers:nil handlers 不得 panic。
|
||
func TestDispatchNilHandlers(t *testing.T) {
|
||
if _, handled := toolroute.Dispatch(nil, api.ToolCall{Name: "stablemem_commit"}, nil); handled {
|
||
t.Fatal("★ nil handlers 却报告 handled")
|
||
}
|
||
}
|