owpengram-server/internal/store/memory/moderation_test.go
2026-07-24 11:56:59 +08:00

92 lines
3.3 KiB
Go

package memory
import (
"context"
"testing"
"time"
"telesrv/internal/domain"
)
func TestModerationReportStoreIdempotencyAndCopyIsolation(t *testing.T) {
report, err := domain.NewModerationReport(domain.ModerationReportDraft{
ReporterUserID: 11, Source: domain.ModerationSourceMessages,
Target: domain.Peer{Type: domain.PeerTypeUser, ID: 22},
Reason: domain.ModerationReasonSpam, Option: "v1/spam",
Items: []domain.ModerationReportItem{{
Kind: domain.ModerationItemMessage,
Peer: domain.Peer{Type: domain.PeerTypeUser, ID: 22},
ItemID: 5, AuthorUserID: 22, EvidenceSchemaVersion: 1,
Evidence: []byte(`{"message":"spam"}`),
}},
CreatedAt: time.Now().UTC(),
})
if err != nil {
t.Fatal(err)
}
store := NewModerationReportStore()
first, created, err := store.CreateModerationReport(context.Background(), report)
if err != nil || !created || first.ID <= 0 {
t.Fatalf("first = %+v created=%v err=%v", first, created, err)
}
first.Items[0].Evidence[0] = '['
retry, created, err := store.CreateModerationReport(context.Background(), report)
if err != nil || created || retry.ID != first.ID {
t.Fatalf("retry = %+v created=%v err=%v", retry, created, err)
}
if retry.Items[0].Evidence[0] != '{' {
t.Fatalf("caller mutation changed stored evidence: %s", retry.Items[0].Evidence)
}
}
func TestModerationReportStoreRateLimitDoesNotChargeIdempotentRetry(t *testing.T) {
ctx := context.Background()
store := NewModerationReportStore()
now := time.Unix(1_750_000_000, 0).UTC()
var first domain.ModerationReport
for i := 0; i < domain.MaxModerationReportsPerHour; i++ {
report, err := domain.NewModerationReport(domain.ModerationReportDraft{
ReporterUserID: 71, Source: domain.ModerationSourceMessages,
Target: domain.Peer{Type: domain.PeerTypeUser, ID: 72},
Reason: domain.ModerationReasonSpam, Option: "spam",
Items: []domain.ModerationReportItem{{
Kind: domain.ModerationItemMessage,
Peer: domain.Peer{Type: domain.PeerTypeUser, ID: 72},
ItemID: int64(i + 1), AuthorUserID: 72,
EvidenceSchemaVersion: 1,
Evidence: []byte(`{"message":"spam"}`),
}},
CreatedAt: now,
})
if err != nil {
t.Fatal(err)
}
if _, created, err := store.CreateModerationReport(ctx, report); err != nil || !created {
t.Fatalf("create %d: created=%v err=%v", i, created, err)
}
if i == 0 {
first = report
}
}
if got, created, err := store.CreateModerationReport(ctx, first); err != nil || created || got.ID == 0 {
t.Fatalf("retry after limit: got=%+v created=%v err=%v", got, created, err)
}
overflow, err := domain.NewModerationReport(domain.ModerationReportDraft{
ReporterUserID: 71, Source: domain.ModerationSourceMessages,
Target: domain.Peer{Type: domain.PeerTypeUser, ID: 72},
Reason: domain.ModerationReasonSpam, Option: "spam",
Items: []domain.ModerationReportItem{{
Kind: domain.ModerationItemMessage,
Peer: domain.Peer{Type: domain.PeerTypeUser, ID: 72},
ItemID: 999, AuthorUserID: 72, EvidenceSchemaVersion: 1,
Evidence: []byte(`{"message":"overflow"}`),
}},
CreatedAt: now,
})
if err != nil {
t.Fatal(err)
}
if _, _, err := store.CreateModerationReport(ctx, overflow); err != domain.ErrModerationRateLimited {
t.Fatalf("overflow err=%v, want ErrModerationRateLimited", err)
}
}