github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/worker/charmrevision/worker_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package charmrevision_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 coretesting "github.com/juju/juju/testing" 15 "github.com/juju/juju/worker" 16 "github.com/juju/juju/worker/charmrevision" 17 ) 18 19 type WorkerSuite struct { 20 testing.IsolationSuite 21 } 22 23 var _ = gc.Suite(&WorkerSuite{}) 24 25 func (s *WorkerSuite) TestUpdatesImmediately(c *gc.C) { 26 fix := newFixture(time.Minute) 27 fix.cleanTest(c, func(_ worker.Worker) { 28 fix.waitCall(c) 29 fix.waitNoCall(c) 30 }) 31 fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions") 32 } 33 34 func (s *WorkerSuite) TestNoMoreUpdatesUntilPeriod(c *gc.C) { 35 fix := newFixture(time.Minute) 36 fix.cleanTest(c, func(_ worker.Worker) { 37 fix.waitCall(c) 38 fix.clock.Advance(time.Minute - time.Nanosecond) 39 fix.waitNoCall(c) 40 }) 41 fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions") 42 } 43 44 func (s *WorkerSuite) TestUpdatesAfterPeriod(c *gc.C) { 45 fix := newFixture(time.Minute) 46 fix.cleanTest(c, func(_ worker.Worker) { 47 fix.waitCall(c) 48 if err := fix.clock.WaitAdvance(time.Minute, 1*time.Second, 1); err != nil { 49 c.Fatal(err) 50 } 51 fix.waitCall(c) 52 fix.waitNoCall(c) 53 }) 54 fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions", "UpdateLatestRevisions") 55 } 56 57 func (s *WorkerSuite) TestImmediateUpdateError(c *gc.C) { 58 fix := newFixture(time.Minute) 59 fix.revisionUpdater.stub.SetErrors( 60 errors.New("no updates for you"), 61 ) 62 fix.dirtyTest(c, func(w worker.Worker) { 63 fix.waitCall(c) 64 c.Check(w.Wait(), gc.ErrorMatches, "no updates for you") 65 fix.waitNoCall(c) 66 }) 67 fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions") 68 } 69 70 func (s *WorkerSuite) TestDelayedUpdateError(c *gc.C) { 71 fix := newFixture(time.Minute) 72 fix.revisionUpdater.stub.SetErrors( 73 nil, 74 errors.New("no more updates for you"), 75 ) 76 fix.dirtyTest(c, func(w worker.Worker) { 77 fix.waitCall(c) 78 fix.clock.Advance(time.Minute) 79 fix.waitCall(c) 80 c.Check(w.Wait(), gc.ErrorMatches, "no more updates for you") 81 fix.waitNoCall(c) 82 }) 83 fix.revisionUpdater.stub.CheckCallNames(c, "UpdateLatestRevisions", "UpdateLatestRevisions") 84 } 85 86 // workerFixture isolates a charmrevision worker for testing. 87 type workerFixture struct { 88 revisionUpdater mockRevisionUpdater 89 clock *testing.Clock 90 period time.Duration 91 } 92 93 func newFixture(period time.Duration) workerFixture { 94 return workerFixture{ 95 revisionUpdater: newMockRevisionUpdater(), 96 clock: testing.NewClock(coretesting.ZeroTime()), 97 period: period, 98 } 99 } 100 101 type testFunc func(worker.Worker) 102 103 func (fix workerFixture) cleanTest(c *gc.C, test testFunc) { 104 fix.runTest(c, test, true) 105 } 106 107 func (fix workerFixture) dirtyTest(c *gc.C, test testFunc) { 108 fix.runTest(c, test, false) 109 } 110 111 func (fix workerFixture) runTest(c *gc.C, test testFunc, checkWaitErr bool) { 112 w, err := charmrevision.NewWorker(charmrevision.Config{ 113 RevisionUpdater: fix.revisionUpdater, 114 Clock: fix.clock, 115 Period: fix.period, 116 }) 117 c.Assert(err, jc.ErrorIsNil) 118 defer func() { 119 err := worker.Stop(w) 120 if checkWaitErr { 121 c.Check(err, jc.ErrorIsNil) 122 } 123 }() 124 test(w) 125 } 126 127 func (fix workerFixture) waitCall(c *gc.C) { 128 select { 129 case <-fix.revisionUpdater.calls: 130 case <-time.After(coretesting.LongWait): 131 c.Fatalf("timed out") 132 } 133 } 134 135 func (fix workerFixture) waitNoCall(c *gc.C) { 136 select { 137 case <-fix.revisionUpdater.calls: 138 c.Fatalf("unexpected revisionUpdater call") 139 case <-time.After(coretesting.ShortWait): 140 } 141 } 142 143 // mockRevisionUpdater records (and notifies of) calls made to UpdateLatestRevisions. 144 type mockRevisionUpdater struct { 145 stub *testing.Stub 146 calls chan struct{} 147 } 148 149 func newMockRevisionUpdater() mockRevisionUpdater { 150 return mockRevisionUpdater{ 151 stub: &testing.Stub{}, 152 calls: make(chan struct{}, 1000), 153 } 154 } 155 156 func (mock mockRevisionUpdater) UpdateLatestRevisions() error { 157 mock.stub.AddCall("UpdateLatestRevisions") 158 mock.calls <- struct{}{} 159 return mock.stub.NextErr() 160 }