package permission import ( "fmt" "sync" "testing" ) func TestPermissionDedup_NewID(t *testing.T) { d := NewPermissionDedup(0) // 使用默认容量 if d.IsResolved("tool_use_123") { t.Error("新 ID 不应被标记为已处理") } } func TestPermissionDedup_MarkAndCheck(t *testing.T) { d := NewPermissionDedup(0) d.MarkResolved("tool_use_123") if !d.IsResolved("tool_use_123") { t.Error("已标记的 ID 应返回 true") } if d.IsResolved("tool_use_456") { t.Error("未标记的 ID 应返回 false") } if d.Size() != 1 { t.Errorf("期望 size=1,实际 %d", d.Size()) } } func TestPermissionDedup_DuplicateMark(t *testing.T) { d := NewPermissionDedup(0) d.MarkResolved("tool_use_123") d.MarkResolved("tool_use_123") // 重复标记 if d.Size() != 1 { t.Errorf("重复标记后 size 应为 1,实际 %d", d.Size()) } } func TestPermissionDedup_FIFOEviction(t *testing.T) { // 容量设为 3 d := NewPermissionDedup(3) d.MarkResolved("id_1") d.MarkResolved("id_2") d.MarkResolved("id_3") if d.Size() != 3 { t.Fatalf("期望 size=3,实际 %d", d.Size()) } // 添加第 4 个,应淘汰 id_1(最早的) d.MarkResolved("id_4") if d.Size() != 3 { t.Errorf("淘汰后 size 应为 3,实际 %d", d.Size()) } if d.IsResolved("id_1") { t.Error("id_1 应该被淘汰") } if !d.IsResolved("id_2") { t.Error("id_2 应该还在") } if !d.IsResolved("id_3") { t.Error("id_3 应该还在") } if !d.IsResolved("id_4") { t.Error("id_4 应该在") } } func TestPermissionDedup_FIFOEvictionOrder(t *testing.T) { d := NewPermissionDedup(2) d.MarkResolved("a") d.MarkResolved("b") // 满了,添加 c 淘汰 a d.MarkResolved("c") if d.IsResolved("a") { t.Error("a 应被淘汰") } if !d.IsResolved("b") { t.Error("b 应在") } if !d.IsResolved("c") { t.Error("c 应在") } // 再添加 d 淘汰 b d.MarkResolved("d") if d.IsResolved("b") { t.Error("b 应被淘汰") } if !d.IsResolved("c") { t.Error("c 应在") } if !d.IsResolved("d") { t.Error("d 应在") } } func TestPermissionDedup_ConcurrentSafety(t *testing.T) { d := NewPermissionDedup(100) var wg sync.WaitGroup // 多个 goroutine 并发读写 for i := 0; i < 50; i++ { wg.Add(1) go func(id int) { defer wg.Done() toolID := fmt.Sprintf("tool_use_%d", id) d.MarkResolved(toolID) _ = d.IsResolved(toolID) _ = d.Size() }(i) } wg.Wait() if d.Size() != 50 { t.Errorf("并发完成后期望 size=50,实际 %d", d.Size()) } } func TestPermissionDedup_DefaultMaxSize(t *testing.T) { d := NewPermissionDedup(0) // 应使用默认值 1000 // 验证可以存到 1000 条 for i := 0; i < 1000; i++ { d.MarkResolved(fmt.Sprintf("id_%d", i)) } if d.Size() != 1000 { t.Errorf("期望 size=1000,实际 %d", d.Size()) } // 第 1001 条应淘汰最早的 d.MarkResolved("id_overflow") if d.Size() != 1000 { t.Errorf("溢出后 size 应保持 1000,实际 %d", d.Size()) } if d.IsResolved("id_0") { t.Error("id_0 应被淘汰") } if !d.IsResolved("id_overflow") { t.Error("id_overflow 应在") } }