package banksync import ( "context" "errors" "io" "testing" ) func TestRunner_RecordsStatus(t *testing.T) { r := NewRunner(func(context.Context, io.Writer) error { return nil }) if _, ok := r.Last(); ok { t.Fatal("Last before any run: want ok=false") } if err := r.Run(context.Background(), "scheduled", io.Discard); err != nil { t.Fatal(err) } st, ok := r.Last() if !ok || st.Trigger != "scheduled" || st.Err != nil || st.Finished.Before(st.Started) { t.Errorf("unexpected status %+v ok=%v", st, ok) } } func TestRunner_RecordsError(t *testing.T) { boom := errors.New("boom") r := NewRunner(func(context.Context, io.Writer) error { return boom }) if err := r.Run(context.Background(), "manual", io.Discard); !errors.Is(err, boom) { t.Fatalf("Run err = %v, want boom", err) } if st, _ := r.Last(); !errors.Is(st.Err, boom) || st.Trigger != "manual" { t.Errorf("unexpected status %+v", st) } } func TestRunner_BusyWhileRunning(t *testing.T) { started := make(chan struct{}) release := make(chan struct{}) first := true r := NewRunner(func(context.Context, io.Writer) error { if first { // runs are serialised by Runner, so no extra locking is needed first = false close(started) <-release } return nil }) done := make(chan error, 1) go func() { done <- r.Run(context.Background(), "scheduled", io.Discard) }() <-started if err := r.Run(context.Background(), "manual", io.Discard); !errors.Is(err, ErrBusy) { t.Errorf("second Run err = %v, want ErrBusy", err) } close(release) if err := <-done; err != nil { t.Fatal(err) } // The skipped run must not overwrite the status of the real one. if st, _ := r.Last(); st.Trigger != "scheduled" { t.Errorf("Last trigger = %q, want scheduled", st.Trigger) } if err := r.Run(context.Background(), "manual", io.Discard); err != nil { t.Errorf("Run after release: %v", err) } }