github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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/testing"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/agent"
    13  	"github.com/juju/juju/api"
    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/apicaller"
    18  	"github.com/juju/juju/worker/dependency"
    19  	dt "github.com/juju/juju/worker/dependency/testing"
    20  )
    21  
    22  type ManifoldSuite struct {
    23  	testing.IsolationSuite
    24  	testing.Stub
    25  	manifold dependency.Manifold
    26  	agent    *mockAgent
    27  	conn     *mockConn
    28  	context  dependency.Context
    29  }
    30  
    31  var _ = gc.Suite(&ManifoldSuite{})
    32  
    33  func (s *ManifoldSuite) SetUpTest(c *gc.C) {
    34  	s.IsolationSuite.SetUpTest(c)
    35  	s.Stub = testing.Stub{}
    36  	s.manifold = apicaller.Manifold(apicaller.ManifoldConfig{
    37  		AgentName:            "agent-name",
    38  		APIConfigWatcherName: "api-config-watcher-name",
    39  		APIOpen: func(*api.Info, api.DialOpts) (api.Connection, error) {
    40  			panic("just a fake")
    41  		},
    42  		NewConnection: func(a agent.Agent, apiOpen api.OpenFunc) (api.Connection, error) {
    43  			c.Check(apiOpen, gc.NotNil) // uncomparable
    44  			s.AddCall("NewConnection", a)
    45  			if err := s.NextErr(); err != nil {
    46  				return nil, err
    47  			}
    48  			return s.conn, nil
    49  		},
    50  		Filter: func(err error) error {
    51  			panic(err)
    52  		},
    53  	})
    54  	checkFilter := func() {
    55  		s.manifold.Filter(errors.New("arrgh"))
    56  	}
    57  	c.Check(checkFilter, gc.PanicMatches, "arrgh")
    58  
    59  	s.agent = &mockAgent{
    60  		stub:  &s.Stub,
    61  		model: coretesting.ModelTag,
    62  	}
    63  	s.context = dt.StubContext(nil, map[string]interface{}{
    64  		"agent-name": s.agent,
    65  	})
    66  
    67  	// Watch out for this: it uses its own Stub because Close calls
    68  	// are made from the worker's loop goroutine. You should make
    69  	// sure to stop the worker before checking the mock conn's calls.
    70  	s.conn = &mockConn{
    71  		stub:   &testing.Stub{},
    72  		broken: make(chan struct{}),
    73  	}
    74  }
    75  
    76  func (s *ManifoldSuite) TestInputs(c *gc.C) {
    77  	c.Check(s.manifold.Inputs, jc.DeepEquals, []string{
    78  		"agent-name",
    79  		"api-config-watcher-name",
    80  	})
    81  }
    82  
    83  func (s *ManifoldSuite) TestStartMissingAgent(c *gc.C) {
    84  	context := dt.StubContext(nil, map[string]interface{}{
    85  		"agent-name": dependency.ErrMissing,
    86  	})
    87  
    88  	worker, err := s.manifold.Start(context)
    89  	c.Check(worker, gc.IsNil)
    90  	c.Check(err, gc.Equals, dependency.ErrMissing)
    91  	s.CheckCalls(c, nil)
    92  }
    93  
    94  func (s *ManifoldSuite) TestStartCannotOpenAPI(c *gc.C) {
    95  	s.SetErrors(errors.New("no api for you"))
    96  
    97  	worker, err := s.manifold.Start(s.context)
    98  	c.Check(worker, gc.IsNil)
    99  	c.Check(err, gc.ErrorMatches, "cannot open api: no api for you")
   100  	s.CheckCalls(c, []testing.StubCall{{
   101  		FuncName: "NewConnection",
   102  		Args:     []interface{}{s.agent},
   103  	}})
   104  }
   105  
   106  func (s *ManifoldSuite) TestStartSuccess(c *gc.C) {
   107  	worker, err := s.manifold.Start(s.context)
   108  	c.Check(err, jc.ErrorIsNil)
   109  	defer assertStop(c, worker)
   110  	s.CheckCalls(c, []testing.StubCall{{
   111  		FuncName: "NewConnection",
   112  		Args:     []interface{}{s.agent},
   113  	}})
   114  }
   115  
   116  func (s *ManifoldSuite) setupWorkerTest(c *gc.C) worker.Worker {
   117  	w, err := s.manifold.Start(s.context)
   118  	c.Assert(err, jc.ErrorIsNil)
   119  	s.AddCleanup(func(c *gc.C) { w.Kill() })
   120  	return w
   121  }
   122  
   123  func (s *ManifoldSuite) TestKillWorkerClosesConnection(c *gc.C) {
   124  	worker := s.setupWorkerTest(c)
   125  	assertStop(c, worker)
   126  	s.conn.stub.CheckCalls(c, []testing.StubCall{{
   127  		FuncName: "Close",
   128  	}})
   129  }
   130  
   131  func (s *ManifoldSuite) TestKillWorkerReportsCloseErr(c *gc.C) {
   132  	s.conn.stub.SetErrors(errors.New("bad plumbing"))
   133  	worker := s.setupWorkerTest(c)
   134  
   135  	assertStopError(c, worker, "bad plumbing")
   136  	s.conn.stub.CheckCalls(c, []testing.StubCall{{
   137  		FuncName: "Close",
   138  	}})
   139  }
   140  
   141  func (s *ManifoldSuite) TestBrokenConnectionKillsWorkerWithCloseErr(c *gc.C) {
   142  	s.conn.stub.SetErrors(errors.New("bad plumbing"))
   143  	worker := s.setupWorkerTest(c)
   144  
   145  	close(s.conn.broken)
   146  	err := worker.Wait()
   147  	c.Check(err, gc.ErrorMatches, "bad plumbing")
   148  	s.conn.stub.CheckCalls(c, []testing.StubCall{{
   149  		FuncName: "Close",
   150  	}})
   151  }
   152  
   153  func (s *ManifoldSuite) TestBrokenConnectionKillsWorkerWithFallbackErr(c *gc.C) {
   154  	worker := s.setupWorkerTest(c)
   155  
   156  	close(s.conn.broken)
   157  	err := worker.Wait()
   158  	c.Check(err, gc.ErrorMatches, "api connection broken unexpectedly")
   159  	s.conn.stub.CheckCalls(c, []testing.StubCall{{
   160  		FuncName: "Close",
   161  	}})
   162  }
   163  
   164  func (s *ManifoldSuite) TestOutputSuccess(c *gc.C) {
   165  	worker := s.setupWorkerTest(c)
   166  
   167  	var apicaller base.APICaller
   168  	err := s.manifold.Output(worker, &apicaller)
   169  	c.Check(err, jc.ErrorIsNil)
   170  	c.Check(apicaller, gc.Equals, s.conn)
   171  
   172  	var conn api.Connection
   173  	err = s.manifold.Output(worker, &conn)
   174  	c.Check(err, jc.ErrorIsNil)
   175  	c.Check(conn, gc.Equals, s.conn)
   176  }
   177  
   178  func (s *ManifoldSuite) TestOutputBadWorker(c *gc.C) {
   179  	var apicaller base.APICaller
   180  	err := s.manifold.Output(dummyWorker{}, &apicaller)
   181  	c.Check(apicaller, gc.IsNil)
   182  	c.Check(err.Error(), gc.Equals, "in should be a *apicaller.apiConnWorker; got apicaller_test.dummyWorker")
   183  }
   184  
   185  func (s *ManifoldSuite) TestOutputBadTarget(c *gc.C) {
   186  	worker := s.setupWorkerTest(c)
   187  
   188  	var apicaller interface{}
   189  	err := s.manifold.Output(worker, &apicaller)
   190  	c.Check(apicaller, gc.IsNil)
   191  	c.Check(err.Error(), gc.Equals, "out should be *base.APICaller or *api.Connection; got *interface {}")
   192  }