Files
HomeAgent/internal/supervisor/test/daemon_contract_test.go
JianFeeeee 379300d89c test: 按模块导出接口重写黑盒判据(批次 7:agent-io / system / ipc / supervisor)
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
2026-11-09 13:38:31 +08:00

64 lines
1.8 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/supervisor 的黑盒判据:New(cfg) → RegisterAgent → 状态输出。
// 不启动后台循环、不碰 d.agents。
import (
"testing"
"time"
"github.com/JianFeeeee/HologramAgent/internal/supervisor"
"github.com/JianFeeeee/HologramAgent/pkg/types"
)
func newDaemon() *supervisor.Daemon {
return supervisor.New(&types.Config{Daemon: types.DaemonConfig{
CheckInterval: time.Minute,
HeartbeatInterval: 30 * time.Second,
}})
}
// TestFreshDaemonHasNoAgents:新 daemon 的 ListAgents 为空。
func TestFreshDaemonHasNoAgents(t *testing.T) {
d := newDaemon()
if got := d.ListAgents(); len(got) != 0 {
t.Fatalf("★ 新 daemon 的 ListAgents = %v,期望空", got)
}
}
// TestRegisterThenList:注册后 ListAgents 与 GetAgentStatus 反映该 agent。
func TestRegisterThenList(t *testing.T) {
d := newDaemon()
id := types.AgentID("contract-agent")
d.RegisterAgent(id)
list := d.ListAgents()
if len(list) != 1 {
t.Fatalf("★ ListAgents = %v,期望 1 个", list)
}
st, err := d.GetAgentStatus(id)
if err != nil {
t.Fatalf("GetAgentStatus: %v", err)
}
if st == nil {
t.Fatal("★ 已注册 agent 的状态为 nil")
}
}
// TestGetUnknownAgentReportsError:查未注册 agent 必须报错。
func TestGetUnknownAgentReportsError(t *testing.T) {
d := newDaemon()
if _, err := d.GetAgentStatus(types.AgentID("ghost")); err == nil {
t.Fatal("★ 查未注册 agent 却返回成功")
}
}
// TestSDKAdapterSeesSameAgents:适配层与 Daemon 看到同一份登记。
func TestSDKAdapterSeesSameAgents(t *testing.T) {
d := newDaemon()
d.RegisterAgent(types.AgentID("a1"))
ad := supervisor.NewSDKAdapter(d)
if got := ad.ListAgents(); len(got) != 1 {
t.Fatalf("★ SDKAdapter.ListAgents = %v,期望 1 个", got)
}
}