github.com/cilium/cilium@v1.16.2/pkg/hubble/metrics/tcp/handler_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Hubble
     3  
     4  package tcp
     5  
     6  import (
     7  	"context"
     8  	"testing"
     9  
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	pb "github.com/cilium/cilium/api/v1/flow"
    15  	"github.com/cilium/cilium/pkg/hubble/metrics/api"
    16  	monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
    17  )
    18  
    19  func TestTcpHandler_Init(t *testing.T) {
    20  	registry := prometheus.NewRegistry()
    21  	opts := api.Options{"sourceContext": "namespace", "destinationContext": "namespace"}
    22  
    23  	tcpHandler := &tcpHandler{}
    24  
    25  	t.Run("Init", func(t *testing.T) {
    26  		require.NoError(t, tcpHandler.Init(registry, opts))
    27  	})
    28  
    29  	t.Run("Status", func(t *testing.T) {
    30  		require.Equal(t, "destination=namespace,source=namespace", tcpHandler.Status())
    31  	})
    32  }
    33  
    34  func TestTcpHandler(t *testing.T) {
    35  
    36  	var supportedFlags = []struct {
    37  		name          string
    38  		flags         *pb.TCPFlags
    39  		expectedLabel string
    40  	}{
    41  		{"SYN", &pb.TCPFlags{SYN: true}, "SYN"},
    42  		{"SYN_ACK", &pb.TCPFlags{SYN: true, ACK: true}, "SYN-ACK"},
    43  		{"FIN", &pb.TCPFlags{FIN: true}, "FIN"},
    44  		{"FIN_ACK", &pb.TCPFlags{FIN: true, ACK: true}, "FIN"},
    45  		{"RST", &pb.TCPFlags{RST: true}, "RST"},
    46  	}
    47  
    48  	for _, tc := range supportedFlags {
    49  		registry := prometheus.NewRegistry()
    50  		opts := api.Options{"sourceContext": "namespace", "destinationContext": "namespace"}
    51  
    52  		tcpHandler := &tcpHandler{}
    53  		require.NoError(t, tcpHandler.Init(registry, opts))
    54  
    55  		t.Run("ProcessSupportedFlagsFlow_"+tc.name, func(t *testing.T) {
    56  			flow := buildFlow(tc.flags)
    57  			_ = tcpHandler.ProcessFlow(context.TODO(), flow)
    58  
    59  			metricFamilies, err := registry.Gather()
    60  			require.NoError(t, err)
    61  
    62  			assert.Equal(t, "hubble_tcp_flags_total", *metricFamilies[0].Name)
    63  			metric := metricFamilies[0].Metric[0]
    64  
    65  			assert.Equal(t, "destination", *metric.Label[0].Name)
    66  			assert.Equal(t, "bar", *metric.Label[0].Value)
    67  
    68  			assert.Equal(t, "family", *metric.Label[1].Name)
    69  			assert.Equal(t, "IPv4", *metric.Label[1].Value)
    70  
    71  			assert.Equal(t, "flag", *metric.Label[2].Name)
    72  			assert.Equal(t, tc.expectedLabel, *metric.Label[2].Value)
    73  
    74  			assert.Equal(t, "source", *metric.Label[3].Name)
    75  			assert.Equal(t, "foo", *metric.Label[3].Value)
    76  
    77  			assert.Equal(t, 1., *metric.Counter.Value)
    78  
    79  			//send another flow with same labels
    80  			tcpHandler.ProcessFlow(context.TODO(), flow)
    81  			metricFamilies, _ = registry.Gather()
    82  			metric = metricFamilies[0].Metric[0]
    83  			assert.Equal(t, 2., *metric.Counter.Value)
    84  		})
    85  
    86  	}
    87  
    88  	var unsupportedFlags = []struct {
    89  		name  string
    90  		flags *pb.TCPFlags
    91  	}{
    92  		{"empty", &pb.TCPFlags{}},
    93  		{"PSH", &pb.TCPFlags{PSH: true}},
    94  		{"ACK", &pb.TCPFlags{ACK: true}},
    95  		{"URG", &pb.TCPFlags{URG: true}},
    96  		{"ECE", &pb.TCPFlags{ECE: true}},
    97  		{"CWR", &pb.TCPFlags{CWR: true}},
    98  		{"NS", &pb.TCPFlags{NS: true}},
    99  	}
   100  
   101  	for _, tc := range unsupportedFlags {
   102  		registry := prometheus.NewRegistry()
   103  		opts := api.Options{"sourceContext": "namespace", "destinationContext": "namespace"}
   104  
   105  		tcpHandler := &tcpHandler{}
   106  		require.NoError(t, tcpHandler.Init(registry, opts))
   107  
   108  		t.Run("ProcessUnsupportedFlagsFlow_"+tc.name, func(t *testing.T) {
   109  			flow := buildFlow(tc.flags)
   110  			_ = tcpHandler.ProcessFlow(context.TODO(), flow)
   111  
   112  			metricFamilies, err := registry.Gather()
   113  			require.NoError(t, err)
   114  			require.Empty(t, metricFamilies)
   115  		})
   116  
   117  	}
   118  
   119  }
   120  
   121  func buildFlow(flags *pb.TCPFlags) *pb.Flow {
   122  	return &pb.Flow{
   123  		EventType: &pb.CiliumEventType{Type: monitorAPI.MessageTypePolicyVerdict},
   124  		IP: &pb.IP{
   125  			IpVersion: pb.IPVersion_IPv4,
   126  		},
   127  		L4: &pb.Layer4{
   128  			Protocol: &pb.Layer4_TCP{
   129  				TCP: &pb.TCP{
   130  					Flags: flags,
   131  				},
   132  			},
   133  		},
   134  		Source:      &pb.Endpoint{Namespace: "foo"},
   135  		Destination: &pb.Endpoint{Namespace: "bar"},
   136  		Verdict:     pb.Verdict_FORWARDED,
   137  	}
   138  }