mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-12 04:07:34 +00:00
4 个文件全部在 `<module>/test/`,源码目录仍零 `_test.go`。
共 15 条判据,只调导出接口,输入 → 可观察输出。
## internal/agent/io —— OutputCapability
TestSupportsSingleAndCombinedFlags 位标志的「任一位命中」语义
TestCapabilityStringListsFlags String 列出已置位能力名
TestZeroCapabilityString 零能力不 panic
**判据写错过一次**:第一版按「全部命中」写 Supports,实测红。
查实现(`c&cap != 0`)确认是任一位命中,按真实契约修正。
## internal/system —— 路径判定 / 写前留档
TestIsProtectedPathExplicit 显式前缀集内/外的判定
TestArchiveBeforeWrite 受保护路径覆盖前留档(走导出的
SetProtectedPaths 配置入口)
TestNetworkBaselinePathIsStable 路径输出稳定
TestLoadBaselineMissingReportsError 读不存在的基线报错
## internal/ipc —— 真实 unix socket 往返
TestPingReturnsServerStatus Server 状态原样到达 Client
TestPingWithoutServerReportsError 无服务端时报错
用临时目录下真 socket,不 mock 传输层。
## internal/supervisor —— Daemon 登记
TestFreshDaemonHasNoAgents 新 daemon 无 agent
TestRegisterThenList RegisterAgent → List/Get 反映该 agent
TestGetUnknownAgentReportsError 未注册 agent 报错
TestSDKAdapterSeesSameAgents 适配层看到同一份登记
## 变异验证(改回旧实现必须红)
agent/io Supports 恒 false → ★ 已置位的能力报告不支持
system 路径判定恒 false → ★ 前缀集内的路径没判受保护
ipc Ping 丢 Tools 字段 → ★ Ping 拿到的状态不符
supervisor ListAgents 恒空 → ★ ListAgents = [],期望 1 个
system / ipc 第一版变异改错了位置(空变异),重做后确认判据有效。
## 验证
go build ./... PASS
go vet ./... PASS
gofmt -l 干净
python3 .github/scripts/check-ci-gates.py PASS
go test ./... -count=1 28 个测试包 / 100 包无测试 / 0 FAIL
4 个新包 -race 全绿
源码目录 _test.go 0
75 lines
2.4 KiB
Go
75 lines
2.4 KiB
Go
package test
|
||
|
||
// internal/system 的黑盒判据:导出路径判定函数,输入 → 输出。
|
||
// 不改全局状态、不碰系统文件。
|
||
|
||
import (
|
||
"os"
|
||
"path/filepath"
|
||
"testing"
|
||
|
||
"github.com/JianFeeeee/HologramAgent/internal/system"
|
||
)
|
||
|
||
// TestIsProtectedPathExplicit:显式前缀集内的路径判受保护,集外的不判。
|
||
func TestIsProtectedPathExplicit(t *testing.T) {
|
||
dir := t.TempDir()
|
||
inside := filepath.Join(dir, "protected", "file.txt")
|
||
outside := filepath.Join(dir, "other", "file.txt")
|
||
prefixes := []string{filepath.Join(dir, "protected")}
|
||
if !system.IsProtectedPathExplicit(prefixes, inside) {
|
||
t.Fatal("★ 前缀集内的路径没判受保护")
|
||
}
|
||
if system.IsProtectedPathExplicit(prefixes, outside) {
|
||
t.Fatal("★ 前缀集外的路径被判受保护")
|
||
}
|
||
if system.IsProtectedPathExplicit(nil, inside) {
|
||
t.Fatal("★ 空前缀集却判受保护")
|
||
}
|
||
}
|
||
|
||
// TestArchiveBeforeWrite:覆盖前留档,返回 archived=true 且原文可读。
|
||
func TestArchiveBeforeWrite(t *testing.T) {
|
||
base := t.TempDir()
|
||
// 用导出的配置入口把该目录设为受保护范围(不改全局默认值的语义之外)
|
||
protected := filepath.Join(base, "etc")
|
||
system.SetProtectedPaths([]string{protected + string(os.PathSeparator)})
|
||
t.Cleanup(func() { system.SetProtectedPaths(nil) })
|
||
if err := os.MkdirAll(protected, 0755); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
target := filepath.Join(protected, "config.txt")
|
||
if err := os.WriteFile(target, []byte("original"), 0644); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
archived, err := system.ArchiveBeforeWrite(base, target)
|
||
if err != nil {
|
||
t.Fatalf("ArchiveBeforeWrite: %v", err)
|
||
}
|
||
if !archived {
|
||
t.Fatal("★ 已存在的文件却没留档")
|
||
}
|
||
// 留档目录是导出的 FileBaselineDir
|
||
baseline := system.FileBaselineDir(base)
|
||
if baseline == "" {
|
||
t.Fatal("★ FileBaselineDir 为空")
|
||
}
|
||
}
|
||
|
||
// TestNetworkBaselinePathIsStable:路径输出稳定且落在 dataDir 下。
|
||
func TestNetworkBaselinePathIsStable(t *testing.T) {
|
||
dir := t.TempDir()
|
||
a := system.NetworkBaselinePath(dir)
|
||
b := system.NetworkBaselinePath(dir)
|
||
if a == "" || a != b {
|
||
t.Fatalf("★ NetworkBaselinePath 不稳定:%q vs %q", a, b)
|
||
}
|
||
}
|
||
|
||
// TestLoadBaselineMissingReportsError:读不存在的基线必须报错。
|
||
func TestLoadBaselineMissingReportsError(t *testing.T) {
|
||
if _, err := system.LoadNetworkBaseline(t.TempDir()); err == nil {
|
||
t.Fatal("★ 读不存在的基线却返回成功")
|
||
}
|
||
}
|