github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/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  	jc "github.com/juju/testing/checkers"
    13  	gc "launchpad.net/gocheck"
    14  
    15  	"github.com/juju/juju/instance"
    16  	"github.com/juju/juju/juju/testing"
    17  	"github.com/juju/juju/provider/dummy"
    18  	"github.com/juju/juju/state"
    19  	coretesting "github.com/juju/juju/testing"
    20  	"github.com/juju/juju/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.NewAddresses(fmt.Sprintf("127.0.0.%d", i))
    35  }
    36  
    37  func (s *workerSuite) TestWorker(c *gc.C) {
    38  	// Most functionality is already tested in detail - we
    39  	// just need to test that things are wired together
    40  	// correctly.
    41  	s.PatchValue(&ShortPoll, 10*time.Millisecond)
    42  	s.PatchValue(&LongPoll, 10*time.Millisecond)
    43  	s.PatchValue(&gatherTime, 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  	// Make sure the second half of the instances have no addresses.
   176  	for i := len(machines) / 2; i < len(machines); i++ {
   177  		dummy.SetInstanceAddresses(insts[i], nil)
   178  	}
   179  	return machines, insts
   180  }