github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/util/retry_test.go (about)

     1  package util
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/pkg/errors"
     8  	. "github.com/smartystreets/goconvey/convey"
     9  )
    10  
    11  const TestRetries = 5
    12  const TestSleep = 10 * time.Millisecond
    13  const TriesTillPass = 2
    14  
    15  func TestRetriesUsedUp(t *testing.T) {
    16  	Convey("When retrying a function that never succeeds", t, func() {
    17  
    18  		failingFunc := func() error {
    19  			return RetriableError{errors.New("something went wrong")}
    20  		}
    21  
    22  		start := time.Now()
    23  		retryFail, err := Retry(failingFunc, TestRetries, TestSleep)
    24  		end := time.Now()
    25  
    26  		Convey("calling it with Retry should return an error", func() {
    27  			So(err, ShouldNotBeNil)
    28  		})
    29  		Convey("the 'retried till failure' flag should be true", func() {
    30  			So(retryFail, ShouldBeTrue)
    31  		})
    32  		Convey("Time spent doing Retry() should be total time sleeping", func() {
    33  			So(end, ShouldHappenOnOrAfter, start.Add((TestRetries-1)*TestSleep))
    34  		})
    35  	})
    36  }
    37  
    38  func TestRetryUntilSuccess(t *testing.T) {
    39  	Convey("When retrying a function that succeeds after 3 tries", t, func() {
    40  
    41  		tryCounter := TriesTillPass
    42  		retryPassingFunc := func() error {
    43  			tryCounter--
    44  			if tryCounter <= 0 {
    45  				return nil
    46  			}
    47  			return RetriableError{errors.New("something went wrong")}
    48  		}
    49  
    50  		start := time.Now()
    51  		retryFail, err := Retry(retryPassingFunc, TestRetries, TestSleep)
    52  		end := time.Now()
    53  
    54  		Convey("calling it with Retry should not return any error", func() {
    55  			So(err, ShouldBeNil)
    56  		})
    57  		Convey("the 'retried till failure' flag should be false", func() {
    58  			So(retryFail, ShouldBeFalse)
    59  		})
    60  		Convey("time spent should be retry sleep * attempts needed to pass", func() {
    61  			backoff := getBackoff(TestSleep, TestRetries)
    62  
    63  			So(end, ShouldHappenOnOrAfter, start.Add((TriesTillPass-1)*TestSleep))
    64  			So(end, ShouldHappenBefore, start.Add(backoff.Max))
    65  		})
    66  
    67  	})
    68  }
    69  
    70  func TestNonRetriableFailure(t *testing.T) {
    71  	Convey("When retrying a func that returns non-retriable err", t, func() {
    72  		failingFuncNoRetry := func() error {
    73  			return errors.New("something went wrong")
    74  		}
    75  
    76  		retryFail, err := Retry(failingFuncNoRetry, TestRetries, TestSleep)
    77  
    78  		Convey("calling it with Retry should return an error", func() {
    79  			So(err, ShouldNotBeNil)
    80  		})
    81  		Convey("the 'retried till failure' flag should be false", func() {
    82  			So(retryFail, ShouldBeFalse)
    83  		})
    84  	})
    85  }