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