package startup import ( "context" "errors" "testing" "time" ) func TestRetryRecoversWithoutOpeningLoginEarly(t *testing.T) { b := New(time.Now()) b.Add("tls", "tls") calls := 0 err := b.Retry(context.Background(), "tls", time.Second, time.Millisecond, func() error { calls++ if b.Snapshot().Ready { t.Error("ready before success") } if calls < 3 { return errors.New("temporary") } return nil }, nil) if err != nil || calls != 3 || !b.Snapshot().Ready { t.Fatalf("%d %v %+v", calls, err, b.Snapshot()) } } func TestDelayedAttemptNeverOverlapsAndCanRecover(t *testing.T) { b := New(time.Now()) b.Add("tls", "tls") release := make(chan struct{}) done := make(chan error, 1) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() go func() { done <- b.Retry(ctx, "tls", time.Millisecond, time.Millisecond, func() error { <-release; return nil }, nil) }() for b.Snapshot().State != "delayed" { select { case <-ctx.Done(): t.Fatal("no delayed state") default: time.Sleep(time.Millisecond) } } if b.Snapshot().Ready { t.Fatal("waiting opened login") } close(release) if err := <-done; err != nil || !b.Snapshot().Ready { t.Fatalf("%v %+v", err, b.Snapshot()) } }