github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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  	"time"
     9  
    10  	"github.com/juju/names"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/status"
    16  	coretesting "github.com/juju/juju/testing"
    17  	"github.com/juju/juju/watcher"
    18  )
    19  
    20  var _ = gc.Suite(&updaterSuite{})
    21  
    22  type updaterSuite struct {
    23  	coretesting.BaseSuite
    24  }
    25  
    26  func (*updaterSuite) TestWatchMachinesWaitsForMachinePollers(c *gc.C) {
    27  	// We can't see that the machine pollers are still alive directly,
    28  	// but we can make the machine's Refresh method block,
    29  	// and test that watchMachinesLoop only terminates
    30  	// when it unblocks.
    31  	waitRefresh := make(chan struct{})
    32  	m := &testMachine{
    33  		tag:        names.NewMachineTag("99"),
    34  		instanceId: "i1234",
    35  		life:       params.Alive,
    36  		refresh: func() error {
    37  			// Signal that we're in Refresh.
    38  			waitRefresh <- struct{}{}
    39  			// Wait to be unblocked.
    40  			<-waitRefresh
    41  			return nil
    42  		},
    43  	}
    44  	dyingc := make(chan struct{})
    45  	context := &testUpdaterContext{
    46  		dyingc: dyingc,
    47  		newMachineContextFunc: func() machineContext {
    48  			return &testMachineContext{
    49  				getInstanceInfo: instanceInfoGetter(c, "i1234", testAddrs, "running", nil),
    50  				dyingc:          dyingc,
    51  			}
    52  		},
    53  		getMachineFunc: func(tag names.MachineTag) (machine, error) {
    54  			c.Check(tag, jc.DeepEquals, m.tag)
    55  			return m, nil
    56  		},
    57  	}
    58  	watcher := &testMachinesWatcher{
    59  		changes: make(chan []string),
    60  	}
    61  	done := make(chan error)
    62  	go func() {
    63  		done <- watchMachinesLoop(context, watcher)
    64  	}()
    65  	// Send two changes; the first one should start the machineLoop;
    66  	// the second should call Refresh.
    67  	watcher.changes <- []string{"99"}
    68  	watcher.changes <- []string{"99"}
    69  	// Wait for the machineLoop to call Refresh
    70  	select {
    71  	case <-waitRefresh:
    72  		c.Logf("poller called Refresh")
    73  	case <-time.After(coretesting.LongWait):
    74  		c.Fatalf("timed out waiting for machine to be refreshed")
    75  	}
    76  	close(context.dyingc)
    77  	// Wait a little while to be sure that watchMachinesLoop is
    78  	// actually waiting for its machine poller to finish.
    79  	select {
    80  	case err := <-done:
    81  		c.Fatalf("watchMachinesLoop terminated prematurely: %v", err)
    82  	case <-time.After(coretesting.ShortWait):
    83  	}
    84  
    85  	waitRefresh <- struct{}{}
    86  	select {
    87  	case err := <-done:
    88  		c.Assert(err, jc.ErrorIsNil)
    89  	case <-time.After(coretesting.LongWait):
    90  		c.Fatalf("timed out waiting for watchMachinesLoop to terminate")
    91  	}
    92  }
    93  
    94  func (s *updaterSuite) TestManualMachinesIgnored(c *gc.C) {
    95  	waitStatus := make(chan struct{})
    96  	s.PatchValue(&MachineStatus, func(m *testMachine) (params.StatusResult, error) {
    97  		// Signal that we're in Status.
    98  		waitStatus <- struct{}{}
    99  		return params.StatusResult{
   100  			Status: status.StatusPending,
   101  			Info:   "",
   102  			Data:   map[string]interface{}{},
   103  			Since:  nil,
   104  		}, nil
   105  	})
   106  	m := &testMachine{
   107  		tag:        names.NewMachineTag("99"),
   108  		instanceId: "manual:1234",
   109  		life:       params.Alive,
   110  	}
   111  	dyingc := make(chan struct{})
   112  	context := &testUpdaterContext{
   113  		dyingc: dyingc,
   114  		newMachineContextFunc: func() machineContext {
   115  			return &testMachineContext{
   116  				getInstanceInfo: instanceInfoGetter(c, "manual:1234", testAddrs, "running", nil),
   117  				dyingc:          dyingc,
   118  			}
   119  		},
   120  		getMachineFunc: func(tag names.MachineTag) (machine, error) {
   121  			c.Check(tag, jc.DeepEquals, m.tag)
   122  			return m, nil
   123  		},
   124  	}
   125  	watcher := &testMachinesWatcher{
   126  		changes: make(chan []string),
   127  	}
   128  	done := make(chan error)
   129  	go func() {
   130  		done <- watchMachinesLoop(context, watcher)
   131  	}()
   132  	// Send a change to start the machineLoop;
   133  	watcher.changes <- []string{"99"}
   134  	select {
   135  	case <-waitStatus:
   136  		c.Fatalf("poller called Status")
   137  	case <-time.After(coretesting.ShortWait):
   138  		c.Logf("status not called")
   139  	}
   140  	close(context.dyingc)
   141  	select {
   142  	case err := <-done:
   143  		c.Assert(err, jc.ErrorIsNil)
   144  	case <-time.After(coretesting.LongWait):
   145  		c.Fatalf("timed out waiting for watchMachinesLoop to terminate")
   146  	}
   147  }
   148  
   149  type testUpdaterContext struct {
   150  	updaterContext
   151  	newMachineContextFunc func() machineContext
   152  	getMachineFunc        func(tag names.MachineTag) (machine, error)
   153  	dyingc                chan struct{}
   154  }
   155  
   156  func (context *testUpdaterContext) newMachineContext() machineContext {
   157  	return context.newMachineContextFunc()
   158  }
   159  
   160  func (context *testUpdaterContext) getMachine(tag names.MachineTag) (machine, error) {
   161  	return context.getMachineFunc(tag)
   162  }
   163  
   164  func (context *testUpdaterContext) dying() <-chan struct{} {
   165  	return context.dyingc
   166  }
   167  
   168  func (context *testUpdaterContext) errDying() error {
   169  	return nil
   170  }
   171  
   172  type testMachinesWatcher struct {
   173  	watcher.StringsWatcher
   174  	changes chan []string
   175  	err     error
   176  }
   177  
   178  func (w *testMachinesWatcher) Changes() watcher.StringsChannel {
   179  	return w.changes
   180  }
   181  
   182  func (w *testMachinesWatcher) Wait() error {
   183  	return w.err
   184  }