github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/peergrouper/manifold_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package peergrouper_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/clock/testclock"
    10  	"github.com/juju/errors"
    11  	"github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  	"gopkg.in/juju/worker.v1"
    15  	"gopkg.in/juju/worker.v1/dependency"
    16  	dt "gopkg.in/juju/worker.v1/dependency/testing"
    17  	"gopkg.in/juju/worker.v1/workertest"
    18  
    19  	"github.com/juju/juju/agent"
    20  	"github.com/juju/juju/apiserver/params"
    21  	"github.com/juju/juju/state"
    22  	statetesting "github.com/juju/juju/state/testing"
    23  	"github.com/juju/juju/worker/peergrouper"
    24  )
    25  
    26  type ManifoldSuite struct {
    27  	statetesting.StateSuite
    28  
    29  	manifold     dependency.Manifold
    30  	context      dependency.Context
    31  	clock        *testclock.Clock
    32  	agent        *mockAgent
    33  	hub          *mockHub
    34  	stateTracker stubStateTracker
    35  
    36  	stub testing.Stub
    37  }
    38  
    39  var _ = gc.Suite(&ManifoldSuite{})
    40  
    41  func (s *ManifoldSuite) SetUpTest(c *gc.C) {
    42  	s.StateSuite.SetUpTest(c)
    43  
    44  	s.clock = testclock.NewClock(time.Time{})
    45  	s.agent = &mockAgent{conf: mockAgentConfig{
    46  		info: &params.StateServingInfo{
    47  			StatePort: 1234,
    48  			APIPort:   5678,
    49  		},
    50  	}}
    51  	s.hub = &mockHub{}
    52  	s.stateTracker = stubStateTracker{pool: s.StatePool}
    53  	s.stub.ResetCalls()
    54  
    55  	s.context = s.newContext(nil)
    56  	s.manifold = peergrouper.Manifold(peergrouper.ManifoldConfig{
    57  		AgentName:          "agent",
    58  		ClockName:          "clock",
    59  		ControllerPortName: "controller-port",
    60  		StateName:          "state",
    61  		Hub:                s.hub,
    62  		NewWorker:          s.newWorker,
    63  		ControllerSupportsSpaces: func(st *state.State) (bool, error) {
    64  			if st != s.State {
    65  				return false, errors.New("invalid state")
    66  			}
    67  			return true, nil
    68  		},
    69  	})
    70  }
    71  
    72  func (s *ManifoldSuite) newContext(overlay map[string]interface{}) dependency.Context {
    73  	resources := map[string]interface{}{
    74  		"agent":           s.agent,
    75  		"clock":           s.clock,
    76  		"controller-port": nil,
    77  		"state":           &s.stateTracker,
    78  	}
    79  	for k, v := range overlay {
    80  		resources[k] = v
    81  	}
    82  	return dt.StubContext(nil, resources)
    83  }
    84  
    85  func (s *ManifoldSuite) newWorker(config peergrouper.Config) (worker.Worker, error) {
    86  	s.stub.MethodCall(s, "NewWorker", config)
    87  	if err := s.stub.NextErr(); err != nil {
    88  		return nil, err
    89  	}
    90  	w := worker.NewRunner(worker.RunnerParams{})
    91  	s.AddCleanup(func(c *gc.C) { workertest.CleanKill(c, w) })
    92  	return w, nil
    93  }
    94  
    95  var expectedInputs = []string{"agent", "clock", "controller-port", "state"}
    96  
    97  func (s *ManifoldSuite) TestInputs(c *gc.C) {
    98  	c.Assert(s.manifold.Inputs, jc.SameContents, expectedInputs)
    99  }
   100  
   101  func (s *ManifoldSuite) TestMissingInputs(c *gc.C) {
   102  	for _, input := range expectedInputs {
   103  		context := s.newContext(map[string]interface{}{
   104  			input: dependency.ErrMissing,
   105  		})
   106  		_, err := s.manifold.Start(context)
   107  		c.Assert(errors.Cause(err), gc.Equals, dependency.ErrMissing)
   108  	}
   109  }
   110  
   111  func (s *ManifoldSuite) TestStart(c *gc.C) {
   112  	w := s.startWorkerClean(c)
   113  	workertest.CleanKill(c, w)
   114  
   115  	s.stub.CheckCallNames(c, "NewWorker")
   116  	args := s.stub.Calls()[0].Args
   117  	c.Assert(args, gc.HasLen, 1)
   118  	c.Assert(args[0], gc.FitsTypeOf, peergrouper.Config{})
   119  	config := args[0].(peergrouper.Config)
   120  
   121  	c.Assert(config, jc.DeepEquals, peergrouper.Config{
   122  		State:        peergrouper.StateShim{s.State},
   123  		MongoSession: peergrouper.MongoSessionShim{s.State.MongoSession()},
   124  		APIHostPortsSetter: &peergrouper.CachingAPIHostPortsSetter{
   125  			APIHostPortsSetter: s.State,
   126  		},
   127  		Clock:          s.clock,
   128  		Hub:            s.hub,
   129  		SupportsSpaces: true,
   130  		MongoPort:      1234,
   131  		APIPort:        5678,
   132  	})
   133  }
   134  
   135  func (s *ManifoldSuite) TestStopWorkerClosesState(c *gc.C) {
   136  	w := s.startWorkerClean(c)
   137  	defer workertest.CleanKill(c, w)
   138  
   139  	s.stateTracker.CheckCallNames(c, "Use")
   140  
   141  	workertest.CleanKill(c, w)
   142  	s.stateTracker.CheckCallNames(c, "Use", "Done")
   143  }
   144  
   145  func (s *ManifoldSuite) startWorkerClean(c *gc.C) worker.Worker {
   146  	w, err := s.manifold.Start(s.context)
   147  	c.Assert(err, jc.ErrorIsNil)
   148  	workertest.CheckAlive(c, w)
   149  	return w
   150  }
   151  
   152  type stubStateTracker struct {
   153  	testing.Stub
   154  	pool *state.StatePool
   155  }
   156  
   157  func (s *stubStateTracker) Use() (*state.StatePool, error) {
   158  	s.MethodCall(s, "Use")
   159  	return s.pool, s.NextErr()
   160  }
   161  
   162  func (s *stubStateTracker) Done() error {
   163  	s.MethodCall(s, "Done")
   164  	return s.NextErr()
   165  }
   166  
   167  func (s *stubStateTracker) Report() map[string]interface{} {
   168  	s.MethodCall(s, "Report")
   169  	return nil
   170  }
   171  
   172  type mockAgent struct {
   173  	agent.Agent
   174  	conf mockAgentConfig
   175  }
   176  
   177  func (ma *mockAgent) CurrentConfig() agent.Config {
   178  	return &ma.conf
   179  }
   180  
   181  type mockAgentConfig struct {
   182  	agent.Config
   183  	info *params.StateServingInfo
   184  }
   185  
   186  func (c *mockAgentConfig) StateServingInfo() (params.StateServingInfo, bool) {
   187  	if c.info != nil {
   188  		return *c.info, true
   189  	}
   190  	return params.StateServingInfo{}, false
   191  }
   192  
   193  type mockHub struct {
   194  	peergrouper.Hub
   195  }