github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/worker/resumer/resumer_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package resumer_test
     5  
     6  import (
     7  	"errors"
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/state"
    16  	coretesting "github.com/juju/juju/testing"
    17  	"github.com/juju/juju/worker/resumer"
    18  )
    19  
    20  type ResumerSuite struct {
    21  	coretesting.BaseSuite
    22  
    23  	mockState *transactionResumerMock
    24  }
    25  
    26  var _ = gc.Suite(&ResumerSuite{})
    27  
    28  // Ensure *state.State implements TransactionResumer
    29  var _ resumer.TransactionResumer = (*state.State)(nil)
    30  
    31  func (s *ResumerSuite) SetUpTest(c *gc.C) {
    32  	s.BaseSuite.SetUpTest(c)
    33  
    34  	s.mockState = &transactionResumerMock{
    35  		Stub: &testing.Stub{},
    36  	}
    37  }
    38  
    39  func (s *ResumerSuite) TestRunStopWithMockState(c *gc.C) {
    40  	rr := resumer.NewResumer(s.mockState)
    41  	c.Assert(rr.Stop(), gc.IsNil)
    42  }
    43  
    44  func (s *ResumerSuite) TestResumerCalls(c *gc.C) {
    45  	// Shorter interval and mock help to count
    46  	// the resumer calls in a given timespan.
    47  	testInterval := coretesting.ShortWait
    48  	resumer.SetInterval(testInterval)
    49  	defer resumer.RestoreInterval()
    50  
    51  	rr := resumer.NewResumer(s.mockState)
    52  	defer func() { c.Assert(rr.Stop(), gc.IsNil) }()
    53  
    54  	time.Sleep(10 * testInterval)
    55  
    56  	s.mockState.CheckTimestamps(c, testInterval)
    57  }
    58  
    59  func (s *ResumerSuite) TestResumeTransactionsFailure(c *gc.C) {
    60  	// Force the first call to ResumeTransactions() to fail, the
    61  	// remaining returning no error.
    62  	s.mockState.SetErrors(errors.New("boom!"))
    63  
    64  	// Shorter interval and mock help to count
    65  	// the resumer calls in a given timespan.
    66  	testInterval := coretesting.ShortWait
    67  	resumer.SetInterval(testInterval)
    68  	defer resumer.RestoreInterval()
    69  
    70  	rr := resumer.NewResumer(s.mockState)
    71  	defer func() { c.Assert(rr.Stop(), gc.IsNil) }()
    72  
    73  	// For 4 intervals between 2 and 3 calls should be made.
    74  	time.Sleep(4 * testInterval)
    75  	s.mockState.CheckNumCallsBetween(c, 2, 3)
    76  }
    77  
    78  // transactionResumerMock is used to check the
    79  // calls of ResumeTransactions().
    80  type transactionResumerMock struct {
    81  	*testing.Stub
    82  
    83  	mu         sync.Mutex
    84  	timestamps []time.Time
    85  }
    86  
    87  func (tr *transactionResumerMock) ResumeTransactions() error {
    88  	tr.mu.Lock()
    89  	defer tr.mu.Unlock()
    90  
    91  	tr.timestamps = append(tr.timestamps, time.Now())
    92  	tr.MethodCall(tr, "ResumeTransactions")
    93  	return tr.NextErr()
    94  }
    95  
    96  func (tr *transactionResumerMock) CheckNumCallsBetween(c *gc.C, minCalls, maxCalls int) {
    97  	tr.mu.Lock()
    98  	defer tr.mu.Unlock()
    99  
   100  	// To combat test flakyness (see bug #1462412) we're expecting up
   101  	// to maxCalls, but at least minCalls.
   102  	calls := tr.Stub.Calls()
   103  	c.Assert(len(calls), jc.GreaterThan, minCalls-1)
   104  	c.Assert(len(calls), jc.LessThan, maxCalls+1)
   105  	for _, call := range calls {
   106  		c.Check(call.FuncName, gc.Equals, "ResumeTransactions")
   107  	}
   108  }
   109  
   110  func (tr *transactionResumerMock) CheckTimestamps(c *gc.C, testInterval time.Duration) {
   111  	// Check that a number of calls has happened with a time
   112  	// difference somewhere between the interval and twice the
   113  	// interval. A more precise time behavior cannot be
   114  	// specified due to the load during the test.
   115  	tr.mu.Lock()
   116  	defer tr.mu.Unlock()
   117  
   118  	longestInterval := 4 * testInterval
   119  	c.Assert(len(tr.timestamps) > 0, jc.IsTrue)
   120  	for i := 1; i < len(tr.timestamps); i++ {
   121  		diff := tr.timestamps[i].Sub(tr.timestamps[i-1])
   122  
   123  		c.Assert(diff >= testInterval, jc.IsTrue)
   124  		c.Assert(diff <= longestInterval, jc.IsTrue)
   125  		tr.Stub.CheckCall(c, i-1, "ResumeTransactions")
   126  	}
   127  }
   128  
   129  var _ resumer.TransactionResumer = (*transactionResumerMock)(nil)