github.com/cilium/cilium@v1.16.2/pkg/hubble/parser/fieldmask/fieldmask_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Hubble 3 4 //nolint:govet 5 package fieldmask 6 7 import ( 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "google.golang.org/protobuf/proto" 12 "google.golang.org/protobuf/types/known/fieldmaskpb" 13 14 flowpb "github.com/cilium/cilium/api/v1/flow" 15 ) 16 17 func TestFieldMask_invalid(t *testing.T) { 18 fm, err := New(&fieldmaskpb.FieldMask{Paths: []string{"invalid-path"}}) 19 assert.ErrorContains(t, err, "invalid fieldmask") 20 assert.False(t, fm.Active()) 21 } 22 23 func TestFieldMask_inactive(t *testing.T) { 24 fm, err := New(&fieldmaskpb.FieldMask{Paths: []string{}}) 25 assert.NoError(t, err) 26 assert.False(t, fm.Active()) 27 } 28 29 func TestFieldMask_normalized_parent(t *testing.T) { 30 fm, err := New(&fieldmaskpb.FieldMask{Paths: []string{"source", "source.identity", "source", "source.pod_name"}}) 31 assert.NoError(t, err) 32 assert.Len(t, fm, 1) 33 assert.Len(t, fm["source"], 0) 34 assert.True(t, fm.Active()) 35 } 36 37 func TestFieldMask_normalized_child(t *testing.T) { 38 fm, err := New(&fieldmaskpb.FieldMask{Paths: []string{"source.identity", "source.identity", "source.pod_name"}}) 39 assert.NoError(t, err) 40 assert.Len(t, fm, 1) 41 assert.Len(t, fm["source"], 2) 42 assert.True(t, fm.Active()) 43 } 44 45 func TestFieldMask_copy_with_alloc(t *testing.T) { 46 fm, err := New(&fieldmaskpb.FieldMask{Paths: []string{"source.identity", "source.pod_name", "destination"}}) 47 assert.NoError(t, err) 48 assert.True(t, fm.Active()) 49 50 flow := &flowpb.Flow{} 51 fm.Alloc(flow.ProtoReflect()) 52 53 srcA := &flowpb.Flow{ 54 NodeName: "srcA", 55 Source: &flowpb.Endpoint{ID: 1234, PodName: "podA", Namespace: "nsA"}, 56 Destination: &flowpb.Endpoint{ID: 5678, PodName: "podB", Namespace: "nsB", Identity: 9123}, 57 } 58 srcACopy := proto.Clone(srcA).(*flowpb.Flow) 59 60 fm.Copy(flow.ProtoReflect(), srcA.ProtoReflect()) 61 // Confirm that source flow wasn't modified 62 assert.True(t, assert.EqualExportedValues(t, srcACopy, srcA), 63 "expected exported flow fields to be equal") 64 65 assert.True(t, assert.EqualExportedValues(t, &flowpb.Flow{ 66 Source: &flowpb.Endpoint{PodName: "podA"}, 67 Destination: &flowpb.Endpoint{ID: 5678, PodName: "podB", Namespace: "nsB", Identity: 9123}, 68 }, flow), "expected exported flow fields to be equal") 69 70 // Set a new field and confirm that previous values were cleared. 71 srcB := &flowpb.Flow{ 72 NodeName: "srcB", 73 Source: &flowpb.Endpoint{Identity: 1234}, 74 Destination: &flowpb.Endpoint{Namespace: "nsA", Identity: 0234}, 75 } 76 fm.Copy(flow.ProtoReflect(), srcB.ProtoReflect()) 77 assert.True(t, assert.EqualExportedValues(t, &flowpb.Flow{ 78 Source: &flowpb.Endpoint{Identity: 1234}, 79 Destination: &flowpb.Endpoint{Namespace: "nsA", Identity: 0234}, 80 }, flow), "expected exported flow fields to be equal") 81 } 82 83 func TestFieldMask_copy_without_alloc(t *testing.T) { 84 fm, err := New(&fieldmaskpb.FieldMask{Paths: []string{"source.identity", "source.pod_name", "destination"}}) 85 assert.NoError(t, err) 86 assert.True(t, fm.Active()) 87 88 flow := &flowpb.Flow{} 89 90 srcA := &flowpb.Flow{ 91 NodeName: "srcA", 92 Source: &flowpb.Endpoint{ID: 1234, PodName: "podA", Namespace: "nsA"}, 93 Destination: &flowpb.Endpoint{ID: 5678, PodName: "podB", Namespace: "nsB", Identity: 9123}, 94 } 95 96 // Allocate field when not pre-allocated 97 assert.NotPanics(t, func() { fm.Copy(flow.ProtoReflect(), srcA.ProtoReflect()) }) 98 assert.True(t, assert.EqualExportedValues(t, &flowpb.Flow{ 99 Source: &flowpb.Endpoint{PodName: "podA"}, 100 Destination: &flowpb.Endpoint{ID: 5678, PodName: "podB", Namespace: "nsB", Identity: 9123}, 101 }, flow), "expected exported flow fields to be equal") 102 }