github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/instancepoller/updater_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // TODO(wallyworld) - move to instancepoller_test 5 package instancepoller 6 7 import ( 8 "time" 9 10 "github.com/juju/names" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/apiserver/params" 15 "github.com/juju/juju/status" 16 coretesting "github.com/juju/juju/testing" 17 "github.com/juju/juju/watcher" 18 ) 19 20 var _ = gc.Suite(&updaterSuite{}) 21 22 type updaterSuite struct { 23 coretesting.BaseSuite 24 } 25 26 func (*updaterSuite) TestWatchMachinesWaitsForMachinePollers(c *gc.C) { 27 // We can't see that the machine pollers are still alive directly, 28 // but we can make the machine's Refresh method block, 29 // and test that watchMachinesLoop only terminates 30 // when it unblocks. 31 waitRefresh := make(chan struct{}) 32 m := &testMachine{ 33 tag: names.NewMachineTag("99"), 34 instanceId: "i1234", 35 life: params.Alive, 36 refresh: func() error { 37 // Signal that we're in Refresh. 38 waitRefresh <- struct{}{} 39 // Wait to be unblocked. 40 <-waitRefresh 41 return nil 42 }, 43 } 44 dyingc := make(chan struct{}) 45 context := &testUpdaterContext{ 46 dyingc: dyingc, 47 newMachineContextFunc: func() machineContext { 48 return &testMachineContext{ 49 getInstanceInfo: instanceInfoGetter(c, "i1234", testAddrs, "running", nil), 50 dyingc: dyingc, 51 } 52 }, 53 getMachineFunc: func(tag names.MachineTag) (machine, error) { 54 c.Check(tag, jc.DeepEquals, m.tag) 55 return m, nil 56 }, 57 } 58 watcher := &testMachinesWatcher{ 59 changes: make(chan []string), 60 } 61 done := make(chan error) 62 go func() { 63 done <- watchMachinesLoop(context, watcher) 64 }() 65 // Send two changes; the first one should start the machineLoop; 66 // the second should call Refresh. 67 watcher.changes <- []string{"99"} 68 watcher.changes <- []string{"99"} 69 // Wait for the machineLoop to call Refresh 70 select { 71 case <-waitRefresh: 72 c.Logf("poller called Refresh") 73 case <-time.After(coretesting.LongWait): 74 c.Fatalf("timed out waiting for machine to be refreshed") 75 } 76 close(context.dyingc) 77 // Wait a little while to be sure that watchMachinesLoop is 78 // actually waiting for its machine poller to finish. 79 select { 80 case err := <-done: 81 c.Fatalf("watchMachinesLoop terminated prematurely: %v", err) 82 case <-time.After(coretesting.ShortWait): 83 } 84 85 waitRefresh <- struct{}{} 86 select { 87 case err := <-done: 88 c.Assert(err, jc.ErrorIsNil) 89 case <-time.After(coretesting.LongWait): 90 c.Fatalf("timed out waiting for watchMachinesLoop to terminate") 91 } 92 } 93 94 func (s *updaterSuite) TestManualMachinesIgnored(c *gc.C) { 95 waitStatus := make(chan struct{}) 96 s.PatchValue(&MachineStatus, func(m *testMachine) (params.StatusResult, error) { 97 // Signal that we're in Status. 98 waitStatus <- struct{}{} 99 return params.StatusResult{ 100 Status: status.StatusPending, 101 Info: "", 102 Data: map[string]interface{}{}, 103 Since: nil, 104 }, nil 105 }) 106 m := &testMachine{ 107 tag: names.NewMachineTag("99"), 108 instanceId: "manual:1234", 109 life: params.Alive, 110 } 111 dyingc := make(chan struct{}) 112 context := &testUpdaterContext{ 113 dyingc: dyingc, 114 newMachineContextFunc: func() machineContext { 115 return &testMachineContext{ 116 getInstanceInfo: instanceInfoGetter(c, "manual:1234", testAddrs, "running", nil), 117 dyingc: dyingc, 118 } 119 }, 120 getMachineFunc: func(tag names.MachineTag) (machine, error) { 121 c.Check(tag, jc.DeepEquals, m.tag) 122 return m, nil 123 }, 124 } 125 watcher := &testMachinesWatcher{ 126 changes: make(chan []string), 127 } 128 done := make(chan error) 129 go func() { 130 done <- watchMachinesLoop(context, watcher) 131 }() 132 // Send a change to start the machineLoop; 133 watcher.changes <- []string{"99"} 134 select { 135 case <-waitStatus: 136 c.Fatalf("poller called Status") 137 case <-time.After(coretesting.ShortWait): 138 c.Logf("status not called") 139 } 140 close(context.dyingc) 141 select { 142 case err := <-done: 143 c.Assert(err, jc.ErrorIsNil) 144 case <-time.After(coretesting.LongWait): 145 c.Fatalf("timed out waiting for watchMachinesLoop to terminate") 146 } 147 } 148 149 type testUpdaterContext struct { 150 updaterContext 151 newMachineContextFunc func() machineContext 152 getMachineFunc func(tag names.MachineTag) (machine, error) 153 dyingc chan struct{} 154 } 155 156 func (context *testUpdaterContext) newMachineContext() machineContext { 157 return context.newMachineContextFunc() 158 } 159 160 func (context *testUpdaterContext) getMachine(tag names.MachineTag) (machine, error) { 161 return context.getMachineFunc(tag) 162 } 163 164 func (context *testUpdaterContext) dying() <-chan struct{} { 165 return context.dyingc 166 } 167 168 func (context *testUpdaterContext) errDying() error { 169 return nil 170 } 171 172 type testMachinesWatcher struct { 173 watcher.StringsWatcher 174 changes chan []string 175 err error 176 } 177 178 func (w *testMachinesWatcher) Changes() watcher.StringsChannel { 179 return w.changes 180 } 181 182 func (w *testMachinesWatcher) Wait() error { 183 return w.err 184 }