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 }