github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/singular/manifold_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package singular_test 5 6 import ( 7 "time" 8 9 "github.com/juju/clock/testclock" 10 "github.com/juju/errors" 11 "github.com/juju/names/v5" 12 "github.com/juju/testing" 13 jc "github.com/juju/testing/checkers" 14 "github.com/juju/worker/v3" 15 "github.com/juju/worker/v3/dependency" 16 dt "github.com/juju/worker/v3/dependency/testing" 17 gc "gopkg.in/check.v1" 18 19 "github.com/juju/juju/api/base" 20 "github.com/juju/juju/cmd/jujud/agent/engine" 21 coretesting "github.com/juju/juju/testing" 22 "github.com/juju/juju/worker/singular" 23 ) 24 25 type ManifoldSuite struct { 26 testing.IsolationSuite 27 28 config singular.ManifoldConfig 29 } 30 31 var _ = gc.Suite(&ManifoldSuite{}) 32 33 func (s *ManifoldSuite) SetUpTest(c *gc.C) { 34 s.IsolationSuite.SetUpTest(c) 35 36 s.config = singular.ManifoldConfig{ 37 Clock: testclock.NewClock(time.Now()), 38 APICallerName: "api-caller", 39 Duration: time.Minute, 40 NewFacade: func(base.APICaller, names.Tag, names.Tag) (singular.Facade, error) { 41 return nil, errors.NotImplementedf("NewFacade") 42 }, 43 NewWorker: func(config singular.FlagConfig) (worker.Worker, error) { 44 return nil, errors.NotImplementedf("NewWorker") 45 }, 46 } 47 } 48 49 func (s *ManifoldSuite) TestValidate(c *gc.C) { 50 c.Check(s.config.Validate(), jc.ErrorIsNil) 51 } 52 53 func (s *ManifoldSuite) TestValidateMissingClock(c *gc.C) { 54 s.config.Clock = nil 55 err := s.config.Validate() 56 c.Check(err, jc.Satisfies, errors.IsNotValid) 57 c.Check(err.Error(), gc.Equals, "nil Clock not valid") 58 } 59 60 func (s *ManifoldSuite) TestValidateMissingAPICallerName(c *gc.C) { 61 s.config.APICallerName = "" 62 err := s.config.Validate() 63 c.Check(err, jc.Satisfies, errors.IsNotValid) 64 c.Check(err.Error(), gc.Equals, "missing APICallerName not valid") 65 } 66 67 func (s *ManifoldSuite) TestValidateMissingNewFacade(c *gc.C) { 68 s.config.NewFacade = nil 69 err := s.config.Validate() 70 c.Check(err, jc.Satisfies, errors.IsNotValid) 71 c.Check(err.Error(), gc.Equals, "nil NewFacade not valid") 72 } 73 74 func (s *ManifoldSuite) TestValidateMissingNewWorker(c *gc.C) { 75 s.config.NewWorker = nil 76 err := s.config.Validate() 77 c.Check(err, jc.Satisfies, errors.IsNotValid) 78 c.Check(err.Error(), gc.Equals, "nil NewWorker not valid") 79 } 80 81 func (s *ManifoldSuite) TestInputs(c *gc.C) { 82 manifold := singular.Manifold(singular.ManifoldConfig{ 83 APICallerName: "kim", 84 }) 85 expectInputs := []string{"kim"} 86 c.Check(manifold.Inputs, jc.DeepEquals, expectInputs) 87 } 88 89 func (s *ManifoldSuite) TestOutputBadWorker(c *gc.C) { 90 manifold := singular.Manifold(singular.ManifoldConfig{}) 91 var out engine.Flag 92 err := manifold.Output(&fakeWorker{}, &out) 93 c.Check(err, gc.ErrorMatches, `expected in to implement Flag; got a .*`) 94 c.Check(out, gc.IsNil) 95 } 96 97 func (s *ManifoldSuite) TestOutputBadResult(c *gc.C) { 98 manifold := singular.Manifold(singular.ManifoldConfig{}) 99 fix := newFixture(c) 100 fix.Run(c, func(flag *singular.FlagWorker, _ *testclock.Clock, _ func()) { 101 var out interface{} 102 err := manifold.Output(flag, &out) 103 c.Check(err, gc.ErrorMatches, `expected out to be a \*Flag; got a .*`) 104 c.Check(out, gc.IsNil) 105 }) 106 } 107 108 func (s *ManifoldSuite) TestOutputSuccess(c *gc.C) { 109 manifold := singular.Manifold(singular.ManifoldConfig{}) 110 fix := newFixture(c) 111 fix.Run(c, func(flag *singular.FlagWorker, _ *testclock.Clock, _ func()) { 112 var out engine.Flag 113 err := manifold.Output(flag, &out) 114 c.Check(err, jc.ErrorIsNil) 115 c.Check(out, gc.Equals, flag) 116 }) 117 } 118 119 func (s *ManifoldSuite) TestStartMissingClock(c *gc.C) { 120 manifold := singular.Manifold(singular.ManifoldConfig{ 121 APICallerName: "api-caller", 122 }) 123 context := dt.StubContext(nil, map[string]interface{}{}) 124 125 worker, err := manifold.Start(context) 126 c.Check(errors.Cause(err), gc.ErrorMatches, `nil Clock not valid`) 127 c.Check(worker, gc.IsNil) 128 } 129 130 func (s *ManifoldSuite) TestStartMissingAPICaller(c *gc.C) { 131 manifold := singular.Manifold(s.config) 132 context := dt.StubContext(nil, map[string]interface{}{ 133 "api-caller": dependency.ErrMissing, 134 }) 135 136 worker, err := manifold.Start(context) 137 c.Check(errors.Cause(err), gc.Equals, dependency.ErrMissing) 138 c.Check(worker, gc.IsNil) 139 } 140 141 func (s *ManifoldSuite) TestStartNewFacadeError(c *gc.C) { 142 expectAPICaller := &fakeAPICaller{} 143 s.config.Claimant = names.NewMachineTag("123") 144 s.config.Entity = coretesting.ModelTag 145 s.config.NewFacade = func(apiCaller base.APICaller, claimant names.Tag, entity names.Tag) (singular.Facade, error) { 146 c.Check(apiCaller, gc.Equals, expectAPICaller) 147 c.Check(claimant.String(), gc.Equals, "machine-123") 148 c.Check(entity, gc.Equals, coretesting.ModelTag) 149 return nil, errors.New("grark plop") 150 } 151 manifold := singular.Manifold(s.config) 152 context := dt.StubContext(nil, map[string]interface{}{ 153 "api-caller": expectAPICaller, 154 }) 155 156 worker, err := manifold.Start(context) 157 c.Check(err, gc.ErrorMatches, "grark plop") 158 c.Check(worker, gc.IsNil) 159 } 160 161 func (s *ManifoldSuite) TestStartNewWorkerError(c *gc.C) { 162 expectFacade := &fakeFacade{} 163 s.config.NewFacade = func(base.APICaller, names.Tag, names.Tag) (singular.Facade, error) { 164 return expectFacade, nil 165 } 166 s.config.NewWorker = func(config singular.FlagConfig) (worker.Worker, error) { 167 c.Check(config.Facade, gc.Equals, expectFacade) 168 err := config.Validate() 169 c.Check(err, jc.ErrorIsNil) 170 return nil, errors.New("blomp tik") 171 } 172 manifold := singular.Manifold(s.config) 173 context := dt.StubContext(nil, map[string]interface{}{ 174 "api-caller": &fakeAPICaller{}, 175 }) 176 177 worker, err := manifold.Start(context) 178 c.Check(err, gc.ErrorMatches, "blomp tik") 179 c.Check(worker, gc.IsNil) 180 } 181 182 func (s *ManifoldSuite) TestStartSuccess(c *gc.C) { 183 var stub testing.Stub 184 expectWorker := newStubWorker(&stub) 185 s.config.NewFacade = func(base.APICaller, names.Tag, names.Tag) (singular.Facade, error) { 186 return &fakeFacade{}, nil 187 } 188 s.config.NewWorker = func(_ singular.FlagConfig) (worker.Worker, error) { 189 return expectWorker, nil 190 } 191 manifold := singular.Manifold(s.config) 192 context := dt.StubContext(nil, map[string]interface{}{ 193 "api-caller": &fakeAPICaller{}, 194 }) 195 196 worker, err := manifold.Start(context) 197 c.Check(err, jc.ErrorIsNil) 198 199 var out engine.Flag 200 err = manifold.Output(worker, &out) 201 c.Check(err, jc.ErrorIsNil) 202 c.Check(out.Check(), jc.IsTrue) 203 204 c.Check(worker.Wait(), jc.ErrorIsNil) 205 stub.CheckCallNames(c, "Check", "Wait") 206 } 207 208 func (s *ManifoldSuite) TestWorkerBouncesOnRefresh(c *gc.C) { 209 var stub testing.Stub 210 stub.SetErrors(singular.ErrRefresh) 211 errWorker := newStubWorker(&stub) 212 s.config.NewFacade = func(base.APICaller, names.Tag, names.Tag) (singular.Facade, error) { 213 return &fakeFacade{}, nil 214 } 215 s.config.NewWorker = func(_ singular.FlagConfig) (worker.Worker, error) { 216 return errWorker, nil 217 } 218 219 manifold := singular.Manifold(s.config) 220 context := dt.StubContext(nil, map[string]interface{}{ 221 "api-caller": &fakeAPICaller{}, 222 }) 223 224 worker, err := manifold.Start(context) 225 c.Check(err, jc.ErrorIsNil) 226 c.Check(worker.Wait(), gc.Equals, dependency.ErrBounce) 227 }