github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/changestream/worker_test.go (about) 1 // Copyright 2023 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 package changestream 4 5 import ( 6 "time" 7 8 "github.com/juju/clock" 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 "github.com/juju/worker/v3" 12 "github.com/juju/worker/v3/workertest" 13 gc "gopkg.in/check.v1" 14 15 coredatabase "github.com/juju/juju/core/database" 16 "github.com/juju/juju/testing" 17 ) 18 19 type workerSuite struct { 20 baseSuite 21 } 22 23 var _ = gc.Suite(&workerSuite{}) 24 25 func (s *workerSuite) TestValidateConfig(c *gc.C) { 26 defer s.setupMocks(c).Finish() 27 28 cfg := s.getConfig() 29 c.Check(cfg.Validate(), jc.ErrorIsNil) 30 31 cfg.Clock = nil 32 c.Check(errors.Is(cfg.Validate(), errors.NotValid), jc.IsTrue) 33 34 cfg = s.getConfig() 35 cfg.Logger = nil 36 c.Check(errors.Is(cfg.Validate(), errors.NotValid), jc.IsTrue) 37 38 cfg = s.getConfig() 39 cfg.DBGetter = nil 40 c.Check(errors.Is(cfg.Validate(), errors.NotValid), jc.IsTrue) 41 42 cfg = s.getConfig() 43 cfg.FileNotifyWatcher = nil 44 c.Check(errors.Is(cfg.Validate(), errors.NotValid), jc.IsTrue) 45 46 cfg = s.getConfig() 47 cfg.NewEventQueueWorker = nil 48 c.Check(errors.Is(cfg.Validate(), errors.NotValid), jc.IsTrue) 49 } 50 51 func (s *workerSuite) getConfig() WorkerConfig { 52 return WorkerConfig{ 53 DBGetter: s.dbGetter, 54 FileNotifyWatcher: s.fileNotifyWatcher, 55 Clock: s.clock, 56 Logger: s.logger, 57 NewEventQueueWorker: func(coredatabase.TrackedDB, FileNotifier, clock.Clock, Logger) (EventQueueWorker, error) { 58 return nil, nil 59 }, 60 } 61 } 62 63 func (s *workerSuite) TestEventQueue(c *gc.C) { 64 defer s.setupMocks(c).Finish() 65 66 s.expectAnyLogs() 67 s.expectClock() 68 69 s.dbGetter.EXPECT().GetDB("controller").Return(s.TrackedDB(), nil) 70 s.eventQueueWorker.EXPECT().EventQueue().Return(s.eventQueue) 71 s.eventQueueWorker.EXPECT().Kill().AnyTimes() 72 s.eventQueueWorker.EXPECT().Wait().MinTimes(1) 73 74 w := s.newWorker(c, 1) 75 defer workertest.DirtyKill(c, w) 76 77 stream, ok := w.(ChangeStream) 78 c.Assert(ok, jc.IsTrue, gc.Commentf("worker does not implement ChangeStream")) 79 80 _, err := stream.EventQueue("controller") 81 c.Assert(err, jc.ErrorIsNil) 82 83 workertest.CleanKill(c, w) 84 } 85 86 func (s *workerSuite) TestEventQueueCalledTwice(c *gc.C) { 87 defer s.setupMocks(c).Finish() 88 89 s.expectAnyLogs() 90 s.expectClock() 91 92 done := make(chan struct{}) 93 94 s.dbGetter.EXPECT().GetDB("controller").Return(s.TrackedDB(), nil) 95 s.eventQueueWorker.EXPECT().EventQueue().Return(s.eventQueue).Times(2) 96 s.eventQueueWorker.EXPECT().Kill().AnyTimes() 97 s.eventQueueWorker.EXPECT().Wait().DoAndReturn(func() error { 98 select { 99 case <-done: 100 case <-time.After(testing.LongWait): 101 c.Fatal("timed out waiting for Wait to be called") 102 } 103 return nil 104 }) 105 106 w := s.newWorker(c, 1) 107 defer workertest.DirtyKill(c, w) 108 109 stream, ok := w.(ChangeStream) 110 c.Assert(ok, jc.IsTrue, gc.Commentf("worker does not implement ChangeStream")) 111 112 // Ensure that the event queue is only created once. 113 _, err := stream.EventQueue("controller") 114 c.Assert(err, jc.ErrorIsNil) 115 116 _, err = stream.EventQueue("controller") 117 c.Assert(err, jc.ErrorIsNil) 118 119 close(done) 120 121 workertest.CleanKill(c, w) 122 } 123 124 func (s *workerSuite) newWorker(c *gc.C, attempts int) worker.Worker { 125 cfg := WorkerConfig{ 126 DBGetter: s.dbGetter, 127 FileNotifyWatcher: s.fileNotifyWatcher, 128 Clock: s.clock, 129 Logger: s.logger, 130 NewEventQueueWorker: func(coredatabase.TrackedDB, FileNotifier, clock.Clock, Logger) (EventQueueWorker, error) { 131 attempts-- 132 if attempts < 0 { 133 c.Fatal("NewEventQueueWorker called too many times") 134 } 135 return s.eventQueueWorker, nil 136 }, 137 } 138 139 w, err := newWorker(cfg) 140 c.Assert(err, jc.ErrorIsNil) 141 return w 142 }