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: &timestamppb.Timestamp{Seconds: 1}}
    20  	resp1 = &observerpb.GetFlowsResponse{Time: &timestamppb.Timestamp{Seconds: 1, Nanos: 1}}
    21  	resp2 = &observerpb.GetFlowsResponse{Time: &timestamppb.Timestamp{Seconds: 2}}
    22  	resp3 = &observerpb.GetFlowsResponse{Time: &timestamppb.Timestamp{Seconds: 3}}
    23  	resp4 = &observerpb.GetFlowsResponse{Time: &timestamppb.Timestamp{Seconds: 4}}
    24  	resp5 = &observerpb.GetFlowsResponse{Time: &timestamppb.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: &timestamppb.Timestamp{Seconds: 5}},
   103  				{Time: &timestamppb.Timestamp{Seconds: 1}},
   104  				{Time: &timestamppb.Timestamp{Seconds: 4}},
   105  				{Time: &timestamppb.Timestamp{Seconds: 2}},
   106  				{Time: &timestamppb.Timestamp{Seconds: 1, Nanos: 1}},
   107  				{Time: &timestamppb.Timestamp{Seconds: 3}},
   108  			},
   109  			time.Unix(3, 1).UTC(),
   110  			[]*observerpb.GetFlowsResponse{
   111  				{Time: &timestamppb.Timestamp{Seconds: 1}},
   112  				{Time: &timestamppb.Timestamp{Seconds: 1, Nanos: 1}},
   113  				{Time: &timestamppb.Timestamp{Seconds: 2}},
   114  				{Time: &timestamppb.Timestamp{Seconds: 3}},
   115  			},
   116  		}, {
   117  			"all olders",
   118  			[]*observerpb.GetFlowsResponse{
   119  				{Time: &timestamppb.Timestamp{Seconds: 2}},
   120  				{Time: &timestamppb.Timestamp{Seconds: 5}},
   121  				{Time: &timestamppb.Timestamp{Seconds: 1, Nanos: 1}},
   122  				{Time: &timestamppb.Timestamp{Seconds: 3}},
   123  				{Time: &timestamppb.Timestamp{Seconds: 4}},
   124  				{Time: &timestamppb.Timestamp{Seconds: 1}},
   125  			},
   126  			time.Unix(6, 0).UTC(),
   127  			[]*observerpb.GetFlowsResponse{
   128  				{Time: &timestamppb.Timestamp{Seconds: 1}},
   129  				{Time: &timestamppb.Timestamp{Seconds: 1, Nanos: 1}},
   130  				{Time: &timestamppb.Timestamp{Seconds: 2}},
   131  				{Time: &timestamppb.Timestamp{Seconds: 3}},
   132  				{Time: &timestamppb.Timestamp{Seconds: 4}},
   133  				{Time: &timestamppb.Timestamp{Seconds: 5}},
   134  			},
   135  		}, {
   136  			"all more recent",
   137  			[]*observerpb.GetFlowsResponse{
   138  				{Time: &timestamppb.Timestamp{Seconds: 1}},
   139  				{Time: &timestamppb.Timestamp{Seconds: 5}},
   140  				{Time: &timestamppb.Timestamp{Seconds: 2}},
   141  				{Time: &timestamppb.Timestamp{Seconds: 4}},
   142  				{Time: &timestamppb.Timestamp{Seconds: 1, Nanos: 1}},
   143  				{Time: &timestamppb.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  }