mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-12 04:07:34 +00:00
test: 按模块导出接口重写黑盒判据(批次 5:vector / systemd / recovery)
3 个文件全部在 `<module>/test/`,源码目录仍零 `_test.go`。
共 17 条判据,只调导出接口,输入 → 可观察输出。
## internal/memory/vector —— 纯数学 + Store
TestCosineSimilarity 稀疏向量:同向/正交/零向量
TestDenseCosine 稠密向量:三种基本情形 + 非单位向量
TestStoreInsertSearchRemove Insert → Search 命中 → Remove → 不再命中
**变异第一版没红**:`DenseCosine` 去掉归一化后,我给的 `{1,0}`
用例点积恰好还是 1 ⇒ 空变异。补 `{4,4} / {2,2}`(不归一化得 16,
归一化得 1)后才真红。**变异必须真的改变被测行为**,这条按纪律记下。
## internal/systemd —— State / NewMigratePlan
TestStateInSync 相同/等价/空/不同路径
TestStateDescribe 一致→空;不一致→含两路径与后果
TestSyncCommand 不一致时给出可执行命令
TestNewMigratePlanNormalizesPaths 路径 Clean;脚本内联新旧路径 + shebang
TestRestartCommand 命令含给定地址
不读单元文件、不执行脚本、不碰系统状态。
## internal/recovery —— 文件往返
TestTaskRoundTrip SaveTask → LoadTask 全字段 + Plugins()
TestTaskPathsAreStable TaskPath/ResultPath 稳定且互异
TestResultRoundTrip SaveResult → LoadResult 结论字段
TestLoadTaskMissingFileReportsError
TestSortSteps 输出可用
## 变异验证(改回旧实现必须红)
vector 不归一化 → ★ 非单位同向 = 16,期望 1
systemd InSync 恒 true → ★ 真不一致: InSync=true
recovery 丢 PluginList → ★ PluginList 丢失:[]
全部还原后复跑全绿。
## 验证
go build ./... PASS
go vet ./... PASS
gofmt -l 干净
python3 .github/scripts/check-ci-gates.py PASS
go test ./... -count=1 20 个测试包 / 100 包无测试 / 0 FAIL
3 个新包 -race 全绿
源码目录 _test.go 0
This commit is contained in:
74
internal/memory/vector/test/vector_contract_test.go
Normal file
74
internal/memory/vector/test/vector_contract_test.go
Normal file
@ -0,0 +1,74 @@
|
||||
package test
|
||||
|
||||
// internal/memory/vector 的黑盒判据:纯数学函数 + Store 公开方法,输入 → 输出。
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/JianFeeeee/HologramAgent/internal/memory/vector"
|
||||
)
|
||||
|
||||
// TestCosineSimilarity:同向=1、正交=0、零向量=0。
|
||||
func TestCosineSimilarity(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
a, b vector.Vector
|
||||
want float64
|
||||
}{
|
||||
{"同向", vector.Vector{"x": 2, "y": 3}, vector.Vector{"x": 4, "y": 6}, 1},
|
||||
{"正交", vector.Vector{"x": 1}, vector.Vector{"y": 1}, 0},
|
||||
{"零向量", vector.Vector{}, vector.Vector{"x": 1}, 0},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got := vector.CosineSimilarity(c.a, c.b)
|
||||
if math.Abs(got-c.want) > 1e-9 {
|
||||
t.Errorf("★ %s: CosineSimilarity=%v,期望 %v", c.name, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestDenseCosine:稠密向量同样的三种基本情形。
|
||||
func TestDenseCosine(t *testing.T) {
|
||||
if got := vector.DenseCosine([]float64{1, 0}, []float64{1, 0}); math.Abs(got-1) > 1e-9 {
|
||||
t.Fatalf("★ 同向 = %v,期望 1", got)
|
||||
}
|
||||
if got := vector.DenseCosine([]float64{1, 0}, []float64{0, 1}); got != 0 {
|
||||
t.Fatalf("★ 正交 = %v,期望 0", got)
|
||||
}
|
||||
if got := vector.DenseCosine([]float64{0, 0}, []float64{1, 1}); got != 0 {
|
||||
t.Fatalf("★ 零向量 = %v,期望 0", got)
|
||||
}
|
||||
// 非单位向量:不归一化会得到点积 32 而不是余弦 1。
|
||||
if got := vector.DenseCosine([]float64{4, 4}, []float64{2, 2}); math.Abs(got-1) > 1e-9 {
|
||||
t.Fatalf("★ 非单位同向 = %v,期望 1(未归一化会得 32)", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestStoreInsertSearchRemove:Insert → Search 命中 → Remove → 不再命中。
|
||||
func TestStoreInsertSearchRemove(t *testing.T) {
|
||||
s := vector.NewStore()
|
||||
s.SetMinScore(0)
|
||||
if got := s.Size(); got != 0 {
|
||||
t.Fatalf("★ 新 Store Size=%d,期望 0", got)
|
||||
}
|
||||
s.Insert("doc-a", "账单服务", vector.Vector{"账单": 1, "发票": 1}, nil)
|
||||
s.Insert("doc-b", "登录会话", vector.Vector{"登录": 1}, nil)
|
||||
if got := s.Size(); got != 2 {
|
||||
t.Fatalf("★ Insert 后 Size=%d,期望 2", got)
|
||||
}
|
||||
hits := s.Search(vector.Vector{"账单": 1}, 2)
|
||||
if len(hits) == 0 || hits[0].ID != "doc-a" {
|
||||
t.Fatalf("★ Search 排第一的是 %+v,期望 doc-a", hits)
|
||||
}
|
||||
s.Remove("doc-a")
|
||||
if got := s.Size(); got != 1 {
|
||||
t.Fatalf("★ Remove 后 Size=%d,期望 1", got)
|
||||
}
|
||||
hits = s.Search(vector.Vector{"账单": 1}, 2)
|
||||
for _, h := range hits {
|
||||
if h.ID == "doc-a" {
|
||||
t.Fatal("★ Remove 后仍能检索到 doc-a")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user