github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/instancepoller/worker_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 "fmt" 9 "reflect" 10 "time" 11 12 "github.com/juju/errors" 13 jc "github.com/juju/testing/checkers" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/instance" 17 "github.com/juju/juju/juju/testing" 18 "github.com/juju/juju/network" 19 "github.com/juju/juju/provider/dummy" 20 "github.com/juju/juju/state" 21 coretesting "github.com/juju/juju/testing" 22 "github.com/juju/juju/worker" 23 ) 24 25 var _ = gc.Suite(&workerSuite{}) 26 27 type workerSuite struct { 28 testing.JujuConnSuite 29 } 30 31 func (*workerSuite) instId(i int) instance.Id { 32 return instance.Id(fmt.Sprint(i)) 33 } 34 35 func (*workerSuite) addressesForIndex(i int) []network.Address { 36 return network.NewAddresses(fmt.Sprintf("127.0.0.%d", i)) 37 } 38 39 func (s *workerSuite) TestWorker(c *gc.C) { 40 // Most functionality is already tested in detail - we 41 // just need to test that things are wired together 42 // correctly. 43 s.PatchValue(&ShortPoll, 10*time.Millisecond) 44 s.PatchValue(&LongPoll, 10*time.Millisecond) 45 s.PatchValue(&gatherTime, 10*time.Millisecond) 46 machines, insts := s.setupScenario(c) 47 s.State.StartSync() 48 w := NewWorker(s.State) 49 defer func() { 50 c.Assert(worker.Stop(w), gc.IsNil) 51 }() 52 53 checkInstanceInfo := func(index int, m machine, expectedStatus string) bool { 54 isProvisioned := true 55 status, err := m.InstanceStatus() 56 if errors.IsNotProvisioned(err) { 57 isProvisioned = false 58 } else { 59 c.Assert(err, jc.ErrorIsNil) 60 } 61 return reflect.DeepEqual(m.Addresses(), s.addressesForIndex(index)) && (!isProvisioned || status == expectedStatus) 62 } 63 64 // Wait for the odd numbered machines in the 65 // first half of the machine slice to be given their 66 // addresses and status. 67 for a := coretesting.LongAttempt.Start(); a.Next(); { 68 if !a.HasNext() { 69 c.Fatalf("timed out waiting for instance info") 70 } 71 72 if machinesSatisfy(c, machines, func(i int, m *state.Machine) bool { 73 if i < len(machines)/2 && i%2 == 1 { 74 return checkInstanceInfo(i, m, "running") 75 } 76 status, err := m.InstanceStatus() 77 if i%2 == 0 { 78 // Even machines not provisioned yet. 79 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 80 } else { 81 c.Assert(status, gc.Equals, "") 82 } 83 return len(m.Addresses()) == 0 84 }) { 85 break 86 } 87 } 88 // Now provision the even machines in the first half and watch them get addresses. 89 for i := 0; i < len(insts)/2; i += 2 { 90 m := machines[i] 91 err := m.SetProvisioned(insts[i].Id(), "nonce", nil) 92 c.Assert(err, jc.ErrorIsNil) 93 dummy.SetInstanceAddresses(insts[i], s.addressesForIndex(i)) 94 dummy.SetInstanceStatus(insts[i], "running") 95 } 96 for a := coretesting.LongAttempt.Start(); a.Next(); { 97 if !a.HasNext() { 98 c.Fatalf("timed out waiting for machine instance info") 99 } 100 if machinesSatisfy(c, machines, func(i int, m *state.Machine) bool { 101 if i < len(machines)/2 { 102 return checkInstanceInfo(i, m, "running") 103 } 104 // Machines in second half still have no addresses, nor status. 105 status, err := m.InstanceStatus() 106 if i%2 == 0 { 107 // Even machines not provisioned yet. 108 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 109 } else { 110 c.Assert(status, gc.Equals, "") 111 } 112 return len(m.Addresses()) == 0 113 }) { 114 break 115 } 116 } 117 118 // Provision the remaining machines and check the address and status. 119 for i := len(insts) / 2; i < len(insts); i++ { 120 if i%2 == 0 { 121 m := machines[i] 122 err := m.SetProvisioned(insts[i].Id(), "nonce", nil) 123 c.Assert(err, jc.ErrorIsNil) 124 } 125 dummy.SetInstanceAddresses(insts[i], s.addressesForIndex(i)) 126 dummy.SetInstanceStatus(insts[i], "running") 127 } 128 for a := coretesting.LongAttempt.Start(); a.Next(); { 129 if !a.HasNext() { 130 c.Fatalf("timed out waiting for machine instance info") 131 } 132 if machinesSatisfy(c, machines, func(i int, m *state.Machine) bool { 133 return checkInstanceInfo(i, m, "running") 134 }) { 135 break 136 } 137 } 138 } 139 140 // TODO(rog) 141 // - check that the environment observer is actually hooked up. 142 // - check that the environment observer is stopped. 143 // - check that the errors propagate correctly. 144 145 func machinesSatisfy(c *gc.C, machines []*state.Machine, f func(i int, m *state.Machine) bool) bool { 146 for i, m := range machines { 147 err := m.Refresh() 148 c.Assert(err, jc.ErrorIsNil) 149 if !f(i, m) { 150 return false 151 } 152 } 153 return true 154 } 155 156 func (s *workerSuite) setupScenario(c *gc.C) ([]*state.Machine, []instance.Instance) { 157 var machines []*state.Machine 158 var insts []instance.Instance 159 for i := 0; i < 10; i++ { 160 m, err := s.State.AddMachine("series", state.JobHostUnits) 161 c.Assert(err, jc.ErrorIsNil) 162 machines = append(machines, m) 163 inst, _ := testing.AssertStartInstance(c, s.Environ, m.Id()) 164 insts = append(insts, inst) 165 } 166 // Associate the odd-numbered machines with an instance. 167 for i := 1; i < len(machines); i += 2 { 168 m := machines[i] 169 err := m.SetProvisioned(insts[i].Id(), "nonce", nil) 170 c.Assert(err, jc.ErrorIsNil) 171 } 172 // Associate the first half of the instances with an address and status. 173 for i := 0; i < len(machines)/2; i++ { 174 dummy.SetInstanceAddresses(insts[i], s.addressesForIndex(i)) 175 dummy.SetInstanceStatus(insts[i], "running") 176 } 177 // Make sure the second half of the instances have no addresses. 178 for i := len(machines) / 2; i < len(machines); i++ { 179 dummy.SetInstanceAddresses(insts[i], nil) 180 } 181 return machines, insts 182 }