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