mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-15 08:51:49 +08:00
## internal/agent/io
原:只有 OutputCapability 位标志 + String
现:
InjectText → 输入事件(source/output_channel/request_id)
InjectInputTo → 显式输出通道被保留
InjectTextSync → 响应回程交到调用方
RegisterDevice → GetDevice → StartAll/StopAll 真实调用设备
重复注册被拒;StartAll 传播设备启动失败
能力标志语义保留(任一位命中)
变异:允许重复注册 / 吞掉启动错误 → 均断言红
## internal/lua
新增:
transform_request 真的执行 Lua body(原来只验证加载与未加载报错)
endpoint/headers 静态声明经公开 API 读回
变异:transform_request 直接返回入参 → 断言红
## internal/system
原:只断言 archived=true 与 baseline 目录非空
现:留档 → 覆盖 → RestoreFileFromBaseline 内容还原为原文
非受保护路径与新建文件不留档
内容未变时重复留档不产生新档案
变异:留档写空内容 / 去掉幂等判断 → 均断言红
## internal/tracker
原:无文件变更时断言无 changeset,rollback 起点为空
现:真实 upper 目录写入 → PostAction 记录 ChangeFileCreated
修改原文 → RollbackLatest 恢复原文内容
新建文件 → RollbackLatest 后消失
空历史定向回滚报错
变异:不记录变更 → 两条断言红
## 验证
go build ./... / go vet ./... PASS
gofmt -l 干净
CI 门禁自检 PASS
go test ./... -count=1 -race 51 测试包 / 100 包无测试 / 0 FAIL
源码目录 _test.go 0
128 lines
4.0 KiB
Go
128 lines
4.0 KiB
Go
package test
|
||
|
||
// internal/lua 的黑盒判据:NewVM → LoadAdapterSource → 可观察输出。
|
||
// 不读适配器源码、不碰 v.pools。
|
||
|
||
import (
|
||
"strings"
|
||
"testing"
|
||
|
||
"github.com/JianFeeeee/HologramAgent/internal/lua"
|
||
)
|
||
|
||
func newVM(t *testing.T) *lua.VM {
|
||
t.Helper()
|
||
return lua.NewVM(t.TempDir())
|
||
}
|
||
|
||
// TestNewVMExposesAdapterDir:构造参数可从 AdapterDir 读回。
|
||
func TestNewVMExposesAdapterDir(t *testing.T) {
|
||
dir := t.TempDir()
|
||
v := lua.NewVM(dir)
|
||
if got := v.AdapterDir(); got != dir {
|
||
t.Fatalf("★ AdapterDir = %q,期望 %q", got, dir)
|
||
}
|
||
}
|
||
|
||
// TestListAdaptersEmptyThenLoaded:加载适配器后 ListAdapters 反映它。
|
||
func TestListAdaptersEmptyThenLoaded(t *testing.T) {
|
||
v := newVM(t)
|
||
if got := v.ListAdapters(); len(got) != 0 {
|
||
t.Fatalf("★ 新 VM 的 ListAdapters = %v,期望空", got)
|
||
}
|
||
// 最小可用适配器脚本(静态检查要求声明 name/version)
|
||
code := `-- name: contract-adapter
|
||
-- version: 1.0
|
||
return {
|
||
transform_request = function(raw) return raw end,
|
||
transform_response = function(raw) return raw end,
|
||
transform_stream_chunk = function(raw) return raw end,
|
||
endpoint = function() return "http://127.0.0.1/v1" end,
|
||
headers = function() return {} end,
|
||
}`
|
||
if err := v.LoadAdapterSource("contract-adapter", code); err != nil {
|
||
t.Fatalf("LoadAdapterSource: %v", err)
|
||
}
|
||
got := v.ListAdapters()
|
||
if len(got) != 1 {
|
||
t.Fatalf("★ ListAdapters = %v,期望 1 个", got)
|
||
}
|
||
if got[0].Name != "contract-adapter" {
|
||
t.Fatalf("★ Name = %q", got[0].Name)
|
||
}
|
||
}
|
||
|
||
// TestLoadAdapterSourceRejectsBadScript:明显不合法的脚本必须报错。
|
||
func TestLoadAdapterSourceRejectsBadScript(t *testing.T) {
|
||
v := newVM(t)
|
||
if err := v.LoadAdapterSource("bad", "this is not lua at all $$$"); err == nil {
|
||
t.Fatal("★ 非法脚本被接受")
|
||
}
|
||
}
|
||
|
||
// TestCallTransformRequestUnknownAdapter:未加载的适配器调用必须报错。
|
||
func TestCallTransformRequestUnknownAdapter(t *testing.T) {
|
||
v := newVM(t)
|
||
_, err := v.CallTransformRequest("ghost", `{}`)
|
||
if err == nil || !strings.Contains(err.Error(), "not loaded") {
|
||
t.Fatalf("★ 未加载适配器的报错不可诊断:%v", err)
|
||
}
|
||
}
|
||
|
||
// TestGetAdapterEndpointUnknownIsEmpty:未知适配器端点为空串、不 panic。
|
||
func TestGetAdapterEndpointUnknownIsEmpty(t *testing.T) {
|
||
if got := newVM(t).GetAdapterEndpoint("ghost"); got != "" {
|
||
t.Fatalf("★ 未知适配器端点 = %q,期望空", got)
|
||
}
|
||
}
|
||
|
||
// TestTransformActuallyRunsAdapter:加载后调用 transform_request,
|
||
// 必须真的执行 Lua 脚本(而非只返回输入或报未加载)。
|
||
func TestTransformActuallyRunsAdapter(t *testing.T) {
|
||
v := newVM(t)
|
||
code := `-- name: contract-adapter
|
||
-- version: 1.0
|
||
return {
|
||
transform_request = function(raw) return '{"rewritten":true}' end,
|
||
transform_response = function(raw) return raw end,
|
||
transform_stream_chunk = function(raw) return raw end,
|
||
}`
|
||
if err := v.LoadAdapterSource("contract-adapter", code); err != nil {
|
||
t.Fatalf("LoadAdapterSource: %v", err)
|
||
}
|
||
out, err := v.CallTransformRequest("contract-adapter", `{"model":"m"}`)
|
||
if err != nil {
|
||
t.Fatalf("CallTransformRequest: %v", err)
|
||
}
|
||
if !strings.Contains(out, "rewritten") {
|
||
t.Fatalf("adapter body not executed: %q", out)
|
||
}
|
||
}
|
||
|
||
// TestAdapterHeadersAndEndpointExposed:静态声明的 endpoint/headers 可读回。
|
||
func TestAdapterHeadersAndEndpointExposed(t *testing.T) {
|
||
v := newVM(t)
|
||
code := `-- name: hdr
|
||
-- version: 1.0
|
||
return {
|
||
endpoint = 'http://127.0.0.1:9000/v1',
|
||
headers = { ['X-Contract'] = 'yes' },
|
||
transform_request = function(raw) return raw end,
|
||
transform_response = function(raw) return raw end,
|
||
transform_stream_chunk = function(raw) return raw end,
|
||
}`
|
||
if err := v.LoadAdapterSource("hdr", code); err != nil {
|
||
t.Fatalf("LoadAdapterSource: %v", err)
|
||
}
|
||
if got := v.GetAdapterEndpoint("hdr"); got != "http://127.0.0.1:9000/v1" {
|
||
t.Fatalf("endpoint = %q", got)
|
||
}
|
||
h, err := v.BuildHeaders("hdr", nil)
|
||
if err != nil {
|
||
t.Fatalf("BuildHeaders: %v", err)
|
||
}
|
||
if h["X-Contract"] != "yes" {
|
||
t.Fatalf("headers = %v", h)
|
||
}
|
||
}
|