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