github.com/cilium/cilium@v1.16.2/pkg/hubble/relay/server/health_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package server
     5  
     6  import (
     7  	"context"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	healthpb "google.golang.org/grpc/health/grpc_health_v1"
    13  
    14  	v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
    15  	"github.com/cilium/cilium/pkg/hubble/relay/pool"
    16  	"github.com/cilium/cilium/pkg/lock"
    17  )
    18  
    19  func TestHealthServer(t *testing.T) {
    20  
    21  	fpr := &fakePeerStatusReporter{}
    22  	hs := newHealthServer(fpr, 10*time.Millisecond)
    23  
    24  	hs.start()
    25  	t.Run("initially unavailable", func(t *testing.T) {
    26  		eventuallServingStatus(t, hs.svc, healthpb.HealthCheckResponse_NOT_SERVING)
    27  	})
    28  	t.Run("updated available", func(t *testing.T) {
    29  		fpr.setStatus(pool.Status{
    30  			PeerServiceConnected: true,
    31  			AvailablePeers:       3,
    32  		})
    33  		eventuallServingStatus(t, hs.svc, healthpb.HealthCheckResponse_SERVING)
    34  	})
    35  	t.Run("updated if no available peers", func(t *testing.T) {
    36  		fpr.setStatus(pool.Status{
    37  			PeerServiceConnected: true,
    38  			AvailablePeers:       0,
    39  		})
    40  		eventuallServingStatus(t, hs.svc, healthpb.HealthCheckResponse_NOT_SERVING)
    41  	})
    42  	t.Run("updated if peers back", func(t *testing.T) {
    43  		fpr.setStatus(pool.Status{
    44  			PeerServiceConnected: true,
    45  			AvailablePeers:       6,
    46  		})
    47  		eventuallServingStatus(t, hs.svc, healthpb.HealthCheckResponse_SERVING)
    48  	})
    49  	t.Run("updated if peer service unavailable", func(t *testing.T) {
    50  		fpr.setStatus(pool.Status{
    51  			PeerServiceConnected: false,
    52  			AvailablePeers:       6,
    53  		})
    54  		eventuallServingStatus(t, hs.svc, healthpb.HealthCheckResponse_NOT_SERVING)
    55  	})
    56  	hs.stop()
    57  }
    58  
    59  func eventuallServingStatus(t *testing.T, svc healthpb.HealthServer, status healthpb.HealthCheckResponse_ServingStatus) {
    60  	t.Helper()
    61  	assert.EventuallyWithT(t, func(c *assert.CollectT) {
    62  		res, err := svc.Check(context.TODO(), &healthpb.HealthCheckRequest{
    63  			Service: "",
    64  		})
    65  		assert.NoError(c, err)
    66  		assert.Equal(c, status, res.Status)
    67  
    68  		res, err = svc.Check(context.TODO(), &healthpb.HealthCheckRequest{
    69  			Service: v1.ObserverServiceName,
    70  		})
    71  		assert.NoError(c, err)
    72  		assert.Equal(c, status, res.Status)
    73  	}, 5*time.Second, 10*time.Millisecond)
    74  }
    75  
    76  type fakePeerStatusReporter struct {
    77  	mu lock.Mutex
    78  
    79  	status pool.Status
    80  }
    81  
    82  func (f *fakePeerStatusReporter) setStatus(stat pool.Status) {
    83  	f.mu.Lock()
    84  	defer f.mu.Unlock()
    85  	f.status = stat
    86  }
    87  
    88  // Status implements peerStatusReporter.
    89  func (f *fakePeerStatusReporter) Status() pool.Status {
    90  	f.mu.Lock()
    91  	defer f.mu.Unlock()
    92  	return f.status
    93  }