package busretry import ( "context" "errors" "fmt" "strings" "testing" "time" "github.com/nats-io/nats.go" "github.com/nats-io/nats.go/jetstream" ) // Issue 774 (bus blackouts at every user-list reload): only a request that reached no one is asked again, within the // bound; a blackout probe that says the bus answers ends the wait at once. func TestABusThatAnswersNothingIsWaitedOut(t *testing.T) { Bound, FirstWait, MostWait = 60*time.Millisecond, time.Millisecond, 4*time.Millisecond for _, row := range []struct { name string errs []error // what each try answers; the last repeats blackout func() bool tries int // at least atMost int delivered bool }{ {"no responders, then an answer", []error{nats.ErrNoResponders, nats.ErrNoResponders, nil}, nil, 3, 3, true}, {"jetstream not enabled, then an answer", []error{jetstream.ErrJetStreamNotEnabled, nil}, nil, 2, 2, true}, {"said in words by a runtime", []error{errors.New("nats: no responders available for request"), nil}, nil, 2, 2, true}, {"a timeout may have been delivered: never asked again", []error{context.DeadlineExceeded}, nil, 1, 1, false}, {"an answer that refuses is an answer", []error{errors.New("refused")}, nil, 1, 1, false}, {"nobody answers on a bus that answers: the callee is not running", []error{nats.ErrNoResponders}, func() bool { return false }, 1, 1, false}, {"blacked out past the bound: said", []error{jetstream.ErrJetStreamNotEnabledForAccount}, func() bool { return true }, 3, 1000, false}, } { tries := 0 _, err := Do("the test", func() (int, error) { e := row.errs[min(tries, len(row.errs)-1)] tries++ return tries, e }, row.blackout) if tries < row.tries || tries > row.atMost || (err == nil) != row.delivered { t.Errorf("%s: %d tries, %v", row.name, tries, err) } if strings.HasPrefix(row.name, "blacked out") && (!Undelivered(err) || !strings.Contains(fmt.Sprint(err), "the bus answered nothing")) { t.Errorf("%s: %v", row.name, err) } } }