github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/metrics/sender/manifold_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package sender_test
     5  
     6  import (
     7  	"context"
     8  	"net/http"
     9  	"net/url"
    10  	"os"
    11  	"path/filepath"
    12  
    13  	"github.com/juju/errors"
    14  	"github.com/juju/names/v5"
    15  	"github.com/juju/testing"
    16  	jc "github.com/juju/testing/checkers"
    17  	"github.com/juju/worker/v3"
    18  	"github.com/juju/worker/v3/dependency"
    19  	dt "github.com/juju/worker/v3/dependency/testing"
    20  	gc "gopkg.in/check.v1"
    21  	"gopkg.in/httprequest.v1"
    22  
    23  	"github.com/juju/juju/agent"
    24  	"github.com/juju/juju/api/agent/metricsadder"
    25  	"github.com/juju/juju/api/base"
    26  	"github.com/juju/juju/worker/metrics/sender"
    27  	"github.com/juju/juju/worker/metrics/spool"
    28  )
    29  
    30  type ManifoldSuite struct {
    31  	testing.IsolationSuite
    32  	factory   spool.MetricFactory
    33  	apiCaller *stubAPICaller
    34  	manifold  dependency.Manifold
    35  	resources dt.StubResources
    36  }
    37  
    38  var _ = gc.Suite(&ManifoldSuite{})
    39  
    40  func (s *ManifoldSuite) SetUpTest(c *gc.C) {
    41  	spoolDir := c.MkDir()
    42  	s.IsolationSuite.SetUpTest(c)
    43  	s.factory = &stubMetricFactory{
    44  		&testing.Stub{},
    45  		spoolDir,
    46  	}
    47  
    48  	testAPIClient := func(apiCaller base.APICaller) metricsadder.MetricsAdderClient {
    49  		return newTestAPIMetricSender()
    50  	}
    51  	s.PatchValue(&sender.NewMetricAdderClient, testAPIClient)
    52  
    53  	s.manifold = sender.Manifold(sender.ManifoldConfig{
    54  		AgentName:       "agent",
    55  		APICallerName:   "api-caller",
    56  		MetricSpoolName: "metric-spool",
    57  	})
    58  
    59  	dataDir := c.MkDir()
    60  	// create unit agent base dir so that hooks can run.
    61  	err := os.MkdirAll(filepath.Join(dataDir, "agents", "unit-u-0"), 0777)
    62  	c.Assert(err, jc.ErrorIsNil)
    63  
    64  	s.apiCaller = &stubAPICaller{&testing.Stub{}}
    65  	s.resources = dt.StubResources{
    66  		"agent":        dt.NewStubResource(&dummyAgent{dataDir: dataDir}),
    67  		"api-caller":   dt.NewStubResource(s.apiCaller),
    68  		"metric-spool": dt.NewStubResource(s.factory),
    69  	}
    70  }
    71  
    72  func (s *ManifoldSuite) TestInputs(c *gc.C) {
    73  	c.Check(s.manifold.Inputs, jc.DeepEquals, []string{"agent", "api-caller", "metric-spool"})
    74  }
    75  
    76  func (s *ManifoldSuite) TestStartMissingAPICaller(c *gc.C) {
    77  	context := dt.StubContext(nil, map[string]interface{}{
    78  		"api-caller":   dependency.ErrMissing,
    79  		"metric-spool": s.factory,
    80  	})
    81  	worker, err := s.manifold.Start(context)
    82  	c.Check(worker, gc.IsNil)
    83  	c.Check(err, gc.ErrorMatches, dependency.ErrMissing.Error())
    84  }
    85  
    86  func (s *ManifoldSuite) TestStartMissingAgent(c *gc.C) {
    87  	context := dt.StubContext(nil, map[string]interface{}{
    88  		"agent":        dependency.ErrMissing,
    89  		"api-caller":   &stubAPICaller{&testing.Stub{}},
    90  		"metric-spool": s.factory,
    91  	})
    92  	worker, err := s.manifold.Start(context)
    93  	c.Check(worker, gc.IsNil)
    94  	c.Check(err, gc.ErrorMatches, dependency.ErrMissing.Error())
    95  }
    96  
    97  func (s *ManifoldSuite) TestStartSuccess(c *gc.C) {
    98  	s.setupWorkerTest(c)
    99  }
   100  
   101  func (s *ManifoldSuite) setupWorkerTest(c *gc.C) worker.Worker {
   102  	worker, err := s.manifold.Start(s.resources.Context())
   103  	c.Check(err, jc.ErrorIsNil)
   104  	s.AddCleanup(func(c *gc.C) {
   105  		worker.Kill()
   106  		err := worker.Wait()
   107  		c.Check(err, jc.ErrorIsNil)
   108  	})
   109  	return worker
   110  }
   111  
   112  type mockListener struct {
   113  	testing.Stub
   114  	spool.ConnectionHandler
   115  }
   116  
   117  // Stop implements the stopper interface.
   118  func (l *mockListener) Stop() error {
   119  	l.AddCall("Stop")
   120  	return nil
   121  }
   122  
   123  func (s *ManifoldSuite) TestWorkerErrorStopsSender(c *gc.C) {
   124  	listener := &mockListener{}
   125  	s.PatchValue(sender.NewListener, sender.NewListenerFunc(listener))
   126  
   127  	s.apiCaller.SetErrors(errors.New("blah"))
   128  
   129  	worker, err := s.manifold.Start(s.resources.Context())
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	c.Assert(worker, gc.NotNil)
   132  	err = worker.Wait()
   133  	c.Assert(err, gc.ErrorMatches, ".*blah")
   134  	listener.CheckCallNames(c, "Stop")
   135  }
   136  
   137  var _ base.APICaller = (*stubAPICaller)(nil)
   138  
   139  type stubAPICaller struct {
   140  	*testing.Stub
   141  }
   142  
   143  func (s *stubAPICaller) APICall(objType string, version int, id, request string, params, response interface{}) error {
   144  	s.MethodCall(s, "APICall", objType, version, id, request, params, response)
   145  	return s.NextErr()
   146  }
   147  
   148  func (s *stubAPICaller) BestFacadeVersion(facade string) int {
   149  	s.MethodCall(s, "BestFacadeVersion", facade)
   150  	return 42
   151  }
   152  
   153  func (s *stubAPICaller) ModelTag() (names.ModelTag, bool) {
   154  	s.MethodCall(s, "ModelTag")
   155  	return names.NewModelTag("foobar"), true
   156  }
   157  
   158  func (s *stubAPICaller) ConnectStream(string, url.Values) (base.Stream, error) {
   159  	panic("should not be called")
   160  }
   161  
   162  func (s *stubAPICaller) ConnectControllerStream(string, url.Values, http.Header) (base.Stream, error) {
   163  	panic("should not be called")
   164  }
   165  
   166  func (s *stubAPICaller) HTTPClient() (*httprequest.Client, error) {
   167  	panic("should not be called")
   168  }
   169  
   170  func (s *stubAPICaller) RootHTTPClient() (*httprequest.Client, error) {
   171  	panic("should not be called")
   172  }
   173  
   174  func (s *stubAPICaller) Context() context.Context {
   175  	return context.Background()
   176  }
   177  
   178  func (s *stubAPICaller) BakeryClient() base.MacaroonDischarger {
   179  	panic("should not be called")
   180  }
   181  
   182  type dummyAgent struct {
   183  	agent.Agent
   184  	dataDir string
   185  }
   186  
   187  func (a dummyAgent) CurrentConfig() agent.Config {
   188  	return &dummyAgentConfig{dataDir: a.dataDir}
   189  }
   190  
   191  type dummyAgentConfig struct {
   192  	agent.Config
   193  	dataDir string
   194  }
   195  
   196  // Tag implements agent.AgentConfig.
   197  func (ac dummyAgentConfig) Tag() names.Tag {
   198  	return names.NewUnitTag("u/0")
   199  }
   200  
   201  // DataDir implements agent.AgentConfig.
   202  func (ac dummyAgentConfig) DataDir() string {
   203  	return ac.dataDir
   204  }