trpc.group/trpc-go/trpc-go@v1.0.3/rpcz/spanarray_test.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  package rpcz
    15  
    16  import (
    17  	"math"
    18  	"testing"
    19  
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  func Test_newSpanArray(t *testing.T) {
    24  	t.Run("capacity equal zero", func(t *testing.T) {
    25  		require.PanicsWithValue(t, "capacity should be greater than 0", func() { newSpanArray(0) })
    26  	})
    27  	t.Run("capacity greater zero", func(t *testing.T) {
    28  		const capacity = 1
    29  		require.Equal(t, &spanArray{capacity: capacity, data: make([]*span, capacity)}, newSpanArray(capacity))
    30  	})
    31  }
    32  
    33  func Test_spanArray_dequeue(t *testing.T) {
    34  	t.Run("dequeue empty span array", func(t *testing.T) {
    35  		sa := newSpanArray(10)
    36  		sa.dequeue()
    37  		require.Equal(t, uint32(math.MaxUint32), sa.length)
    38  		require.Equal(t, uint32(1), sa.head)
    39  	})
    40  	t.Run("#num dequeue more than length of span array", func(t *testing.T) {
    41  		sa := newSpanArray(10)
    42  		sa.enqueue(&span{})
    43  		sa.dequeue()
    44  		sa.dequeue()
    45  		require.Equal(t, uint32(math.MaxUint32), sa.length)
    46  		require.Equal(t, uint32(2), sa.head)
    47  	})
    48  	t.Run("#num dequeue equal #num enqueue", func(t *testing.T) {
    49  		const capacity = 10
    50  		sa := newSpanArray(capacity)
    51  		for i := 0; i < capacity; i++ {
    52  			sa.enqueue(&span{id: SpanID(i)})
    53  		}
    54  		for i := 0; i < capacity; i++ {
    55  			require.Equal(t, &span{id: SpanID(i)}, sa.front())
    56  			sa.dequeue()
    57  		}
    58  		require.Equal(t, sa.head, sa.tail)
    59  		require.Equal(t, uint32(0), sa.length)
    60  	})
    61  	t.Run("dequeue and enqueue in pairs", func(t *testing.T) {
    62  		const capacity = 10
    63  		sa := newSpanArray(capacity)
    64  		for i := 0; i < capacity; i++ {
    65  			sa.enqueue(&span{id: SpanID(i)})
    66  			require.Equal(t, &span{id: SpanID(i)}, sa.front())
    67  			sa.dequeue()
    68  		}
    69  		require.Equal(t, sa.head, sa.tail)
    70  		require.Equal(t, uint32(0), sa.length)
    71  	})
    72  }
    73  
    74  func Test_spanArray_doBackward(t *testing.T) {
    75  	const (
    76  		capacity = 10
    77  		num      = 5
    78  	)
    79  
    80  	sa := newSpanArray(capacity)
    81  	for i := 0; i < capacity; i++ {
    82  		sa.enqueue(&span{id: SpanID(i)})
    83  	}
    84  
    85  	var got []*span
    86  	count := num
    87  	sa.doBackward(func(s *span) bool {
    88  		if count <= 0 {
    89  			return false
    90  		}
    91  		count--
    92  		got = append(got, s)
    93  		return true
    94  	})
    95  
    96  	var want []*span
    97  	for i := capacity - 1; i >= num; i-- {
    98  		want = append(want, &span{id: SpanID(i)})
    99  	}
   100  
   101  	require.Equal(t, want, got)
   102  }
   103  
   104  func Test_spanArray_enqueue(t *testing.T) {
   105  	t.Run("len less than capacity", func(t *testing.T) {
   106  		a := &spanArray{
   107  			length:   1,
   108  			capacity: 10,
   109  			data:     make([]*span, 10),
   110  			head:     0,
   111  			tail:     1,
   112  		}
   113  		want := *a
   114  		want.length++
   115  		want.tail++
   116  
   117  		a.enqueue(&span{})
   118  		require.Equal(t, &want, a)
   119  	})
   120  	t.Run("tail equals capacity-1", func(t *testing.T) {
   121  		a := &spanArray{
   122  			length:   9,
   123  			capacity: 10,
   124  			data:     make([]*span, 10),
   125  			head:     0,
   126  			tail:     9,
   127  		}
   128  		want := *a
   129  		want.length++
   130  		want.tail = 0
   131  
   132  		a.enqueue(&span{})
   133  		require.Equal(t, &want, a)
   134  	})
   135  	t.Run("len equals capacity", func(t *testing.T) {
   136  		a := &spanArray{
   137  			length:   10,
   138  			capacity: 10,
   139  			data:     make([]*span, 10),
   140  			head:     0,
   141  			tail:     0,
   142  		}
   143  		want := *a
   144  		want.tail = 1
   145  		want.head = 1
   146  
   147  		a.enqueue(&span{})
   148  		require.Equal(t, &want, a)
   149  	})
   150  	t.Run("array is full", func(t *testing.T) {
   151  		a := newSpanArray(10)
   152  		for i := 0; i < 1000; i++ {
   153  			a.enqueue(&span{})
   154  			if i >= 10 {
   155  				require.Equal(t, uint32(10), a.length)
   156  				require.True(t, a.tail == a.head)
   157  			}
   158  		}
   159  	})
   160  }
   161  
   162  func Test_spanArray_full(t *testing.T) {
   163  	type fields struct {
   164  		capacity uint32
   165  		length   uint32
   166  		data     []*span
   167  		front    uint32
   168  		rear     uint32
   169  	}
   170  	tests := []struct {
   171  		name   string
   172  		fields fields
   173  		want   bool
   174  	}{
   175  		{
   176  			name: "length equals capacity",
   177  			fields: fields{
   178  				capacity: 10,
   179  				length:   10,
   180  				data:     make([]*span, 10),
   181  				front:    0,
   182  				rear:     0,
   183  			},
   184  			want: true,
   185  		},
   186  		{
   187  			name: "length greater than capacity",
   188  			fields: fields{
   189  				capacity: 10,
   190  				length:   11,
   191  				// other fields is invalid, this case shouldn't happen.
   192  			},
   193  			want: true,
   194  		},
   195  		{
   196  			name: "length less than capacity",
   197  			fields: fields{
   198  				capacity: 10,
   199  				length:   9,
   200  				data:     make([]*span, 10),
   201  				front:    0,
   202  				rear:     9,
   203  			},
   204  			want: false,
   205  		},
   206  	}
   207  	for _, tt := range tests {
   208  		t.Run(tt.name, func(t *testing.T) {
   209  			a := &spanArray{
   210  				capacity: tt.fields.capacity,
   211  				length:   tt.fields.length,
   212  				data:     tt.fields.data,
   213  				head:     tt.fields.front,
   214  				tail:     tt.fields.rear,
   215  			}
   216  			if got := a.full(); got != tt.want {
   217  				t.Errorf("full() = %v, want %v", got, tt.want)
   218  			}
   219  		})
   220  	}
   221  }
   222  
   223  func Test_spanArray_nextIndex(t *testing.T) {
   224  	type fields struct {
   225  		capacity uint32
   226  		length   uint32
   227  		data     []*span
   228  		front    uint32
   229  		rear     uint32
   230  	}
   231  	type args struct {
   232  		index uint32
   233  	}
   234  	tests := []struct {
   235  		name   string
   236  		fields fields
   237  		args   args
   238  		want   uint32
   239  	}{
   240  		{
   241  			name:   "index less than spanArray.capacity-1, and no less than zero",
   242  			fields: fields{capacity: 10, length: 0, front: 0, rear: 0},
   243  			args:   args{index: 0},
   244  			want:   1,
   245  		},
   246  		{
   247  			name:   "index equals spanArray.capacity-1",
   248  			fields: fields{capacity: 10, length: 0, front: 0, rear: 0},
   249  			args:   args{index: 9},
   250  			want:   0,
   251  		},
   252  		{
   253  			name:   "index greater than spanArray.capacity-1",
   254  			fields: fields{capacity: 10, length: 0, front: 0, rear: 0},
   255  			args:   args{index: 11},
   256  			want:   2,
   257  		},
   258  	}
   259  	for _, tt := range tests {
   260  		t.Run(tt.name, func(t *testing.T) {
   261  			a := &spanArray{
   262  				capacity: tt.fields.capacity,
   263  				length:   tt.fields.length,
   264  				data:     tt.fields.data,
   265  				head:     tt.fields.front,
   266  				tail:     tt.fields.rear,
   267  			}
   268  			if got := a.nextIndex(tt.args.index); got != tt.want {
   269  				t.Errorf("nextIndex() = %v, want %v", got, tt.want)
   270  			}
   271  		})
   272  	}
   273  	t.Run("input and output in valid range", func(t *testing.T) {
   274  		const capacity = 10
   275  		sa := newSpanArray(capacity)
   276  		var (
   277  			got  []uint32
   278  			want []uint32
   279  		)
   280  		for i := uint32(0); i < capacity; i++ {
   281  			want = append(want, i)
   282  			got = append(got, sa.nextIndex(i))
   283  		}
   284  		require.ElementsMatch(t, want, got)
   285  	})
   286  }
   287  
   288  func Test_spanArray_previousIndex(t *testing.T) {
   289  	type fields struct {
   290  		capacity uint32
   291  		length   uint32
   292  		data     []*span
   293  		front    uint32
   294  		rear     uint32
   295  	}
   296  	type args struct {
   297  		index uint32
   298  	}
   299  	tests := []struct {
   300  		name   string
   301  		fields fields
   302  		args   args
   303  		want   uint32
   304  	}{
   305  		{
   306  			name:   "index greater than zero  and no less than  capacity",
   307  			fields: fields{capacity: 10, length: 0, front: 0, rear: 0},
   308  			args:   args{index: 10},
   309  			want:   9,
   310  		},
   311  		{
   312  			name:   "index greater than zero  and less than capacity",
   313  			fields: fields{capacity: 10, length: 0, front: 0, rear: 0},
   314  			args:   args{index: 1},
   315  			want:   0,
   316  		},
   317  		{
   318  			name:   "index equals zero",
   319  			fields: fields{capacity: 10, length: 0, front: 0, rear: 0},
   320  			args:   args{index: 0},
   321  			want:   9,
   322  		},
   323  	}
   324  	for _, tt := range tests {
   325  		t.Run(tt.name, func(t *testing.T) {
   326  			a := &spanArray{
   327  				capacity: tt.fields.capacity,
   328  				length:   tt.fields.length,
   329  				data:     tt.fields.data,
   330  				head:     tt.fields.front,
   331  				tail:     tt.fields.rear,
   332  			}
   333  			if got := a.previousIndex(tt.args.index); got != tt.want {
   334  				t.Errorf("previousIndex() = %v, want %v", got, tt.want)
   335  			}
   336  		})
   337  	}
   338  	t.Run("input and output in valid range", func(t *testing.T) {
   339  		const capacity = 10
   340  		sa := newSpanArray(capacity)
   341  		var (
   342  			got  []uint32
   343  			want []uint32
   344  		)
   345  		for i := uint32(0); i < capacity; i++ {
   346  			want = append(want, i)
   347  			got = append(got, sa.previousIndex(i))
   348  		}
   349  		require.ElementsMatch(t, want, got)
   350  	})
   351  }
   352  
   353  func Test_spanArray_front(t *testing.T) {
   354  	a := newSpanArray(2)
   355  	a.enqueue(&span{id: 1})
   356  	s := a.front()
   357  	require.Equal(t, SpanID(1), s.id)
   358  
   359  	a.dequeue()
   360  	require.Empty(t, a.length)
   361  	require.Equal(t, SpanID(1), s.id)
   362  
   363  	a.enqueue(&span{id: 2})
   364  	a.enqueue(&span{id: 3})
   365  	a.enqueue(&span{id: 4})
   366  	require.Equal(t, SpanID(1), s.id)
   367  }