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 }