package daemon import ( "context" "errors" "log/slog" "testing" "time" "s3watch/internal/syncer" ) func TestRunOnceRunsHookOnlyWhenChanged(t *testing.T) { tests := []struct { name string result syncer.Result wantCalls int }{ { name: "changed", result: syncer.Result{Downloaded: 1}, wantCalls: 1, }, { name: "unchanged", result: syncer.Result{Unchanged: 1}, wantCalls: 0, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { hook := &fakeHook{} err := Run(context.Background(), Config{Interval: time.Second, Once: true}, fakeSyncer{result: tt.result}, hook, slog.New(slog.DiscardHandler)) if err != nil { t.Fatalf("Run() error = %v", err) } if hook.calls != tt.wantCalls { t.Fatalf("hook calls = %d, want %d", hook.calls, tt.wantCalls) } }) } } func TestRunOnceReturnsHookError(t *testing.T) { wantErr := errors.New("hook failed") err := Run( context.Background(), Config{Interval: time.Second, Once: true}, fakeSyncer{result: syncer.Result{Updated: 1}}, &fakeHook{err: wantErr}, slog.New(slog.DiscardHandler), ) if !errors.Is(err, wantErr) { t.Fatalf("Run() error = %v, want %v", err, wantErr) } } type fakeSyncer struct { result syncer.Result err error } func (f fakeSyncer) Sync(context.Context) (syncer.Result, error) { return f.result, f.err } type fakeHook struct { calls int err error } func (f *fakeHook) Run(context.Context, syncer.Result) error { f.calls++ return f.err }