github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/worker/apicaller/manifold_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package apicaller_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names"
     9  	"github.com/juju/testing"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	coreagent "github.com/juju/juju/agent"
    14  	"github.com/juju/juju/api/base"
    15  	coretesting "github.com/juju/juju/testing"
    16  	"github.com/juju/juju/worker"
    17  	"github.com/juju/juju/worker/agent"
    18  	"github.com/juju/juju/worker/apicaller"
    19  	"github.com/juju/juju/worker/dependency"
    20  	dt "github.com/juju/juju/worker/dependency/testing"
    21  )
    22  
    23  type ManifoldSuite struct {
    24  	testing.IsolationSuite
    25  	testing.Stub
    26  	manifold    dependency.Manifold
    27  	agent       *mockAgent
    28  	conn        *mockConn
    29  	getResource dependency.GetResourceFunc
    30  }
    31  
    32  var _ = gc.Suite(&ManifoldSuite{})
    33  
    34  func (s *ManifoldSuite) SetUpTest(c *gc.C) {
    35  	s.IsolationSuite.SetUpTest(c)
    36  	s.Stub = testing.Stub{}
    37  	s.manifold = apicaller.Manifold(apicaller.ManifoldConfig{
    38  		AgentName: "agent-name",
    39  	})
    40  
    41  	s.agent = &mockAgent{
    42  		stub: &s.Stub,
    43  		env:  coretesting.EnvironmentTag,
    44  	}
    45  	s.getResource = dt.StubGetResource(dt.StubResources{
    46  		"agent-name": dt.StubResource{Output: s.agent},
    47  	})
    48  
    49  	// Watch out for this: it uses its own Stub because Close calls are made from
    50  	// the worker's loop goroutine. You should make sure to stop the worker before
    51  	// checking the mock conn's calls (unless you know the connection will outlive
    52  	// the test -- see setupMutatorTest).
    53  	s.conn = &mockConn{
    54  		stub:   &testing.Stub{},
    55  		broken: make(chan struct{}),
    56  	}
    57  	s.PatchValue(apicaller.OpenConnection, func(agent agent.Agent) (apicaller.Connection, error) {
    58  		s.AddCall("openConnection", agent)
    59  		if err := s.NextErr(); err != nil {
    60  			return nil, err
    61  		}
    62  		return s.conn, nil
    63  	})
    64  }
    65  
    66  func (s *ManifoldSuite) TestInputs(c *gc.C) {
    67  	c.Check(s.manifold.Inputs, jc.DeepEquals, []string{"agent-name"})
    68  }
    69  
    70  func (s *ManifoldSuite) TestStartMissingDependency(c *gc.C) {
    71  	getResource := dt.StubGetResource(dt.StubResources{
    72  		"agent-name": dt.StubResource{Error: dependency.ErrMissing},
    73  	})
    74  
    75  	worker, err := s.manifold.Start(getResource)
    76  	c.Check(worker, gc.IsNil)
    77  	c.Check(err, gc.Equals, dependency.ErrMissing)
    78  	s.CheckCalls(c, nil)
    79  }
    80  
    81  func (s *ManifoldSuite) TestStartCannotOpenAPI(c *gc.C) {
    82  	s.SetErrors(errors.New("no api for you"))
    83  
    84  	worker, err := s.manifold.Start(s.getResource)
    85  	c.Check(worker, gc.IsNil)
    86  	c.Check(err, gc.ErrorMatches, "cannot open api: no api for you")
    87  	s.CheckCalls(c, []testing.StubCall{{
    88  		FuncName: "openConnection",
    89  		Args:     []interface{}{s.agent},
    90  	}})
    91  }
    92  
    93  func (s *ManifoldSuite) TestStartSuccessWithEnvironnmentIdSet(c *gc.C) {
    94  	worker, err := s.manifold.Start(s.getResource)
    95  	c.Check(err, jc.ErrorIsNil)
    96  	defer assertStop(c, worker)
    97  	s.CheckCalls(c, []testing.StubCall{{
    98  		FuncName: "openConnection",
    99  		Args:     []interface{}{s.agent},
   100  	}})
   101  }
   102  
   103  func (s *ManifoldSuite) setupMutatorTest(c *gc.C) coreagent.ConfigMutator {
   104  	s.agent.env = names.EnvironTag{}
   105  	s.conn.stub = &s.Stub // will be unsafe if worker stopped before test finished
   106  	s.SetErrors(
   107  		nil, //                                               openConnection,
   108  		errors.New("nonfatal: always logged and ignored"), // ChangeConfig
   109  	)
   110  
   111  	worker, err := s.manifold.Start(s.getResource)
   112  	c.Assert(err, jc.ErrorIsNil)
   113  	s.AddCleanup(func(c *gc.C) { assertStop(c, worker) })
   114  
   115  	s.CheckCallNames(c, "openConnection", "ChangeConfig")
   116  	changeArgs := s.Calls()[1].Args
   117  	c.Assert(changeArgs, gc.HasLen, 1)
   118  	s.ResetCalls()
   119  	return changeArgs[0].(coreagent.ConfigMutator)
   120  }
   121  
   122  func (s *ManifoldSuite) TestStartSuccessWithEnvironnmentIdNotSet(c *gc.C) {
   123  	mutator := s.setupMutatorTest(c)
   124  	mockSetter := &mockSetter{stub: &s.Stub}
   125  
   126  	err := mutator(mockSetter)
   127  	c.Check(err, jc.ErrorIsNil)
   128  	s.CheckCalls(c, []testing.StubCall{{
   129  		FuncName: "EnvironTag",
   130  	}, {
   131  		FuncName: "Migrate",
   132  		Args: []interface{}{coreagent.MigrateParams{
   133  			Environment: coretesting.EnvironmentTag,
   134  		}},
   135  	}})
   136  }
   137  
   138  func (s *ManifoldSuite) TestStartSuccessWithEnvironnmentIdNotSetBadAPIState(c *gc.C) {
   139  	mutator := s.setupMutatorTest(c)
   140  	s.SetErrors(errors.New("no tag for you"))
   141  
   142  	err := mutator(nil)
   143  	c.Check(err, gc.ErrorMatches, "no environment uuid set on api: no tag for you")
   144  	s.CheckCalls(c, []testing.StubCall{{
   145  		FuncName: "EnvironTag",
   146  	}})
   147  }
   148  
   149  func (s *ManifoldSuite) TestStartSuccessWithEnvironnmentIdNotSetMigrateFailure(c *gc.C) {
   150  	mutator := s.setupMutatorTest(c)
   151  	mockSetter := &mockSetter{stub: &s.Stub}
   152  	s.SetErrors(nil, errors.New("migrate failure"))
   153  
   154  	err := mutator(mockSetter)
   155  	c.Check(err, gc.ErrorMatches, "migrate failure")
   156  	s.CheckCalls(c, []testing.StubCall{{
   157  		FuncName: "EnvironTag",
   158  	}, {
   159  		FuncName: "Migrate",
   160  		Args: []interface{}{coreagent.MigrateParams{
   161  			Environment: coretesting.EnvironmentTag,
   162  		}},
   163  	}})
   164  }
   165  
   166  func (s *ManifoldSuite) setupWorkerTest(c *gc.C) worker.Worker {
   167  	w, err := s.manifold.Start(s.getResource)
   168  	c.Assert(err, jc.ErrorIsNil)
   169  	s.AddCleanup(func(c *gc.C) { w.Kill() })
   170  	return w
   171  }
   172  
   173  func (s *ManifoldSuite) TestKillWorkerClosesConnection(c *gc.C) {
   174  	worker := s.setupWorkerTest(c)
   175  	assertStop(c, worker)
   176  	s.conn.stub.CheckCalls(c, []testing.StubCall{{
   177  		FuncName: "Close",
   178  	}})
   179  }
   180  
   181  func (s *ManifoldSuite) TestKillWorkerReportsCloseErr(c *gc.C) {
   182  	s.conn.stub.SetErrors(errors.New("bad plumbing"))
   183  	worker := s.setupWorkerTest(c)
   184  
   185  	assertStopError(c, worker, "bad plumbing")
   186  	s.conn.stub.CheckCalls(c, []testing.StubCall{{
   187  		FuncName: "Close",
   188  	}})
   189  }
   190  
   191  func (s *ManifoldSuite) TestBrokenConnectionKillsWorkerWithCloseErr(c *gc.C) {
   192  	s.conn.stub.SetErrors(errors.New("bad plumbing"))
   193  	worker := s.setupWorkerTest(c)
   194  
   195  	close(s.conn.broken)
   196  	err := worker.Wait()
   197  	c.Check(err, gc.ErrorMatches, "bad plumbing")
   198  	s.conn.stub.CheckCalls(c, []testing.StubCall{{
   199  		FuncName: "Close",
   200  	}})
   201  }
   202  
   203  func (s *ManifoldSuite) TestBrokenConnectionKillsWorkerWithFallbackErr(c *gc.C) {
   204  	worker := s.setupWorkerTest(c)
   205  
   206  	close(s.conn.broken)
   207  	err := worker.Wait()
   208  	c.Check(err, gc.ErrorMatches, "api connection broken unexpectedly")
   209  	s.conn.stub.CheckCalls(c, []testing.StubCall{{
   210  		FuncName: "Close",
   211  	}})
   212  }
   213  
   214  func (s *ManifoldSuite) TestOutputSuccess(c *gc.C) {
   215  	worker := s.setupWorkerTest(c)
   216  
   217  	var apicaller base.APICaller
   218  	err := s.manifold.Output(worker, &apicaller)
   219  	c.Check(err, jc.ErrorIsNil)
   220  	c.Check(apicaller, gc.Equals, s.conn)
   221  }
   222  
   223  func (s *ManifoldSuite) TestOutputBadWorker(c *gc.C) {
   224  	var apicaller base.APICaller
   225  	err := s.manifold.Output(dummyWorker{}, &apicaller)
   226  	c.Check(apicaller, gc.IsNil)
   227  	c.Check(err.Error(), gc.Equals, "expected *apicaller.apiConnWorker->*base.APICaller; got apicaller_test.dummyWorker->*base.APICaller")
   228  }
   229  
   230  func (s *ManifoldSuite) TestOutputBadTarget(c *gc.C) {
   231  	worker := s.setupWorkerTest(c)
   232  
   233  	var apicaller interface{}
   234  	err := s.manifold.Output(worker, &apicaller)
   235  	c.Check(apicaller, gc.IsNil)
   236  	c.Check(err.Error(), gc.Equals, "expected *apicaller.apiConnWorker->*base.APICaller; got *apicaller.apiConnWorker->*interface {}")
   237  }