github.com/cilium/cilium@v1.16.2/pkg/hubble/relay/queue/priority_queue_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Hubble 3 4 package queue 5 6 import ( 7 "testing" 8 "time" 9 10 "github.com/google/go-cmp/cmp" 11 "github.com/google/go-cmp/cmp/cmpopts" 12 "github.com/stretchr/testify/assert" 13 "google.golang.org/protobuf/types/known/timestamppb" 14 15 observerpb "github.com/cilium/cilium/api/v1/observer" 16 ) 17 18 var ( 19 resp0 = &observerpb.GetFlowsResponse{Time: ×tamppb.Timestamp{Seconds: 1}} 20 resp1 = &observerpb.GetFlowsResponse{Time: ×tamppb.Timestamp{Seconds: 1, Nanos: 1}} 21 resp2 = &observerpb.GetFlowsResponse{Time: ×tamppb.Timestamp{Seconds: 2}} 22 resp3 = &observerpb.GetFlowsResponse{Time: ×tamppb.Timestamp{Seconds: 3}} 23 resp4 = &observerpb.GetFlowsResponse{Time: ×tamppb.Timestamp{Seconds: 4}} 24 resp5 = &observerpb.GetFlowsResponse{Time: ×tamppb.Timestamp{Seconds: 5}} 25 ) 26 27 func TestPriorityQueue(t *testing.T) { 28 pq := NewPriorityQueue(42) 29 assert.Equal(t, pq.Len(), 0) 30 31 // push some objects to the queue 32 pq.Push(resp1) 33 pq.Push(resp2) 34 35 // try poping out these 2 objects, the oldest one should pop out first 36 event := pq.Pop() 37 assert.Equal(t, event, resp1) 38 event = pq.Pop() 39 assert.Equal(t, event, resp2) 40 41 // calling pop on an empty priority queue should return nil 42 assert.Equal(t, pq.Len(), 0) 43 event = pq.Pop() 44 assert.Nil(t, event) 45 46 // let's push some objects in seemingly random order 47 pq.Push(resp5) 48 pq.Push(resp3) 49 pq.Push(resp1) 50 pq.Push(resp4) 51 pq.Push(resp2) 52 assert.Equal(t, pq.Len(), 5) 53 54 // now, when popped out, they should pop out in chronological order 55 event = pq.Pop() 56 assert.Equal(t, event, resp1) 57 event = pq.Pop() 58 assert.Equal(t, event, resp2) 59 event = pq.Pop() 60 assert.Equal(t, event, resp3) 61 event = pq.Pop() 62 assert.Equal(t, event, resp4) 63 event = pq.Pop() 64 assert.Equal(t, event, resp5) 65 assert.Equal(t, pq.Len(), 0) 66 } 67 68 func TestPriorityQueue_WithobjectsInTheSameSecond(t *testing.T) { 69 pq := NewPriorityQueue(2) 70 pq.Push(resp1) 71 pq.Push(resp0) 72 assert.Equal(t, pq.Len(), 2) 73 event := pq.Pop() 74 assert.Equal(t, event, resp0) 75 event = pq.Pop() 76 assert.Equal(t, event, resp1) 77 } 78 79 func TestPriorityQueue_WithInitialCapacity0(t *testing.T) { 80 pq := NewPriorityQueue(0) 81 assert.Equal(t, pq.Len(), 0) 82 } 83 84 func TestPriorityQueue_GrowingOverInitialCapacity(t *testing.T) { 85 pq := NewPriorityQueue(1) 86 assert.Equal(t, pq.Len(), 0) 87 pq.Push(resp1) 88 pq.Push(resp2) 89 assert.Equal(t, pq.Len(), 2) 90 } 91 92 func TestPriorityQueue_PopOlderThan(t *testing.T) { 93 tests := []struct { 94 name string 95 has []*observerpb.GetFlowsResponse 96 filter time.Time 97 want []*observerpb.GetFlowsResponse 98 }{ 99 { 100 "some older, some newer", 101 []*observerpb.GetFlowsResponse{ 102 {Time: ×tamppb.Timestamp{Seconds: 5}}, 103 {Time: ×tamppb.Timestamp{Seconds: 1}}, 104 {Time: ×tamppb.Timestamp{Seconds: 4}}, 105 {Time: ×tamppb.Timestamp{Seconds: 2}}, 106 {Time: ×tamppb.Timestamp{Seconds: 1, Nanos: 1}}, 107 {Time: ×tamppb.Timestamp{Seconds: 3}}, 108 }, 109 time.Unix(3, 1).UTC(), 110 []*observerpb.GetFlowsResponse{ 111 {Time: ×tamppb.Timestamp{Seconds: 1}}, 112 {Time: ×tamppb.Timestamp{Seconds: 1, Nanos: 1}}, 113 {Time: ×tamppb.Timestamp{Seconds: 2}}, 114 {Time: ×tamppb.Timestamp{Seconds: 3}}, 115 }, 116 }, { 117 "all olders", 118 []*observerpb.GetFlowsResponse{ 119 {Time: ×tamppb.Timestamp{Seconds: 2}}, 120 {Time: ×tamppb.Timestamp{Seconds: 5}}, 121 {Time: ×tamppb.Timestamp{Seconds: 1, Nanos: 1}}, 122 {Time: ×tamppb.Timestamp{Seconds: 3}}, 123 {Time: ×tamppb.Timestamp{Seconds: 4}}, 124 {Time: ×tamppb.Timestamp{Seconds: 1}}, 125 }, 126 time.Unix(6, 0).UTC(), 127 []*observerpb.GetFlowsResponse{ 128 {Time: ×tamppb.Timestamp{Seconds: 1}}, 129 {Time: ×tamppb.Timestamp{Seconds: 1, Nanos: 1}}, 130 {Time: ×tamppb.Timestamp{Seconds: 2}}, 131 {Time: ×tamppb.Timestamp{Seconds: 3}}, 132 {Time: ×tamppb.Timestamp{Seconds: 4}}, 133 {Time: ×tamppb.Timestamp{Seconds: 5}}, 134 }, 135 }, { 136 "all more recent", 137 []*observerpb.GetFlowsResponse{ 138 {Time: ×tamppb.Timestamp{Seconds: 1}}, 139 {Time: ×tamppb.Timestamp{Seconds: 5}}, 140 {Time: ×tamppb.Timestamp{Seconds: 2}}, 141 {Time: ×tamppb.Timestamp{Seconds: 4}}, 142 {Time: ×tamppb.Timestamp{Seconds: 1, Nanos: 1}}, 143 {Time: ×tamppb.Timestamp{Seconds: 3}}, 144 }, 145 time.Unix(0, 0).UTC(), 146 []*observerpb.GetFlowsResponse{}, 147 }, { 148 "empty queue", 149 nil, 150 time.Unix(0, 0).UTC(), 151 []*observerpb.GetFlowsResponse{}, 152 }, 153 } 154 for _, tt := range tests { 155 t.Run(tt.name, func(t *testing.T) { 156 pq := NewPriorityQueue(len(tt.has)) 157 assert.Equal(t, pq.Len(), 0) 158 for _, resp := range tt.has { 159 pq.Push(resp) 160 } 161 assert.Equal(t, pq.Len(), len(tt.has)) 162 got := pq.PopOlderThan(tt.filter) 163 if diff := cmp.Diff( 164 tt.want, 165 got, 166 cmpopts.IgnoreUnexported( 167 observerpb.GetFlowsResponse{}, 168 timestamppb.Timestamp{}, 169 ), 170 ); diff != "" { 171 t.Errorf("mismatch (-want +got):\n%s", diff) 172 } 173 }) 174 } 175 }