github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/modelcache/manifold_test.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package modelcache_test 5 6 import ( 7 "unsafe" 8 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 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 "gopkg.in/juju/worker.v1/dependency" 16 dt "gopkg.in/juju/worker.v1/dependency/testing" 17 18 "github.com/juju/juju/state" 19 "github.com/juju/juju/worker/modelcache" 20 workerstate "github.com/juju/juju/worker/state" 21 ) 22 23 type ManifoldSuite struct { 24 testing.IsolationSuite 25 config modelcache.ManifoldConfig 26 } 27 28 var _ = gc.Suite(&ManifoldSuite{}) 29 30 func (s *ManifoldSuite) SetUpTest(c *gc.C) { 31 s.IsolationSuite.SetUpTest(c) 32 s.config = modelcache.ManifoldConfig{ 33 StateName: "state", 34 Logger: loggo.GetLogger("test"), 35 PrometheusRegisterer: noopRegisterer{}, 36 NewWorker: func(modelcache.Config) (worker.Worker, error) { 37 return nil, errors.New("boom") 38 }, 39 } 40 } 41 42 func (s *ManifoldSuite) manifold() dependency.Manifold { 43 return modelcache.Manifold(s.config) 44 } 45 46 func (s *ManifoldSuite) TestInputs(c *gc.C) { 47 c.Check(s.manifold().Inputs, jc.DeepEquals, []string{"state"}) 48 } 49 50 func (s *ManifoldSuite) TestConfigValidation(c *gc.C) { 51 err := s.config.Validate() 52 c.Assert(err, jc.ErrorIsNil) 53 } 54 55 func (s *ManifoldSuite) TestConfigValidationMissingStateName(c *gc.C) { 56 s.config.StateName = "" 57 err := s.config.Validate() 58 c.Check(err, jc.Satisfies, errors.IsNotValid) 59 c.Check(err, gc.ErrorMatches, "empty StateName not valid") 60 } 61 62 func (s *ManifoldSuite) TestConfigValidationMissingPrometheusRegisterer(c *gc.C) { 63 s.config.PrometheusRegisterer = nil 64 err := s.config.Validate() 65 c.Check(err, jc.Satisfies, errors.IsNotValid) 66 c.Check(err, gc.ErrorMatches, "missing PrometheusRegisterer not valid") 67 } 68 69 func (s *ManifoldSuite) TestConfigValidationMissingLogger(c *gc.C) { 70 s.config.Logger = nil 71 err := s.config.Validate() 72 c.Check(err, jc.Satisfies, errors.IsNotValid) 73 c.Check(err, gc.ErrorMatches, "missing Logger not valid") 74 } 75 76 func (s *ManifoldSuite) TestConfigValidationMissingNewWorker(c *gc.C) { 77 s.config.NewWorker = nil 78 err := s.config.Validate() 79 c.Check(err, jc.Satisfies, errors.IsNotValid) 80 c.Check(err, gc.ErrorMatches, "missing NewWorker func not valid") 81 } 82 83 func (s *ManifoldSuite) TestManifoldCallsValidate(c *gc.C) { 84 context := dt.StubContext(nil, map[string]interface{}{}) 85 s.config.Logger = nil 86 worker, err := s.manifold().Start(context) 87 c.Check(worker, gc.IsNil) 88 c.Check(err, jc.Satisfies, errors.IsNotValid) 89 c.Check(err, gc.ErrorMatches, `missing Logger not valid`) 90 } 91 92 func (s *ManifoldSuite) TestAgentMissing(c *gc.C) { 93 context := dt.StubContext(nil, map[string]interface{}{ 94 "state": dependency.ErrMissing, 95 }) 96 97 worker, err := s.manifold().Start(context) 98 c.Check(worker, gc.IsNil) 99 c.Check(errors.Cause(err), gc.Equals, dependency.ErrMissing) 100 } 101 102 func (s *ManifoldSuite) TestNewWorkerArgs(c *gc.C) { 103 var config modelcache.Config 104 s.config.NewWorker = func(c modelcache.Config) (worker.Worker, error) { 105 config = c 106 return &fakeWorker{}, nil 107 } 108 109 tracker := &fakeStateTracker{} 110 context := dt.StubContext(nil, map[string]interface{}{ 111 "state": tracker, 112 }) 113 114 worker, err := s.manifold().Start(context) 115 c.Check(err, jc.ErrorIsNil) 116 c.Check(worker, gc.NotNil) 117 118 c.Check(config.Validate(), jc.ErrorIsNil) 119 c.Check(config.StatePool, gc.Equals, tracker.pool()) 120 c.Check(config.Logger, gc.Equals, s.config.Logger) 121 c.Check(config.PrometheusRegisterer, gc.Equals, s.config.PrometheusRegisterer) 122 123 c.Check(tracker.released, jc.IsFalse) 124 config.Cleanup() 125 c.Check(tracker.released, jc.IsTrue) 126 } 127 128 func (s *ManifoldSuite) TestNewWorkerErrorReleasesState(c *gc.C) { 129 tracker := &fakeStateTracker{} 130 context := dt.StubContext(nil, map[string]interface{}{ 131 "state": tracker, 132 }) 133 134 worker, err := s.manifold().Start(context) 135 c.Check(err, gc.ErrorMatches, "boom") 136 c.Check(worker, gc.IsNil) 137 c.Check(tracker.released, jc.IsTrue) 138 } 139 140 type fakeWorker struct { 141 worker.Worker 142 } 143 144 type fakeStateTracker struct { 145 workerstate.StateTracker 146 released bool 147 } 148 149 // Return an invalid but non-zero state pool pointer. 150 // Is only ever used for comparison. 151 func (f *fakeStateTracker) Use() (*state.StatePool, error) { 152 return f.pool(), nil 153 } 154 155 func (f *fakeStateTracker) pool() *state.StatePool { 156 return (*state.StatePool)(unsafe.Pointer(f)) 157 } 158 159 // Done tracks that the used pool is released. 160 func (f *fakeStateTracker) Done() error { 161 f.released = true 162 return nil 163 }