11package fileaudit
22
33import (
4+ "context"
45 "os"
56 "path/filepath"
7+ "sync"
68 "testing"
79 "time"
810
11+ "github.com/dagu-org/dagu/internal/service/audit"
912 "github.com/stretchr/testify/assert"
1013 "github.com/stretchr/testify/require"
1114)
@@ -147,9 +150,7 @@ func TestPurgeExpiredFiles_ZeroRetentionSkipsCleanup(t *testing.T) {
147150}
148151
149152func TestCleaner_StopIsIdempotent (t * testing.T ) {
150- dir := t .TempDir ()
151-
152- c := newCleaner (dir , 7 )
153+ c := newTestCleaner (t .TempDir (), 7 )
153154
154155 // Calling stop multiple times should not panic
155156 assert .NotPanics (t , func () {
@@ -168,6 +169,57 @@ func TestPurgeExpiredFiles_NonexistentDirectory(t *testing.T) {
168169 })
169170}
170171
172+ func TestPurgeExpiredFiles_LogsCleanupAuditEntry (t * testing.T ) {
173+ dir := t .TempDir ()
174+
175+ // Create two expired files with known dates
176+ oldDate := time .Now ().UTC ().AddDate (0 , 0 , - 30 ).Format (dateFormat )
177+ olderDate := time .Now ().UTC ().AddDate (0 , 0 , - 31 ).Format (dateFormat )
178+ createTestFile (t , dir , oldDate + auditFileExtension )
179+ createTestFile (t , dir , olderDate + auditFileExtension )
180+
181+ var mu sync.Mutex
182+ var entries []* audit.Entry
183+ fn := func (_ context.Context , entry * audit.Entry ) error {
184+ mu .Lock ()
185+ defer mu .Unlock ()
186+ entries = append (entries , entry )
187+ return nil
188+ }
189+
190+ c := & cleaner {baseDir : dir , retentionDays : 7 , appendFn : fn , stopCh : make (chan struct {})}
191+ c .purgeExpiredFiles ()
192+
193+ require .Len (t , entries , 1 )
194+ assert .Equal (t , audit .CategorySystem , entries [0 ].Category )
195+ assert .Equal (t , "audit_cleanup" , entries [0 ].Action )
196+ assert .Equal (t , "" , entries [0 ].UserID )
197+ assert .Equal (t , "system" , entries [0 ].Username )
198+ assert .Contains (t , entries [0 ].Details , `"files_removed":2` )
199+ assert .Contains (t , entries [0 ].Details , `"retention_days":7` )
200+ assert .Contains (t , entries [0 ].Details , `"purged_from"` )
201+ assert .Contains (t , entries [0 ].Details , `"purged_to"` )
202+ }
203+
204+ func TestPurgeExpiredFiles_NoEntryWhenNothingPurged (t * testing.T ) {
205+ dir := t .TempDir ()
206+
207+ // Create only a recent file — nothing to purge
208+ recentDate := time .Now ().UTC ().AddDate (0 , 0 , - 1 ).Format (dateFormat )
209+ createTestFile (t , dir , recentDate + auditFileExtension )
210+
211+ called := false
212+ fn := func (_ context.Context , _ * audit.Entry ) error {
213+ called = true
214+ return nil
215+ }
216+
217+ c := & cleaner {baseDir : dir , retentionDays : 7 , appendFn : fn , stopCh : make (chan struct {})}
218+ c .purgeExpiredFiles ()
219+
220+ assert .False (t , called , "appendFn should not be called when no files are purged" )
221+ }
222+
171223func TestPurgeExpiredFiles_BoundaryDate (t * testing.T ) {
172224 dir := t .TempDir ()
173225
0 commit comments