package test import ( "RenewCMS/internal/domain/audit" "RenewCMS/internal/infrastructure/auditing" persistence "RenewCMS/internal/infrastructure/persistence/repositories" "RenewCMS/internal/infrastructure/useCases" "bytes" "context" "errors" "log" "testing" "time" ) var testCtx = context.Background() var discardRecorder audit.Recorder = audit.Discard type activityProbeRepo struct { inner audit.Repository appendErr error appendPanic bool reads int listCalls []audit.Filter deleteErr error deleteCalls int readErr error sizeErr error sizeBytes *int64 oldestErr error oldestCalls int } var _ audit.Repository = &activityProbeRepo{} func (p *activityProbeRepo) Append(event audit.Event) (audit.Event, error) { if p.appendPanic { panic("audit repository exploded") } if p.appendErr != nil { return audit.Event{}, p.appendErr } return p.inner.Append(event) } func (p *activityProbeRepo) List(filter audit.Filter) (audit.Page, error) { p.reads++ p.listCalls = append(p.listCalls, filter) if p.readErr != nil { return audit.Page{}, p.readErr } return p.inner.List(filter) } func (p *activityProbeRepo) Summary(query audit.SummaryQuery) (audit.Summary, error) { p.reads++ if p.readErr != nil { return audit.Summary{}, p.readErr } return p.inner.Summary(query) } func (p *activityProbeRepo) DeleteOlderThan(cutoff time.Time) (int, error) { p.deleteCalls++ if p.deleteErr != nil { return 0, p.deleteErr } return p.inner.DeleteOlderThan(cutoff) } func (p *activityProbeRepo) DeleteOldest(limit int, before time.Time) (int, error) { p.oldestCalls++ if p.oldestErr != nil { return 0, p.oldestErr } return p.inner.DeleteOldest(limit, before) } func (p *activityProbeRepo) SizeBytes() (int64, error) { if p.sizeErr != nil { return 0, p.sizeErr } if p.sizeBytes != nil { return *p.sizeBytes, nil } return p.inner.SizeBytes() } type activitySettingsFake struct { settings audit.Settings saveErr error getErr error retentionOK int cleanupOK int } var _ audit.SettingsRepository = &activitySettingsFake{} func newActivitySettingsFake() *activitySettingsFake { return &activitySettingsFake{settings: audit.DefaultSettings()} } func (f *activitySettingsFake) Get() (audit.Settings, error) { if f.getErr != nil { return audit.Settings{}, f.getErr } return f.settings, nil } func (f *activitySettingsFake) SaveRetention(days int, maxGB int) error { if f.saveErr != nil { return f.saveErr } f.retentionOK++ f.settings.RetentionDays = days f.settings.RetentionMaxGB = maxGB return nil } func (f *activitySettingsFake) SaveLastCleanup(at time.Time, removed int) error { if f.saveErr != nil { return f.saveErr } f.cleanupOK++ f.settings.LastCleanupAt = &at f.settings.LastCleanupRemoved = removed return nil } type activityHarness struct { probe *activityProbeRepo store *persistence.AuditEventRepository settings *activitySettingsFake logs *bytes.Buffer now time.Time recorder *auditing.Recorder } func newActivityHarness(t *testing.T) *activityHarness { t.Helper() store := persistence.NewAuditEventRepository(openActivityDatabase(t)) h := &activityHarness{ probe: &activityProbeRepo{inner: store}, store: store, settings: newActivitySettingsFake(), logs: &bytes.Buffer{}, now: time.Date(2026, time.October, 6, 12, 0, 0, 0, time.UTC), } h.recorder = auditing.NewRecorder(h.probe, func() time.Time { return h.now }, log.New(h.logs, "", 0)) return h } func (h *activityHarness) clock() time.Time { return h.now } func (h *activityHarness) all(t *testing.T) []audit.Event { t.Helper() page, err := h.store.List(audit.Filter{Page: 1, Size: 1000}) if err != nil { t.Fatalf("listing stored events failed: %v", err) } return page.Items } func (h *activityHarness) seed(t *testing.T, event audit.Event) audit.Event { t.Helper() return activityMustAppend(t, h.store, event) } var errDiskFull = errors.New("disk full") func newSizeEvents(t *testing.T) audit.Repository { t.Helper() return persistence.NewAuditEventRepository(openActivityDatabase(t)) } func retentionDays(days int) useCases.UpdateActivityRetentionCommand { return useCases.UpdateActivityRetentionCommand{Days: &days} } func retentionMaxGB(maxGB int) useCases.UpdateActivityRetentionCommand { return useCases.UpdateActivityRetentionCommand{MaxGB: &maxGB} }