launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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 "launchpad.net/errgo/errors" 9 stdtesting "testing" 10 "time" 11 12 gc "launchpad.net/gocheck" 13 14 "launchpad.net/juju-core/state" 15 coretesting "launchpad.net/juju-core/testing" 16 jc "launchpad.net/juju-core/testing/checkers" 17 "launchpad.net/juju-core/testing/testbase" 18 ) 19 20 func TestPackage(t *stdtesting.T) { 21 coretesting.MgoTestPackage(t) 22 } 23 24 var _ = gc.Suite(&updaterSuite{}) 25 26 type updaterSuite struct { 27 testbase.LoggingSuite 28 } 29 30 func (*updaterSuite) TestStopsWatcher(c *gc.C) { 31 context := &testUpdaterContext{ 32 dyingc: make(chan struct{}), 33 } 34 expectErr := errors.New("some error") 35 watcher := &testMachinesWatcher{ 36 changes: make(chan []string), 37 err: expectErr, 38 } 39 done := make(chan error) 40 go func() { 41 done <- watchMachinesLoop(context, watcher) 42 }() 43 close(context.dyingc) 44 select { 45 case err := <-done: 46 c.Assert(err, gc.ErrorMatches, ".*"+expectErr.Error()) 47 case <-time.After(coretesting.LongWait): 48 c.Fatalf("timed out waiting for watchMachinesLoop to terminate") 49 } 50 c.Assert(watcher.stopped, jc.IsTrue) 51 } 52 53 func (*updaterSuite) TestWatchMachinesWaitsForMachinePollers(c *gc.C) { 54 // We can't see that the machine pollers are still alive directly, 55 // but we can make the machine's Refresh method block, 56 // and test that watchMachinesLoop only terminates 57 // when it unblocks. 58 waitRefresh := make(chan struct{}) 59 m := &testMachine{ 60 id: "99", 61 instanceId: "i1234", 62 life: state.Alive, 63 refresh: func() error { 64 // Signal that we're in Refresh. 65 waitRefresh <- struct{}{} 66 // Wait to be unblocked. 67 <-waitRefresh 68 return nil 69 }, 70 } 71 dyingc := make(chan struct{}) 72 context := &testUpdaterContext{ 73 dyingc: dyingc, 74 newMachineContextFunc: func() machineContext { 75 return &testMachineContext{ 76 getInstanceInfo: instanceInfoGetter(c, "i1234", testAddrs, "running", nil), 77 dyingc: dyingc, 78 } 79 }, 80 getMachineFunc: func(id string) (machine, error) { 81 c.Check(id, gc.Equals, m.id) 82 return m, nil 83 }, 84 } 85 watcher := &testMachinesWatcher{ 86 changes: make(chan []string), 87 } 88 done := make(chan error) 89 go func() { 90 done <- watchMachinesLoop(context, watcher) 91 }() 92 // Send two changes; the first one should start the machineLoop; 93 // the second should call Refresh. 94 watcher.changes <- []string{"99"} 95 watcher.changes <- []string{"99"} 96 // Wait for the machineLoop to call Refresh 97 select { 98 case <-waitRefresh: 99 c.Logf("poller called Refresh") 100 case <-time.After(coretesting.LongWait): 101 c.Fatalf("timed out waiting for machine to be refreshed") 102 } 103 close(context.dyingc) 104 // Wait a little while to be sure that watchMachinesLoop is 105 // actually waiting for its machine poller to finish. 106 select { 107 case err := <-done: 108 c.Fatalf("watchMachinesLoop terminated prematurely: %v", err) 109 case <-time.After(coretesting.ShortWait): 110 } 111 112 waitRefresh <- struct{}{} 113 select { 114 case err := <-done: 115 c.Assert(err, gc.IsNil) 116 case <-time.After(coretesting.LongWait): 117 c.Fatalf("timed out waiting for watchMachinesLoop to terminate") 118 } 119 c.Assert(watcher.stopped, jc.IsTrue) 120 } 121 122 type testUpdaterContext struct { 123 newMachineContextFunc func() machineContext 124 getMachineFunc func(id string) (machine, error) 125 dyingc chan struct{} 126 } 127 128 func (context *testUpdaterContext) newMachineContext() machineContext { 129 return context.newMachineContextFunc() 130 } 131 132 func (context *testUpdaterContext) getMachine(id string) (machine, error) { 133 return context.getMachineFunc(id) 134 } 135 136 func (context *testUpdaterContext) dying() <-chan struct{} { 137 return context.dyingc 138 } 139 140 type testMachinesWatcher struct { 141 stopped bool 142 changes chan []string 143 err error 144 } 145 146 func (w *testMachinesWatcher) Changes() <-chan []string { 147 return w.changes 148 } 149 150 func (w *testMachinesWatcher) Stop() error { 151 w.stopped = true 152 return w.err 153 } 154 155 func (w *testMachinesWatcher) Err() error { 156 return w.err 157 }