Tests for retry_utils
One can argue about how necessary they are, but at least I remembered how to do golang.
This commit is contained in:
		
							parent
							
								
									60c742a3e8
								
							
						
					
					
						commit
						dd79fcd036
					
				|  | @ -5,14 +5,39 @@ import ( | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Retry calls ConditionFunc until it returns boolean true, a timeout expires or an error occurs.
 | type RetryTicker interface { | ||||||
|  | 	Stop() | ||||||
|  | 	Tick() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Ticker struct { | ||||||
|  | 	ticker *time.Ticker | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Ticker) Stop() { t.ticker.Stop() } | ||||||
|  | 
 | ||||||
|  | func (t *Ticker) Tick() { <-t.ticker.C } | ||||||
|  | 
 | ||||||
|  | // Retry calls ConditionFunc until either:
 | ||||||
|  | // * it returns boolean true
 | ||||||
|  | // * a timeout expires
 | ||||||
|  | // * an error occurs
 | ||||||
| func Retry(interval time.Duration, timeout time.Duration, f func() (bool, error)) error { | func Retry(interval time.Duration, timeout time.Duration, f func() (bool, error)) error { | ||||||
| 	//TODO: make the retry exponential
 | 	//TODO: make the retry exponential
 | ||||||
| 	if timeout < interval { | 	if timeout < interval { | ||||||
| 		return fmt.Errorf("timout(%s) should be greater than interval(%v)", timeout, interval) | 		return fmt.Errorf("timout(%s) should be greater than interval(%v)", timeout, interval) | ||||||
| 	} | 	} | ||||||
|  | 	tick := &Ticker{time.NewTicker(interval)} | ||||||
|  | 	return RetryWorker(interval, timeout, f, tick) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func RetryWorker( | ||||||
|  | 	interval time.Duration, | ||||||
|  | 	timeout time.Duration, | ||||||
|  | 	f func() (bool, error), | ||||||
|  | 	tick RetryTicker) error { | ||||||
|  | 
 | ||||||
| 	maxRetries := int(timeout / interval) | 	maxRetries := int(timeout / interval) | ||||||
| 	tick := time.NewTicker(interval) |  | ||||||
| 	defer tick.Stop() | 	defer tick.Stop() | ||||||
| 
 | 
 | ||||||
| 	for i := 0; ; i++ { | 	for i := 0; ; i++ { | ||||||
|  | @ -26,7 +51,7 @@ func Retry(interval time.Duration, timeout time.Duration, f func() (bool, error) | ||||||
| 		if i+1 == maxRetries { | 		if i+1 == maxRetries { | ||||||
| 			break | 			break | ||||||
| 		} | 		} | ||||||
| 		<-tick.C | 		tick.Tick() | ||||||
| 	} | 	} | ||||||
| 	return fmt.Errorf("still failing after %d retries", maxRetries) | 	return fmt.Errorf("still failing after %d retries", maxRetries) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,68 @@ | ||||||
|  | package retryutil | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type mockTicker struct { | ||||||
|  | 	test    *testing.T | ||||||
|  | 	counter int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *mockTicker) Stop() {} | ||||||
|  | 
 | ||||||
|  | func (t *mockTicker) Tick() { | ||||||
|  | 	t.counter += 1 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestRetryWorkerSuccess(t *testing.T) { | ||||||
|  | 	tick := &mockTicker{t, 0} | ||||||
|  | 	result := RetryWorker(10, 20, func() (bool, error) { | ||||||
|  | 		return true, nil | ||||||
|  | 	}, tick) | ||||||
|  | 
 | ||||||
|  | 	if result != nil { | ||||||
|  | 		t.Errorf("Wrong result, expected: %#v, got: %#v", nil, result) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if tick.counter != 0 { | ||||||
|  | 		t.Errorf("Ticker was started once, but it shouldn't be") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestRetryWorkerOneFalse(t *testing.T) { | ||||||
|  | 	var counter = 0 | ||||||
|  | 
 | ||||||
|  | 	tick := &mockTicker{t, 0} | ||||||
|  | 	result := RetryWorker(1, 3, func() (bool, error) { | ||||||
|  | 		counter += 1 | ||||||
|  | 
 | ||||||
|  | 		if counter <= 1 { | ||||||
|  | 			return false, nil | ||||||
|  | 		} else { | ||||||
|  | 			return true, nil | ||||||
|  | 		} | ||||||
|  | 	}, tick) | ||||||
|  | 
 | ||||||
|  | 	if result != nil { | ||||||
|  | 		t.Errorf("Wrong result, expected: %#v, got: %#v", nil, result) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if tick.counter != 1 { | ||||||
|  | 		t.Errorf("Ticker was started %#v, but supposed to be just once", tick.counter) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestRetryWorkerError(t *testing.T) { | ||||||
|  | 	fail := errors.New("Error") | ||||||
|  | 
 | ||||||
|  | 	tick := &mockTicker{t, 0} | ||||||
|  | 	result := RetryWorker(1, 3, func() (bool, error) { | ||||||
|  | 		return false, fail | ||||||
|  | 	}, tick) | ||||||
|  | 
 | ||||||
|  | 	if result != fail { | ||||||
|  | 		t.Errorf("Wrong result, expected: %#v, got: %#v", fail, result) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue