launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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  	"launchpad.net/errgo/errors"
     9  	stdtesting "testing"
    10  	"time"
    11  
    12  	gc "launchpad.net/gocheck"
    13  
    14  	"launchpad.net/juju-core/state"
    15  	coretesting "launchpad.net/juju-core/testing"
    16  	jc "launchpad.net/juju-core/testing/checkers"
    17  	"launchpad.net/juju-core/testing/testbase"
    18  )
    19  
    20  func TestPackage(t *stdtesting.T) {
    21  	coretesting.MgoTestPackage(t)
    22  }
    23  
    24  var _ = gc.Suite(&updaterSuite{})
    25  
    26  type updaterSuite struct {
    27  	testbase.LoggingSuite
    28  }
    29  
    30  func (*updaterSuite) TestStopsWatcher(c *gc.C) {
    31  	context := &testUpdaterContext{
    32  		dyingc: make(chan struct{}),
    33  	}
    34  	expectErr := errors.New("some error")
    35  	watcher := &testMachinesWatcher{
    36  		changes: make(chan []string),
    37  		err:     expectErr,
    38  	}
    39  	done := make(chan error)
    40  	go func() {
    41  		done <- watchMachinesLoop(context, watcher)
    42  	}()
    43  	close(context.dyingc)
    44  	select {
    45  	case err := <-done:
    46  		c.Assert(err, gc.ErrorMatches, ".*"+expectErr.Error())
    47  	case <-time.After(coretesting.LongWait):
    48  		c.Fatalf("timed out waiting for watchMachinesLoop to terminate")
    49  	}
    50  	c.Assert(watcher.stopped, jc.IsTrue)
    51  }
    52  
    53  func (*updaterSuite) TestWatchMachinesWaitsForMachinePollers(c *gc.C) {
    54  	// We can't see that the machine pollers are still alive directly,
    55  	// but we can make the machine's Refresh method block,
    56  	// and test that watchMachinesLoop only terminates
    57  	// when it unblocks.
    58  	waitRefresh := make(chan struct{})
    59  	m := &testMachine{
    60  		id:         "99",
    61  		instanceId: "i1234",
    62  		life:       state.Alive,
    63  		refresh: func() error {
    64  			// Signal that we're in Refresh.
    65  			waitRefresh <- struct{}{}
    66  			// Wait to be unblocked.
    67  			<-waitRefresh
    68  			return nil
    69  		},
    70  	}
    71  	dyingc := make(chan struct{})
    72  	context := &testUpdaterContext{
    73  		dyingc: dyingc,
    74  		newMachineContextFunc: func() machineContext {
    75  			return &testMachineContext{
    76  				getInstanceInfo: instanceInfoGetter(c, "i1234", testAddrs, "running", nil),
    77  				dyingc:          dyingc,
    78  			}
    79  		},
    80  		getMachineFunc: func(id string) (machine, error) {
    81  			c.Check(id, gc.Equals, m.id)
    82  			return m, nil
    83  		},
    84  	}
    85  	watcher := &testMachinesWatcher{
    86  		changes: make(chan []string),
    87  	}
    88  	done := make(chan error)
    89  	go func() {
    90  		done <- watchMachinesLoop(context, watcher)
    91  	}()
    92  	// Send two changes; the first one should start the machineLoop;
    93  	// the second should call Refresh.
    94  	watcher.changes <- []string{"99"}
    95  	watcher.changes <- []string{"99"}
    96  	// Wait for the machineLoop to call Refresh
    97  	select {
    98  	case <-waitRefresh:
    99  		c.Logf("poller called Refresh")
   100  	case <-time.After(coretesting.LongWait):
   101  		c.Fatalf("timed out waiting for machine to be refreshed")
   102  	}
   103  	close(context.dyingc)
   104  	// Wait a little while to be sure that watchMachinesLoop is
   105  	// actually waiting for its machine poller to finish.
   106  	select {
   107  	case err := <-done:
   108  		c.Fatalf("watchMachinesLoop terminated prematurely: %v", err)
   109  	case <-time.After(coretesting.ShortWait):
   110  	}
   111  
   112  	waitRefresh <- struct{}{}
   113  	select {
   114  	case err := <-done:
   115  		c.Assert(err, gc.IsNil)
   116  	case <-time.After(coretesting.LongWait):
   117  		c.Fatalf("timed out waiting for watchMachinesLoop to terminate")
   118  	}
   119  	c.Assert(watcher.stopped, jc.IsTrue)
   120  }
   121  
   122  type testUpdaterContext struct {
   123  	newMachineContextFunc func() machineContext
   124  	getMachineFunc        func(id string) (machine, error)
   125  	dyingc                chan struct{}
   126  }
   127  
   128  func (context *testUpdaterContext) newMachineContext() machineContext {
   129  	return context.newMachineContextFunc()
   130  }
   131  
   132  func (context *testUpdaterContext) getMachine(id string) (machine, error) {
   133  	return context.getMachineFunc(id)
   134  }
   135  
   136  func (context *testUpdaterContext) dying() <-chan struct{} {
   137  	return context.dyingc
   138  }
   139  
   140  type testMachinesWatcher struct {
   141  	stopped bool
   142  	changes chan []string
   143  	err     error
   144  }
   145  
   146  func (w *testMachinesWatcher) Changes() <-chan []string {
   147  	return w.changes
   148  }
   149  
   150  func (w *testMachinesWatcher) Stop() error {
   151  	w.stopped = true
   152  	return w.err
   153  }
   154  
   155  func (w *testMachinesWatcher) Err() error {
   156  	return w.err
   157  }