...

Source file src/github.com/docker/go-events/retry_test.go

Documentation: github.com/docker/go-events

     1  package events
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  func TestRetryingSinkBreaker(t *testing.T) {
    11  	testRetryingSink(t, NewBreaker(3, 10*time.Millisecond))
    12  }
    13  
    14  func TestRetryingSinkExponentialBackoff(t *testing.T) {
    15  	testRetryingSink(t, NewExponentialBackoff(ExponentialBackoffConfig{
    16  		Base:   time.Millisecond,
    17  		Factor: time.Millisecond,
    18  		Max:    time.Millisecond * 5,
    19  	}))
    20  }
    21  
    22  func testRetryingSink(t *testing.T, strategy RetryStrategy) {
    23  	const nevents = 100
    24  	ts := newTestSink(t, nevents)
    25  
    26  	// Make a sync that fails most of the time, ensuring that all the events
    27  	// make it through.
    28  	flaky := &flakySink{
    29  		rate: 1.0, // start out always failing.
    30  		Sink: ts,
    31  	}
    32  
    33  	s := NewRetryingSink(flaky, strategy)
    34  
    35  	var wg sync.WaitGroup
    36  	for i := 1; i <= nevents; i++ {
    37  		event := "myevent-" + fmt.Sprint(i)
    38  
    39  		// Above 50, set the failure rate lower
    40  		if i > 50 {
    41  			flaky.mu.Lock()
    42  			flaky.rate = 0.9
    43  			flaky.mu.Unlock()
    44  		}
    45  
    46  		wg.Add(1)
    47  		go func(event Event) {
    48  			defer wg.Done()
    49  			if err := s.Write(event); err != nil {
    50  				t.Fatalf("error writing event: %v", err)
    51  			}
    52  		}(event)
    53  	}
    54  
    55  	wg.Wait()
    56  	checkClose(t, s)
    57  
    58  	ts.mu.Lock()
    59  	defer ts.mu.Unlock()
    60  }
    61  
    62  func TestExponentialBackoff(t *testing.T) {
    63  	strategy := NewExponentialBackoff(DefaultExponentialBackoffConfig)
    64  	backoff := strategy.Proceed(nil)
    65  
    66  	if backoff != 0 {
    67  		t.Errorf("untouched backoff should be zero-wait: %v != 0", backoff)
    68  	}
    69  
    70  	expected := strategy.config.Base + strategy.config.Factor
    71  	for i := 1; i <= 10; i++ {
    72  		if strategy.Failure(nil, nil) {
    73  			t.Errorf("no facilities for dropping events in ExponentialBackoff")
    74  		}
    75  
    76  		for j := 0; j < 1000; j++ {
    77  			// sample this several thousand times.
    78  			backoff := strategy.Proceed(nil)
    79  			if backoff > expected {
    80  				t.Fatalf("expected must be bounded by %v after %v failures: %v", expected, i, backoff)
    81  			}
    82  		}
    83  
    84  		expected = strategy.config.Base + strategy.config.Factor*time.Duration(1<<uint64(i))
    85  		if expected > strategy.config.Max {
    86  			expected = strategy.config.Max
    87  		}
    88  	}
    89  
    90  	strategy.Success(nil) // recovery!
    91  
    92  	backoff = strategy.Proceed(nil)
    93  	if backoff != 0 {
    94  		t.Errorf("should have recovered: %v != 0", backoff)
    95  	}
    96  }
    97  

View as plain text