Files
HomeAgent/internal/pluginview/test/terminal_view_contract_test.go
JianFeeeee 8814ccdef6 test: 按模块导出接口重写黑盒判据(批次 6:promptsec / toolroute / pluginview / meta)
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
2026-11-09 13:22:35 +08:00

70 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package test
// internal/pluginview 的黑盒判据:事件输入 → Snapshot 输出。
// 只调 NewTerminalView/OnToolCall/OnTerminalOutput/Snapshot。
import (
"testing"
"github.com/JianFeeeee/HologramAgent/internal/pluginview"
)
// TestFreshViewIsEmpty:新视图的 Snapshot 为空。
func TestFreshViewIsEmpty(t *testing.T) {
v := pluginview.NewTerminalView()
terms, cmds := v.Snapshot()
if len(terms) != 0 || len(cmds) != 0 {
t.Fatalf("★ 新视图非空:terms=%d cmds=%d", len(terms), len(cmds))
}
}
// TestCmdRunEventAppearsInSnapshot:cmd_run 事件必须进入命令历史。
func TestCmdRunEventAppearsInSnapshot(t *testing.T) {
v := pluginview.NewTerminalView()
v.OnToolCall(map[string]interface{}{
"tool": "cmd_run",
"args": map[string]interface{}{"command": "echo hello"},
"status": "ok",
})
_, cmds := v.Snapshot()
if len(cmds) != 1 {
t.Fatalf("★ cmd_run 未进命令历史:%d 条", len(cmds))
}
if cmds[0].Command != "echo hello" {
t.Fatalf("★ Command = %q,期望 echo hello", cmds[0].Command)
}
}
// TestTerminalCreateThenOutput:创建终端事件 + 输出事件 → Snapshot 反映状态。
func TestTerminalCreateThenOutput(t *testing.T) {
v := pluginview.NewTerminalView()
v.OnToolCall(map[string]interface{}{
"tool": "terminal_create",
"args": map[string]interface{}{"id": "term-1", "command": "bash"},
})
terms, _ := v.Snapshot()
if len(terms) != 1 || terms[0].ID != "term-1" {
t.Fatalf("★ terminal_create 未出现在 Snapshot:%+v", terms)
}
v.OnTerminalOutput(map[string]interface{}{
"terminal_id": "term-1", "output": "line-1\n", "running": true,
})
terms, _ = v.Snapshot()
if len(terms) != 1 {
t.Fatalf("★ 输出事件后终端数变了:%d", len(terms))
}
if terms[0].Output == "" {
t.Fatal("★ 输出事件没进 Snapshot 的 Output")
}
}
// TestUnknownToolIsIgnored:未知工具事件不得造出命令/终端。
func TestUnknownToolIsIgnored(t *testing.T) {
v := pluginview.NewTerminalView()
v.OnToolCall(map[string]interface{}{"tool": "some_plugin_tool", "args": map[string]interface{}{}})
terms, cmds := v.Snapshot()
if len(terms) != 0 || len(cmds) != 0 {
t.Fatalf("★ 未知工具造出了记录:terms=%d cmds=%d", len(terms), len(cmds))
}
}