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