| package backoff |
| |
| import ( |
| "context" |
| "errors" |
| "fmt" |
| "log" |
| "testing" |
| "time" |
| ) |
| |
| func TestTicker(t *testing.T) { |
| const successOn = 3 |
| var i = 0 |
| |
| // This function is successful on "successOn" calls. |
| f := func() error { |
| i++ |
| log.Printf("function is called %d. time\n", i) |
| |
| if i == successOn { |
| log.Println("OK") |
| return nil |
| } |
| |
| log.Println("error") |
| return errors.New("error") |
| } |
| |
| b := NewExponentialBackOff() |
| ticker := NewTicker(b) |
| elapsed := b.GetElapsedTime() |
| if elapsed > time.Second { |
| t.Errorf("elapsed time too large: %v", elapsed) |
| } |
| |
| var err error |
| for _ = range ticker.C { |
| if err = f(); err != nil { |
| t.Log(err) |
| continue |
| } |
| |
| break |
| } |
| if err != nil { |
| t.Errorf("unexpected error: %s", err.Error()) |
| } |
| if i != successOn { |
| t.Errorf("invalid number of retries: %d", i) |
| } |
| } |
| |
| func TestTickerContext(t *testing.T) { |
| const cancelOn = 3 |
| var i = 0 |
| |
| ctx, cancel := context.WithCancel(context.Background()) |
| defer cancel() |
| |
| // This function cancels context on "cancelOn" calls. |
| f := func() error { |
| i++ |
| log.Printf("function is called %d. time\n", i) |
| |
| // cancelling the context in the operation function is not a typical |
| // use-case, however it allows to get predictable test results. |
| if i == cancelOn { |
| cancel() |
| } |
| |
| log.Println("error") |
| return fmt.Errorf("error (%d)", i) |
| } |
| |
| b := WithContext(NewConstantBackOff(time.Millisecond), ctx) |
| ticker := NewTicker(b) |
| |
| var err error |
| for _ = range ticker.C { |
| if err = f(); err != nil { |
| t.Log(err) |
| continue |
| } |
| |
| break |
| } |
| if err == nil { |
| t.Errorf("error is unexpectedly nil") |
| } |
| if err.Error() != "error (3)" { |
| t.Errorf("unexpected error: %s", err.Error()) |
| } |
| if i != cancelOn { |
| t.Errorf("invalid number of retries: %d", i) |
| } |
| } |