github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/singular/manifold_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package singular_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/clock/testclock"
    10  	"github.com/juju/errors"
    11  	"github.com/juju/names/v5"
    12  	"github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	"github.com/juju/worker/v3"
    15  	"github.com/juju/worker/v3/dependency"
    16  	dt "github.com/juju/worker/v3/dependency/testing"
    17  	gc "gopkg.in/check.v1"
    18  
    19  	"github.com/juju/juju/api/base"
    20  	"github.com/juju/juju/cmd/jujud/agent/engine"
    21  	coretesting "github.com/juju/juju/testing"
    22  	"github.com/juju/juju/worker/singular"
    23  )
    24  
    25  type ManifoldSuite struct {
    26  	testing.IsolationSuite
    27  
    28  	config singular.ManifoldConfig
    29  }
    30  
    31  var _ = gc.Suite(&ManifoldSuite{})
    32  
    33  func (s *ManifoldSuite) SetUpTest(c *gc.C) {
    34  	s.IsolationSuite.SetUpTest(c)
    35  
    36  	s.config = singular.ManifoldConfig{
    37  		Clock:         testclock.NewClock(time.Now()),
    38  		APICallerName: "api-caller",
    39  		Duration:      time.Minute,
    40  		NewFacade: func(base.APICaller, names.Tag, names.Tag) (singular.Facade, error) {
    41  			return nil, errors.NotImplementedf("NewFacade")
    42  		},
    43  		NewWorker: func(config singular.FlagConfig) (worker.Worker, error) {
    44  			return nil, errors.NotImplementedf("NewWorker")
    45  		},
    46  	}
    47  }
    48  
    49  func (s *ManifoldSuite) TestValidate(c *gc.C) {
    50  	c.Check(s.config.Validate(), jc.ErrorIsNil)
    51  }
    52  
    53  func (s *ManifoldSuite) TestValidateMissingClock(c *gc.C) {
    54  	s.config.Clock = nil
    55  	err := s.config.Validate()
    56  	c.Check(err, jc.Satisfies, errors.IsNotValid)
    57  	c.Check(err.Error(), gc.Equals, "nil Clock not valid")
    58  }
    59  
    60  func (s *ManifoldSuite) TestValidateMissingAPICallerName(c *gc.C) {
    61  	s.config.APICallerName = ""
    62  	err := s.config.Validate()
    63  	c.Check(err, jc.Satisfies, errors.IsNotValid)
    64  	c.Check(err.Error(), gc.Equals, "missing APICallerName not valid")
    65  }
    66  
    67  func (s *ManifoldSuite) TestValidateMissingNewFacade(c *gc.C) {
    68  	s.config.NewFacade = nil
    69  	err := s.config.Validate()
    70  	c.Check(err, jc.Satisfies, errors.IsNotValid)
    71  	c.Check(err.Error(), gc.Equals, "nil NewFacade not valid")
    72  }
    73  
    74  func (s *ManifoldSuite) TestValidateMissingNewWorker(c *gc.C) {
    75  	s.config.NewWorker = nil
    76  	err := s.config.Validate()
    77  	c.Check(err, jc.Satisfies, errors.IsNotValid)
    78  	c.Check(err.Error(), gc.Equals, "nil NewWorker not valid")
    79  }
    80  
    81  func (s *ManifoldSuite) TestInputs(c *gc.C) {
    82  	manifold := singular.Manifold(singular.ManifoldConfig{
    83  		APICallerName: "kim",
    84  	})
    85  	expectInputs := []string{"kim"}
    86  	c.Check(manifold.Inputs, jc.DeepEquals, expectInputs)
    87  }
    88  
    89  func (s *ManifoldSuite) TestOutputBadWorker(c *gc.C) {
    90  	manifold := singular.Manifold(singular.ManifoldConfig{})
    91  	var out engine.Flag
    92  	err := manifold.Output(&fakeWorker{}, &out)
    93  	c.Check(err, gc.ErrorMatches, `expected in to implement Flag; got a .*`)
    94  	c.Check(out, gc.IsNil)
    95  }
    96  
    97  func (s *ManifoldSuite) TestOutputBadResult(c *gc.C) {
    98  	manifold := singular.Manifold(singular.ManifoldConfig{})
    99  	fix := newFixture(c)
   100  	fix.Run(c, func(flag *singular.FlagWorker, _ *testclock.Clock, _ func()) {
   101  		var out interface{}
   102  		err := manifold.Output(flag, &out)
   103  		c.Check(err, gc.ErrorMatches, `expected out to be a \*Flag; got a .*`)
   104  		c.Check(out, gc.IsNil)
   105  	})
   106  }
   107  
   108  func (s *ManifoldSuite) TestOutputSuccess(c *gc.C) {
   109  	manifold := singular.Manifold(singular.ManifoldConfig{})
   110  	fix := newFixture(c)
   111  	fix.Run(c, func(flag *singular.FlagWorker, _ *testclock.Clock, _ func()) {
   112  		var out engine.Flag
   113  		err := manifold.Output(flag, &out)
   114  		c.Check(err, jc.ErrorIsNil)
   115  		c.Check(out, gc.Equals, flag)
   116  	})
   117  }
   118  
   119  func (s *ManifoldSuite) TestStartMissingClock(c *gc.C) {
   120  	manifold := singular.Manifold(singular.ManifoldConfig{
   121  		APICallerName: "api-caller",
   122  	})
   123  	context := dt.StubContext(nil, map[string]interface{}{})
   124  
   125  	worker, err := manifold.Start(context)
   126  	c.Check(errors.Cause(err), gc.ErrorMatches, `nil Clock not valid`)
   127  	c.Check(worker, gc.IsNil)
   128  }
   129  
   130  func (s *ManifoldSuite) TestStartMissingAPICaller(c *gc.C) {
   131  	manifold := singular.Manifold(s.config)
   132  	context := dt.StubContext(nil, map[string]interface{}{
   133  		"api-caller": dependency.ErrMissing,
   134  	})
   135  
   136  	worker, err := manifold.Start(context)
   137  	c.Check(errors.Cause(err), gc.Equals, dependency.ErrMissing)
   138  	c.Check(worker, gc.IsNil)
   139  }
   140  
   141  func (s *ManifoldSuite) TestStartNewFacadeError(c *gc.C) {
   142  	expectAPICaller := &fakeAPICaller{}
   143  	s.config.Claimant = names.NewMachineTag("123")
   144  	s.config.Entity = coretesting.ModelTag
   145  	s.config.NewFacade = func(apiCaller base.APICaller, claimant names.Tag, entity names.Tag) (singular.Facade, error) {
   146  		c.Check(apiCaller, gc.Equals, expectAPICaller)
   147  		c.Check(claimant.String(), gc.Equals, "machine-123")
   148  		c.Check(entity, gc.Equals, coretesting.ModelTag)
   149  		return nil, errors.New("grark plop")
   150  	}
   151  	manifold := singular.Manifold(s.config)
   152  	context := dt.StubContext(nil, map[string]interface{}{
   153  		"api-caller": expectAPICaller,
   154  	})
   155  
   156  	worker, err := manifold.Start(context)
   157  	c.Check(err, gc.ErrorMatches, "grark plop")
   158  	c.Check(worker, gc.IsNil)
   159  }
   160  
   161  func (s *ManifoldSuite) TestStartNewWorkerError(c *gc.C) {
   162  	expectFacade := &fakeFacade{}
   163  	s.config.NewFacade = func(base.APICaller, names.Tag, names.Tag) (singular.Facade, error) {
   164  		return expectFacade, nil
   165  	}
   166  	s.config.NewWorker = func(config singular.FlagConfig) (worker.Worker, error) {
   167  		c.Check(config.Facade, gc.Equals, expectFacade)
   168  		err := config.Validate()
   169  		c.Check(err, jc.ErrorIsNil)
   170  		return nil, errors.New("blomp tik")
   171  	}
   172  	manifold := singular.Manifold(s.config)
   173  	context := dt.StubContext(nil, map[string]interface{}{
   174  		"api-caller": &fakeAPICaller{},
   175  	})
   176  
   177  	worker, err := manifold.Start(context)
   178  	c.Check(err, gc.ErrorMatches, "blomp tik")
   179  	c.Check(worker, gc.IsNil)
   180  }
   181  
   182  func (s *ManifoldSuite) TestStartSuccess(c *gc.C) {
   183  	var stub testing.Stub
   184  	expectWorker := newStubWorker(&stub)
   185  	s.config.NewFacade = func(base.APICaller, names.Tag, names.Tag) (singular.Facade, error) {
   186  		return &fakeFacade{}, nil
   187  	}
   188  	s.config.NewWorker = func(_ singular.FlagConfig) (worker.Worker, error) {
   189  		return expectWorker, nil
   190  	}
   191  	manifold := singular.Manifold(s.config)
   192  	context := dt.StubContext(nil, map[string]interface{}{
   193  		"api-caller": &fakeAPICaller{},
   194  	})
   195  
   196  	worker, err := manifold.Start(context)
   197  	c.Check(err, jc.ErrorIsNil)
   198  
   199  	var out engine.Flag
   200  	err = manifold.Output(worker, &out)
   201  	c.Check(err, jc.ErrorIsNil)
   202  	c.Check(out.Check(), jc.IsTrue)
   203  
   204  	c.Check(worker.Wait(), jc.ErrorIsNil)
   205  	stub.CheckCallNames(c, "Check", "Wait")
   206  }
   207  
   208  func (s *ManifoldSuite) TestWorkerBouncesOnRefresh(c *gc.C) {
   209  	var stub testing.Stub
   210  	stub.SetErrors(singular.ErrRefresh)
   211  	errWorker := newStubWorker(&stub)
   212  	s.config.NewFacade = func(base.APICaller, names.Tag, names.Tag) (singular.Facade, error) {
   213  		return &fakeFacade{}, nil
   214  	}
   215  	s.config.NewWorker = func(_ singular.FlagConfig) (worker.Worker, error) {
   216  		return errWorker, nil
   217  	}
   218  
   219  	manifold := singular.Manifold(s.config)
   220  	context := dt.StubContext(nil, map[string]interface{}{
   221  		"api-caller": &fakeAPICaller{},
   222  	})
   223  
   224  	worker, err := manifold.Start(context)
   225  	c.Check(err, jc.ErrorIsNil)
   226  	c.Check(worker.Wait(), gc.Equals, dependency.ErrBounce)
   227  }