github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/integration/suites/harness/agent_test.go (about)

     1  // Copyright (c) 2022, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package harness
     6  
     7  import (
     8  	"context"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/choria-io/go-choria/choria"
    14  	"github.com/choria-io/go-choria/client/rpcutilclient"
    15  	"github.com/choria-io/go-choria/config"
    16  	"github.com/choria-io/go-choria/integration/agentharness"
    17  	"github.com/choria-io/go-choria/integration/testbroker"
    18  	"github.com/choria-io/go-choria/integration/testutil"
    19  	"github.com/choria-io/go-choria/inter"
    20  	"github.com/choria-io/go-choria/internal/fs"
    21  	"github.com/choria-io/go-choria/providers/agent/mcorpc"
    22  	"github.com/choria-io/go-choria/server"
    23  	"github.com/golang/mock/gomock"
    24  	. "github.com/onsi/ginkgo/v2"
    25  	. "github.com/onsi/gomega"
    26  	"github.com/onsi/gomega/gbytes"
    27  	"github.com/sirupsen/logrus"
    28  )
    29  
    30  func TestAgentHarnessAgent(t *testing.T) {
    31  	RegisterFailHandler(Fail)
    32  	RunSpecs(t, "Integration/Agent Testing Harness")
    33  }
    34  
    35  var _ = Describe("testing harness agent", func() {
    36  	var (
    37  		ctx           context.Context
    38  		cancel        context.CancelFunc
    39  		wg            sync.WaitGroup
    40  		srv           *server.Instance
    41  		rpcutilAgent  *agentharness.AgentHarness
    42  		rpcutilClient *rpcutilclient.RpcutilClient
    43  		brokerLogger  *logrus.Logger
    44  		brokerLogbuff *gbytes.Buffer
    45  		serverLogbuff *gbytes.Buffer
    46  		mockCtl       *gomock.Controller
    47  		err           error
    48  	)
    49  
    50  	startServerInstance := func(cfgFile string, logbuff *gbytes.Buffer) (*server.Instance, error) {
    51  		logger := logrus.New()
    52  		logger.SetOutput(logbuff)
    53  
    54  		srv, err = testutil.StartServerInstance(ctx, &wg, cfgFile, logger, testutil.ServerWithDiscovery())
    55  		Expect(err).ToNot(HaveOccurred())
    56  
    57  		Eventually(logbuff).Should(gbytes.Say("Connected to nats://localhost:4222"))
    58  		Eventually(logbuff).Should(gbytes.Say("Registering new agent discovery of type discovery"))
    59  
    60  		return srv, nil
    61  	}
    62  
    63  	createAgent := func(fw inter.Framework) *mcorpc.Agent {
    64  		ddl, err := fs.FS.ReadFile("ddl/cache/agent/rpcutil.json")
    65  		Expect(err).ToNot(HaveOccurred())
    66  
    67  		rpcutilAgent, err = agentharness.NewWithDDLBytes(fw, mockCtl, "rpcutil", ddl)
    68  		Expect(err).ToNot(HaveOccurred())
    69  
    70  		a, err := rpcutilAgent.Agent()
    71  		Expect(err).ToNot(HaveOccurred())
    72  
    73  		return a
    74  	}
    75  
    76  	createRpcUtilClient := func() (*gbytes.Buffer, *rpcutilclient.RpcutilClient, error) {
    77  		logBuff, logger := testutil.GbytesLogger(logrus.DebugLevel)
    78  
    79  		cfg, err := config.NewConfig("testdata/client.conf")
    80  		if err != nil {
    81  			return nil, nil, err
    82  		}
    83  
    84  		cfg.CustomLogger = logger
    85  		cfg.OverrideCertname = "rip.mcollective"
    86  
    87  		fw, err := choria.NewWithConfig(cfg)
    88  		if err != nil {
    89  			return nil, nil, err
    90  		}
    91  
    92  		client, err := rpcutilclient.New(fw)
    93  		if err != nil {
    94  			return nil, nil, err
    95  		}
    96  
    97  		return logBuff, client, nil
    98  	}
    99  
   100  	BeforeEach(func() {
   101  		mockCtl = gomock.NewController(GinkgoT())
   102  
   103  		ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
   104  		DeferCleanup(func() {
   105  			cancel()
   106  			Eventually(brokerLogbuff, 5).Should(gbytes.Say("Choria Network Broker shut down"))
   107  		})
   108  
   109  		brokerLogbuff, brokerLogger = testutil.GbytesLogger(logrus.DebugLevel)
   110  		serverLogbuff = gbytes.NewBuffer()
   111  
   112  		_, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/broker.conf", brokerLogger)
   113  		Expect(err).ToNot(HaveOccurred())
   114  		Eventually(brokerLogbuff, 1).Should(gbytes.Say("Server is ready"))
   115  
   116  		srv, err = startServerInstance("testdata/server.conf", serverLogbuff)
   117  		Expect(err).ToNot(HaveOccurred())
   118  
   119  		err = srv.AgentManager().RegisterAgent(ctx, "rpcutil", createAgent(srv.Choria()), srv.Connector())
   120  		Expect(err).ToNot(HaveOccurred())
   121  
   122  		Eventually(serverLogbuff).Should(gbytes.Say("Registering new agent rpcutil of type rpcutil"))
   123  
   124  		_, rpcutilClient, err = createRpcUtilClient()
   125  		Expect(err).ToNot(HaveOccurred())
   126  	})
   127  
   128  	AfterEach(func() {
   129  		mockCtl.Finish()
   130  	})
   131  
   132  	Describe("action stubbing", func() {
   133  		It("Should do the correct stubs", FlakeAttempts(5), func() {
   134  			rpcutilAgent.Stub("ping", func(_ context.Context, _ *mcorpc.Request, reply *mcorpc.Reply, _ *mcorpc.Agent, _ inter.ConnectorInfo) {
   135  				reply.Data = map[string]any{
   136  					"pong": time.Now().Unix(),
   137  				}
   138  			}).AnyTimes()
   139  
   140  			for i := 0; i < 5; i++ {
   141  				res, err := rpcutilClient.OptionFactFilter("hello=world").Ping().Do(ctx)
   142  				Expect(err).ToNot(HaveOccurred())
   143  				Expect(res.Stats().OKCount()).To(Equal(1))
   144  				r := res.AllOutputs()[0]
   145  				Expect(err).ToNot(HaveOccurred())
   146  				Expect(r.Pong()).To(BeNumerically("==", time.Now().Unix(), 1))
   147  			}
   148  
   149  			// checks that the server did indeed sent back 10 - 5+discovery replies ie. round trip calls all happened
   150  			// we check for >= 10 since flake attempts will continue to increase the stats
   151  			Expect(srv.Stats().Replies).To(BeNumerically(">=", 10))
   152  		})
   153  	})
   154  })