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)