github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/jujud/agent/machine/stateworkers_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package machine_test 5 6 import ( 7 "errors" 8 "sync" 9 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 13 "github.com/juju/juju/cmd/jujud/agent/machine" 14 "github.com/juju/juju/state" 15 coretesting "github.com/juju/juju/testing" 16 "github.com/juju/juju/worker" 17 "github.com/juju/juju/worker/dependency" 18 dt "github.com/juju/juju/worker/dependency/testing" 19 ) 20 21 type StateWorkersSuite struct { 22 coretesting.BaseSuite 23 manifold dependency.Manifold 24 startError error 25 startCalled bool 26 } 27 28 var _ = gc.Suite(&StateWorkersSuite{}) 29 30 func (s *StateWorkersSuite) SetUpTest(c *gc.C) { 31 s.startError = nil 32 s.startCalled = false 33 s.manifold = machine.StateWorkersManifold(machine.StateWorkersConfig{ 34 StateName: "state", 35 StartStateWorkers: s.startStateWorkers, 36 }) 37 } 38 39 func (s *StateWorkersSuite) startStateWorkers(st *state.State) (worker.Worker, error) { 40 s.startCalled = true 41 if s.startError != nil { 42 return nil, s.startError 43 } 44 return new(mockWorker), nil 45 } 46 47 func (s *StateWorkersSuite) TestInputs(c *gc.C) { 48 c.Assert(s.manifold.Inputs, jc.SameContents, []string{ 49 "state", 50 }) 51 } 52 53 func (s *StateWorkersSuite) TestNoStartStateWorkers(c *gc.C) { 54 manifold := machine.StateWorkersManifold(machine.StateWorkersConfig{}) 55 worker, err := manifold.Start(dt.StubContext(nil, nil)) 56 c.Check(worker, gc.IsNil) 57 c.Check(err, gc.ErrorMatches, "StartStateWorkers not specified") 58 c.Check(s.startCalled, jc.IsFalse) 59 } 60 61 func (s *StateWorkersSuite) TestStateMissing(c *gc.C) { 62 context := dt.StubContext(nil, map[string]interface{}{ 63 "state": dependency.ErrMissing, 64 }) 65 worker, err := s.manifold.Start(context) 66 c.Check(worker, gc.IsNil) 67 c.Check(err, gc.Equals, dependency.ErrMissing) 68 c.Check(s.startCalled, jc.IsFalse) 69 } 70 71 func (s *StateWorkersSuite) TestStartError(c *gc.C) { 72 tracker := new(mockStateTracker) 73 context := dt.StubContext(nil, map[string]interface{}{ 74 "state": tracker, 75 }) 76 s.startError = errors.New("boom") 77 78 worker, err := s.manifold.Start(context) 79 c.Check(worker, gc.IsNil) 80 c.Check(err, gc.ErrorMatches, "worker startup: boom") 81 c.Check(s.startCalled, jc.IsTrue) 82 tracker.assertDoneCalled(c) 83 } 84 85 func (s *StateWorkersSuite) TestStartSuccess(c *gc.C) { 86 tracker := new(mockStateTracker) 87 context := dt.StubContext(nil, map[string]interface{}{ 88 "state": tracker, 89 }) 90 w, err := s.manifold.Start(context) 91 c.Check(w, gc.Not(gc.IsNil)) 92 c.Check(err, jc.ErrorIsNil) 93 c.Check(s.startCalled, jc.IsTrue) 94 c.Check(tracker.isDoneCalled(), jc.IsFalse) 95 96 // Ensure Done is called on tracker when worker exits. 97 worker.Stop(w) 98 tracker.assertDoneCalled(c) 99 } 100 101 // Implements StateTracker. 102 type mockStateTracker struct { 103 mu sync.Mutex 104 doneCalled bool 105 } 106 107 func (t *mockStateTracker) Use() (*state.State, error) { 108 t.mu.Lock() 109 defer t.mu.Unlock() 110 return new(state.State), nil 111 } 112 113 func (t *mockStateTracker) Done() error { 114 t.mu.Lock() 115 defer t.mu.Unlock() 116 t.doneCalled = true 117 return nil 118 } 119 120 func (t *mockStateTracker) isDoneCalled() bool { 121 t.mu.Lock() 122 defer t.mu.Unlock() 123 return t.doneCalled 124 } 125 126 func (t *mockStateTracker) assertDoneCalled(c *gc.C) { 127 for a := coretesting.LongAttempt.Start(); a.Next(); { 128 if t.isDoneCalled() { 129 return 130 } 131 } 132 c.Fatal("Done() not called on tracker") 133 }