From d216e157c300fb603eac402b8e67573c6cf26e70 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Thu, 23 Jul 2026 02:09:02 +0800 Subject: [PATCH] =?UTF-8?q?test(agent):=20=E8=A6=86=E7=9B=96=20acl.json=20?= =?UTF-8?q?=E8=A2=AB=E5=88=A0=E6=97=B6=E4=BB=8D=E8=B5=B0=20last-good=20?= =?UTF-8?q?=E5=85=9C=E5=BA=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删文件走的是 LoadACLConfig 返回 (nil,nil) 的分支,与坏 JSON 的 err!=nil 分支不同,此前无回归覆盖。 Co-Authored-By: Claude Opus 4.8 --- server/internal/agentd/acl_test.go | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/server/internal/agentd/acl_test.go b/server/internal/agentd/acl_test.go index 390f53e..7100b9a 100644 --- a/server/internal/agentd/acl_test.go +++ b/server/internal/agentd/acl_test.go @@ -416,3 +416,49 @@ func TestACL_NeverConfiguredYieldsNoRoute(t *testing.T) { t.Error("未配置 ACL 也未启用 WARP,不应产出 route 块") } } + +// acl.json 被删除 → 规则不能消失(内存 last-good 兜底)。 +func TestACL_DeletedFileKeepsInMemoryLastGood(t *testing.T) { + cfg := testConfig(t) + writeACL(t, cfg.ACLConfigPath, validACL) + sb := NewSingBox(cfg, nil) + sb.ApplyConfig(sampleSnapshot(&agentv1.Credential{DpUUID: "aaaa", Protocol: agentv1.ProtocolBoth}), true) + if _, err := sb.RenderConfig(); err != nil { + t.Fatal(err) + } + + if err := os.Remove(cfg.ACLConfigPath); err != nil { + t.Fatalf("failed to remove acl.json: %v", err) + } + data, err := sb.RenderConfig() + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(data), "reject") { + t.Fatal("acl.json 被删除后拒绝规则消失了 —— 这是 fail-open,私有服务已敞开") + } +} + +// 新 agent 实例(模拟进程重启) + 被删的 acl.json → 磁盘 last-good 兜底,规则仍在。 +func TestACL_ColdStartAfterDeletedFileFallsBackToDisk(t *testing.T) { + cfg := testConfig(t) + writeACL(t, cfg.ACLConfigPath, validACL) + sb1 := NewSingBox(cfg, nil) + sb1.ApplyConfig(sampleSnapshot(&agentv1.Credential{DpUUID: "aaaa", Protocol: agentv1.ProtocolBoth}), true) + if _, err := sb1.RenderConfig(); err != nil { + t.Fatal(err) + } + + if err := os.Remove(cfg.ACLConfigPath); err != nil { + t.Fatalf("failed to remove acl.json: %v", err) + } + sb2 := NewSingBox(cfg, nil) // 全新实例,内存 last-good 为空 + sb2.ApplyConfig(sampleSnapshot(&agentv1.Credential{DpUUID: "aaaa", Protocol: agentv1.ProtocolBoth}), true) + data, err := sb2.RenderConfig() + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(data), "reject") { + t.Fatal("冷启动(acl.json 删除)未回退到磁盘 last-good,私有服务已敞开") + } +}