// Copyright 2026 tamakyi. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package db import ( "context" "testing" "time" "github.com/stretchr/testify/require" ) // TestBanRecordStore 覆盖自动封禁账本的写入与检索。 // // 这张表不参与判定(IsBanned 只读内存),所以测试只锁两件事: // ① 记录能落库并按时间倒序取回;② 到期时间与时长原样保留 —— // 事后排查全依赖这两个字段回答「封了多久、什么时候解」。 func TestBanRecordStore(t *testing.T) { database, cleanup := newTestDB(t) ctx := context.Background() t.Cleanup(func() { if err := cleanup("ban_records"); err != nil { t.Fatal(err) } }) store := NewBanRecordsStore(database) now := time.Now() rows := []*BanRecord{ {BanKey: "1.2.3.4", Reason: "敏感路径探测", DurationMinutes: 60, ExpiresAt: now.Add(time.Hour), CreatedAt: now.Add(-2 * time.Hour)}, {BanKey: "2001:db8::/64", Reason: "蜜罐提交凭据", DurationMinutes: 1440, ExpiresAt: now.Add(24 * time.Hour), CreatedAt: now.Add(-10 * time.Minute)}, } for _, r := range rows { require.NoError(t, store.Create(ctx, r)) } got, err := store.ListSince(ctx, now.Add(-3*time.Hour), 10) require.NoError(t, err) require.Len(t, got, 2) // 时间倒序:最新的一条在最前 require.Equal(t, "2001:db8::/64", got[0].BanKey) require.Equal(t, "蜜罐提交凭据", got[0].Reason) require.Equal(t, 1440, got[0].DurationMinutes) require.False(t, got[0].ExpiresAt.IsZero(), "到期时间必须保留,否则无法回答「什么时候解」") // 时间窗过滤生效 recent, err := store.ListSince(ctx, now.Add(-30*time.Minute), 10) require.NoError(t, err) require.Len(t, recent, 1) require.Equal(t, "2001:db8::/64", recent[0].BanKey) }