github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/providers/agent/mcorpc/client/stats_test.go (about)

     1  // Copyright (c) 2020-2021, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package client
     6  
     7  import (
     8  	"sort"
     9  	"strings"
    10  	"time"
    11  
    12  	. "github.com/onsi/ginkgo/v2"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("McoRPC/Client/Stats", func() {
    17  	Describe("All", func() {
    18  		var (
    19  			s *Stats
    20  		)
    21  
    22  		BeforeEach(func() {
    23  			s = NewStats()
    24  		})
    25  
    26  		Describe("Merge", func() {
    27  			It("Should correctly merge", func() {
    28  				other := NewStats()
    29  
    30  				s.SetDiscoveredNodes([]string{"host1", "host2", "host3"})
    31  				other.SetDiscoveredNodes([]string{"host2", "host3"})
    32  
    33  				other.StartPublish()
    34  				other.publishStart = other.publishStart.Add(-10 * time.Second)
    35  
    36  				other.RecordReceived("host2")
    37  				other.RecordReceived("host3")
    38  				other.RecordReceived("host4")
    39  				other.PassedRequestInc()
    40  				other.FailedRequestInc()
    41  
    42  				other.EndPublish()
    43  
    44  				s.Merge(other)
    45  
    46  				Expect(s.UnexpectedResponseFrom()).To(Equal([]string{"host4"}))
    47  				Expect(s.outstandingNodes.Hosts()).To(Equal([]string{"host1"}))
    48  				Expect(s.FailCount()).To(Equal(1))
    49  				Expect(s.OKCount()).To(Equal(1))
    50  				Expect(s.PublishDuration()).To(BeNumerically("~", 10*time.Second, 10*time.Millisecond))
    51  			})
    52  		})
    53  
    54  		Describe("SetAgent / Agent", func() {
    55  			It("Should set and get the right agent", func() {
    56  				Expect(s.Agent()).To(Equal(""))
    57  				s.SetAgent("foo")
    58  				Expect(s.Agent()).To(Equal("foo"))
    59  			})
    60  		})
    61  
    62  		Describe("SetAction / Action", func() {
    63  			It("Should set and get the right action", func() {
    64  				Expect(s.Action()).To(Equal(""))
    65  				s.SetAction("foo")
    66  				Expect(s.Action()).To(Equal("foo"))
    67  			})
    68  		})
    69  
    70  		Describe("All", func() {
    71  			It("Should correctly determine if all nodes have completed", func() {
    72  				s.SetDiscoveredNodes([]string{"host1", "host2"})
    73  				Expect(s.All()).To(BeFalse())
    74  				s.RecordReceived("host1")
    75  				Expect(s.All()).To(BeFalse())
    76  				s.RecordReceived("host2")
    77  				Expect(s.All()).To(BeTrue())
    78  			})
    79  		})
    80  
    81  		Describe("NoResponseFrom", func() {
    82  			It("Should return the correct list", func() {
    83  				s.SetDiscoveredNodes([]string{"host1", "host2"})
    84  
    85  				nr := s.NoResponseFrom()
    86  				sort.Strings(nr)
    87  				Expect(nr).To(Equal(strings.Fields("host1 host2")))
    88  
    89  				s.RecordReceived("host1")
    90  				Expect(s.NoResponseFrom()).To(Equal([]string{"host2"}))
    91  
    92  				s.RecordReceived("host2")
    93  				Expect(s.NoResponseFrom()).To(Equal([]string{}))
    94  			})
    95  		})
    96  
    97  		Describe("UnexpectedResponseFrom", func() {
    98  			It("Should report correctly", func() {
    99  				s.SetDiscoveredNodes([]string{"host1", "host2"})
   100  				Expect(s.UnexpectedResponseFrom()).To(Equal([]string{}))
   101  				s.RecordReceived("host3")
   102  				Expect(s.UnexpectedResponseFrom()).To(Equal([]string{"host3"}))
   103  			})
   104  		})
   105  
   106  		Describe("WaitingFor", func() {
   107  			It("Should report nodes correctly", func() {
   108  				s.SetDiscoveredNodes([]string{"host1", "host2"})
   109  				Expect(s.outstandingNodes.Count()).To(Equal(2))
   110  				Expect(s.outstandingNodes.HaveAny("host1", "host2")).To(BeTrue())
   111  				Expect(s.WaitingFor([]string{"host1", "host2"})).To(BeTrue())
   112  				Expect(s.WaitingFor([]string{"host3", "host4"})).To(BeFalse())
   113  			})
   114  		})
   115  
   116  		Describe("SetDiscoveredNodes", func() {
   117  			It("Should set the node and outstanding nodes", func() {
   118  				s.outstandingNodes.AddHosts("host100")
   119  				s.SetDiscoveredNodes([]string{"host1", "host2"})
   120  				Expect(s.discoveredNodes).To(Equal([]string{"host1", "host2"}))
   121  
   122  				o := s.outstandingNodes.Hosts()
   123  				sort.Strings(o)
   124  				Expect(o).To(Equal([]string{"host1", "host2"}))
   125  			})
   126  		})
   127  
   128  		Describe("FailedRequestInc", func() {
   129  			It("Should increase the count", func() {
   130  				Expect(s.failed).To(Equal(int32(0)))
   131  				s.FailedRequestInc()
   132  				Expect(s.failed).To(Equal(int32(1)))
   133  			})
   134  		})
   135  
   136  		Describe("PassedRequestInc", func() {
   137  			It("Should increase the count", func() {
   138  				Expect(s.passed).To(Equal(int32(0)))
   139  				s.PassedRequestInc()
   140  				Expect(s.passed).To(Equal(int32(1)))
   141  			})
   142  		})
   143  
   144  		Describe("RecordReceived", func() {
   145  			It("Should handle outstanding nodes", func() {
   146  				s.SetDiscoveredNodes([]string{"host1", "host2"})
   147  				Expect(s.responses).To(Equal(int32(0)))
   148  				s.RecordReceived("host2")
   149  				Expect(s.responses).To(Equal(int32(1)))
   150  				Expect(s.NoResponseFrom()).To(Equal([]string{"host1"}))
   151  			})
   152  
   153  			It("Should handle unexpected nodes", func() {
   154  				s.SetDiscoveredNodes([]string{"host1", "host2"})
   155  				Expect(s.responses).To(Equal(int32(0)))
   156  				s.RecordReceived("host3")
   157  				Expect(s.responses).To(Equal(int32(1)))
   158  				Expect(s.UnexpectedResponseFrom()).To(Equal([]string{"host3"}))
   159  			})
   160  		})
   161  
   162  		Describe("DiscoveredCount", func() {
   163  			It("Should return the right length", func() {
   164  				Expect(s.DiscoveredCount()).To(Equal(0))
   165  				s.SetDiscoveredNodes([]string{"host1", "host2"})
   166  				Expect(s.DiscoveredCount()).To(Equal(2))
   167  			})
   168  		})
   169  
   170  		Describe("FailCount", func() {
   171  			It("Should return the right length", func() {
   172  				Expect(s.FailCount()).To(Equal(0))
   173  				s.FailedRequestInc()
   174  				Expect(s.FailCount()).To(Equal(1))
   175  			})
   176  		})
   177  
   178  		Describe("OKCount", func() {
   179  			It("Should return the right length", func() {
   180  				Expect(s.OKCount()).To(Equal(0))
   181  				s.PassedRequestInc()
   182  				Expect(s.OKCount()).To(Equal(1))
   183  			})
   184  		})
   185  
   186  		Describe("ResponsesCount", func() {
   187  			It("Should return the right length", func() {
   188  				Expect(s.ResponsesCount()).To(Equal(0))
   189  				s.RecordReceived("host1")
   190  				Expect(s.ResponsesCount()).To(Equal(1))
   191  			})
   192  		})
   193  
   194  		Describe("StartPublish", func() {
   195  			It("Should start the clock if it has not yet started", func() {
   196  				Expect(s.publishStart).To(BeZero())
   197  				s.StartPublish()
   198  
   199  				t := s.publishStart
   200  				Expect(t).ToNot(BeZero())
   201  
   202  				s.StartPublish()
   203  				Expect(s.publishStart).To(Equal(t))
   204  			})
   205  		})
   206  
   207  		Describe("EndPublish", func() {
   208  			It("Should end the publishing if its not already ended", func() {
   209  				Expect(s.publishEnd).To(BeZero())
   210  				s.StartPublish()
   211  				s.EndPublish()
   212  
   213  				t := s.publishEnd
   214  				Expect(t).ToNot(BeZero())
   215  
   216  				s.EndPublish()
   217  				Expect(s.publishEnd).To(Equal(t))
   218  			})
   219  		})
   220  
   221  		Describe("PublishDuration", func() {
   222  			It("Should handle in-progress or not yet started requests", func() {
   223  				_, err := s.PublishDuration()
   224  				Expect(err).To(MatchError("publishing is not completed"))
   225  
   226  				s.StartPublish()
   227  				_, err = s.PublishDuration()
   228  				Expect(err).To(MatchError("publishing is not completed"))
   229  
   230  				s.publishStart = time.Now().Add(-10 * time.Second)
   231  
   232  				Expect(s.publishStart).ToNot(BeZero())
   233  				Expect(s.publishing).To(BeTrue())
   234  				Expect(s.publishEnd).To(BeZero())
   235  
   236  				s.EndPublish()
   237  
   238  				Expect(s.publishEnd).ToNot(BeZero())
   239  				Expect(s.publishing).To(BeFalse())
   240  
   241  				_, err = s.PublishDuration()
   242  				Expect(err).ToNot(HaveOccurred())
   243  			})
   244  
   245  			It("Should determine the correct duration", func() {
   246  				t := time.Now()
   247  
   248  				s.StartPublish()
   249  				s.publishStart = t.Add(-10 * time.Second)
   250  				s.EndPublish()
   251  
   252  				Expect(s.PublishDuration()).To(BeNumerically("~", 10*time.Second, 100*time.Millisecond))
   253  			})
   254  
   255  			It("Should support multiple publishes", func() {
   256  				t := time.Now()
   257  
   258  				s.StartPublish()
   259  				s.publishStart = t.Add(-10 * time.Second)
   260  				s.EndPublish()
   261  
   262  				t = time.Now()
   263  				s.StartPublish()
   264  				s.publishStart = t.Add(-10 * time.Second)
   265  				s.EndPublish()
   266  
   267  				Expect(s.PublishDuration()).To(BeNumerically("~", 20*time.Second, 100*time.Millisecond))
   268  			})
   269  		})
   270  
   271  		Describe("Start", func() {
   272  			It("Should start the clock if its not already started", func() {
   273  				Expect(s.start).To(BeZero())
   274  				s.Start()
   275  				t := s.start
   276  				s.Start()
   277  				Expect(s.start).To(Equal(t))
   278  			})
   279  		})
   280  
   281  		Describe("End", func() {
   282  			It("Should end the clock if its not already end", func() {
   283  				Expect(s.end).To(BeZero())
   284  				s.End()
   285  				t := s.end
   286  				s.End()
   287  				Expect(s.end).To(Equal(t))
   288  			})
   289  		})
   290  
   291  		Describe("RequestDuration", func() {
   292  			It("Should detect unfinished requests", func() {
   293  				s.Start()
   294  				_, err := s.RequestDuration()
   295  				Expect(err).To(MatchError("request is not completed"))
   296  			})
   297  
   298  			It("Should handle completed requests", func() {
   299  				s.Start()
   300  				s.start = time.Now().Add(-1 * time.Second)
   301  				s.End()
   302  				d, err := s.RequestDuration()
   303  				Expect(err).ToNot(HaveOccurred())
   304  				Expect(d).To(BeNumerically("~", time.Second, 50*time.Millisecond))
   305  			})
   306  		})
   307  	})
   308  })