go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/collections/queue_test.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package collections 9 10 import ( 11 "testing" 12 13 . "go.charczuk.com/sdk/assert" 14 ) 15 16 func okValue[K any](v K, _ bool) K { 17 return v 18 } 19 20 func ok[K any](_ K, ok bool) bool { 21 return ok 22 } 23 24 func Test_Queue(t *testing.T) { 25 buffer := new(Queue[int]) 26 27 buffer.Push(1) 28 ItsEqual(t, 1, buffer.array[0], "the 0 index should hold the head value of 1") 29 ItsEqual(t, 1, buffer.Len()) 30 ItsEqual(t, 1, okValue(buffer.Peek())) 31 ItsEqual(t, 1, okValue(buffer.PeekBack())) 32 33 buffer.Push(2) 34 ItsEqual(t, 2, buffer.Len()) 35 ItsEqual(t, 1, okValue(buffer.Peek())) 36 ItsEqual(t, 2, okValue(buffer.PeekBack())) 37 38 buffer.Push(3) 39 ItsEqual(t, 3, buffer.Len()) 40 ItsEqual(t, 1, okValue(buffer.Peek())) 41 ItsEqual(t, 3, okValue(buffer.PeekBack())) 42 43 buffer.Push(4) 44 ItsEqual(t, 4, buffer.Len()) 45 ItsEqual(t, 1, okValue(buffer.Peek())) 46 ItsEqual(t, 4, okValue(buffer.PeekBack())) 47 48 buffer.Push(5) 49 ItsEqual(t, 5, buffer.Len()) 50 ItsEqual(t, 1, okValue(buffer.Peek())) 51 ItsEqual(t, 5, okValue(buffer.PeekBack())) 52 53 buffer.Push(6) 54 ItsEqual(t, 6, buffer.Len()) 55 ItsEqual(t, 1, okValue(buffer.Peek())) 56 ItsEqual(t, 6, okValue(buffer.PeekBack())) 57 58 buffer.Push(7) 59 ItsEqual(t, 7, buffer.Len()) 60 ItsEqual(t, 1, okValue(buffer.Peek())) 61 ItsEqual(t, 7, okValue(buffer.PeekBack())) 62 63 buffer.Push(8) 64 ItsEqual(t, 8, buffer.Len()) 65 ItsEqual(t, 1, okValue(buffer.Peek())) 66 ItsEqual(t, 8, okValue(buffer.PeekBack())) 67 68 value, ok := buffer.Pop() 69 ItsEqual(t, 0, buffer.array[0], "we should zero elements that we pop") 70 ItsEqual(t, true, ok) 71 ItsEqual(t, 1, value) 72 ItsEqual(t, 7, buffer.Len()) 73 ItsEqual(t, 2, okValue(buffer.Peek())) 74 ItsEqual(t, 8, okValue(buffer.PeekBack())) 75 76 value, ok = buffer.Pop() 77 ItsEqual(t, true, ok) 78 ItsEqual(t, 2, value) 79 ItsEqual(t, 6, buffer.Len()) 80 ItsEqual(t, 3, okValue(buffer.Peek())) 81 ItsEqual(t, 8, okValue(buffer.PeekBack())) 82 83 value, ok = buffer.Pop() 84 ItsEqual(t, true, ok) 85 ItsEqual(t, 3, value) 86 ItsEqual(t, 5, buffer.Len()) 87 ItsEqual(t, 4, okValue(buffer.Peek())) 88 ItsEqual(t, 8, okValue(buffer.PeekBack())) 89 90 value, ok = buffer.Pop() 91 ItsEqual(t, true, ok) 92 ItsEqual(t, 4, value) 93 ItsEqual(t, 4, buffer.Len()) 94 ItsEqual(t, 5, okValue(buffer.Peek())) 95 ItsEqual(t, 8, okValue(buffer.PeekBack())) 96 97 value, ok = buffer.Pop() 98 ItsEqual(t, true, ok) 99 ItsEqual(t, 5, value) 100 ItsEqual(t, 3, buffer.Len()) 101 ItsEqual(t, 6, okValue(buffer.Peek())) 102 ItsEqual(t, 8, okValue(buffer.PeekBack())) 103 104 value, ok = buffer.Pop() 105 ItsEqual(t, true, ok) 106 ItsEqual(t, 6, value) 107 ItsEqual(t, 2, buffer.Len()) 108 ItsEqual(t, 7, okValue(buffer.Peek())) 109 ItsEqual(t, 8, okValue(buffer.PeekBack())) 110 111 value, ok = buffer.Pop() 112 ItsEqual(t, true, ok) 113 ItsEqual(t, 7, value) 114 ItsEqual(t, 1, buffer.Len()) 115 ItsEqual(t, 8, okValue(buffer.Peek())) 116 ItsEqual(t, 8, okValue(buffer.PeekBack())) 117 118 value, ok = buffer.Pop() 119 ItsEqual(t, true, ok) 120 ItsEqual(t, 8, value) 121 ItsEqual(t, 0, buffer.Len()) 122 ItsEqual(t, 0, okValue(buffer.Peek())) 123 ItsEqual(t, 0, okValue(buffer.PeekBack())) 124 } 125 126 func Test_Queue_Push(t *testing.T) { 127 q := new(Queue[int]) 128 129 ItsEqual(t, 0, len(q.array)) 130 ItsEqual(t, 0, q.Len()) 131 132 q.Push(314) 133 134 ItsEqual(t, true, ok(q.Peek())) 135 ItsEqual(t, 314, okValue(q.Peek())) 136 ItsEqual(t, true, ok(q.PeekBack())) 137 ItsEqual(t, 314, okValue(q.PeekBack())) 138 139 ItsEqual(t, 0, q.head) 140 ItsEqual(t, 1, q.tail) 141 ItsEqual(t, 1, q.size) 142 ItsEqual(t, 4, len(q.array)) 143 ItsEqual(t, 1, q.Len()) 144 145 q.Push(1) 146 q.Push(2) 147 q.Push(3) 148 149 ItsEqual(t, 0, q.head) 150 ItsEqual(t, 0, q.tail) 151 ItsEqual(t, 4, q.size) 152 ItsEqual(t, 4, len(q.array)) 153 154 ItsEqual(t, true, ok(q.Peek())) 155 ItsEqual(t, 314, okValue(q.Peek())) 156 ItsEqual(t, true, ok(q.PeekBack())) 157 ItsEqual(t, 3, okValue(q.PeekBack())) 158 159 ItsEqual(t, 0, q.head) 160 ItsEqual(t, 0, q.tail) 161 ItsEqual(t, 4, q.size) 162 ItsEqual(t, 4, len(q.array)) 163 } 164 165 func Test_Queue_Pop_afterGrow(t *testing.T) { 166 q := new(Queue[int]) 167 for x := 0; x < queueDefaultCapacity+1; x++ { 168 q.Push(x) 169 } 170 ItsEqual(t, queueDefaultCapacity+1, q.Len()) 171 172 for x := 0; x < queueDefaultCapacity+1; x++ { 173 value, ok := q.Pop() 174 ItsEqual(t, true, ok) 175 ItsEqual(t, x, value) 176 } 177 178 value, ok := q.Pop() 179 ItsEqual(t, false, ok) 180 ItsEqual(t, 0, value) 181 } 182 183 func Test_Queue_PopBack(t *testing.T) { 184 buffer := new(Queue[int]) 185 186 value, ok := buffer.PopBack() 187 ItsEqual(t, false, ok) 188 ItsEqual(t, 0, value) 189 190 buffer.Push(1) 191 buffer.Push(2) 192 buffer.Push(3) 193 194 value, ok = buffer.PopBack() 195 ItsEqual(t, true, ok) 196 ItsEqual(t, 0, buffer.array[2], "PopBack should zero the tail before returning") 197 ItsEqual(t, 3, value) 198 ItsEqual(t, 2, buffer.Len()) 199 200 value, ok = buffer.PopBack() 201 ItsEqual(t, true, ok) 202 ItsEqual(t, 2, value) 203 ItsEqual(t, 1, buffer.Len()) 204 205 value, ok = buffer.PopBack() 206 ItsEqual(t, true, ok) 207 ItsEqual(t, 1, value) 208 ItsEqual(t, 0, buffer.Len()) 209 210 value, ok = buffer.PopBack() 211 ItsEqual(t, false, ok) 212 ItsEqual(t, 0, value) 213 214 // do a popback with tail == 0 215 q := new(Queue[int]) 216 217 for x := 0; x < queueDefaultCapacity; x++ { 218 q.Push(x) 219 } 220 value, ok = q.PopBack() 221 ItsEqual(t, true, ok) 222 ItsEqual(t, queueDefaultCapacity-1, value) 223 } 224 225 func Test_Queue_Cap(t *testing.T) { 226 buffer := new(Queue[int]) 227 for x := 0; x <= queueDefaultCapacity+1; x++ { 228 buffer.Push(x) 229 } 230 231 ItsEqual(t, 8, buffer.Cap()) 232 } 233 234 func Test_Queue_Clear(t *testing.T) { 235 buffer := new(Queue[int]) 236 237 // establish situation where head < tail 238 // but there are valid elements 239 for x := 0; x < 7; x++ { 240 buffer.Push(x) 241 } 242 ItsEqual(t, 7, buffer.Len()) 243 buffer.Clear() 244 245 ItsEqual(t, 0, buffer.Len()) 246 ItsEqual(t, 0, okValue(buffer.Peek())) 247 ItsEqual(t, 0, okValue(buffer.PeekBack())) 248 249 // get into situation where head > tail 250 251 // grow the buffer to 8 cap 252 for x := 0; x < 8; x++ { 253 buffer.Push(x) 254 } 255 // remove 5 elements 256 for x := 0; x < 5; x++ { 257 _, _ = buffer.Pop() 258 } 259 // push another 4 elements 260 // causing tail to wrap around 261 for x := 0; x < 4; x++ { 262 buffer.Push(x) 263 } 264 ItsEqual(t, 7, buffer.Len()) 265 buffer.Clear() 266 267 ItsEqual(t, 0, buffer.Len()) 268 ItsEqual(t, 0, okValue(buffer.Peek())) 269 ItsEqual(t, 0, okValue(buffer.PeekBack())) 270 } 271 272 func Test_Queue_Trim(t *testing.T) { 273 buffer := new(Queue[int]) 274 275 for x := 0; x < 7; x++ { 276 buffer.Push(x) 277 } 278 ItsEqual(t, 7, buffer.Len()) 279 280 buffer.Trim(5) 281 ItsEqual(t, 5, buffer.Len()) 282 283 value, ok := buffer.PopBack() 284 ItsEqual(t, true, ok) 285 ItsEqual(t, 4, value) 286 287 value, ok = buffer.Pop() 288 ItsEqual(t, true, ok) 289 ItsEqual(t, 0, value) 290 291 ItsEqual(t, 3, buffer.Len()) 292 } 293 294 func Test_Queue_Each(t *testing.T) { 295 buffer := new(Queue[int]) 296 297 // each empty 298 var values []int 299 buffer.Each(func(v int) { 300 values = append(values, v) 301 }) 302 ItsEqual(t, nil, values) 303 buffer.Clear() 304 305 // each where head < tail 306 for x := 1; x < queueDefaultCapacity; x++ { 307 buffer.Push(x) 308 } 309 values = nil 310 buffer.Each(func(v int) { 311 values = append(values, v) 312 }) 313 ItsEqual(t, []int{1, 2, 3}, values) 314 315 buffer.Clear() 316 317 // each where head > tail 318 319 // 0, 1, 2, 3, 4, 5, 6, 7 320 // _, _, _, 3, 4, 5, 6, 7 321 // 8, 9, _, 3 322 for x := 0; x < 8; x++ { 323 buffer.Push(x) 324 } 325 for x := 0; x < 5; x++ { 326 _, _ = buffer.Pop() 327 } 328 for x := 0; x < 3; x++ { 329 buffer.Push(8 + x) 330 } 331 332 values = nil 333 buffer.Each(func(v int) { 334 values = append(values, v) 335 }) 336 ItsEqual(t, []int{5, 6, 7, 8, 9, 10}, values) 337 } 338 339 func Test_Queue_ReverseEach(t *testing.T) { 340 buffer := new(Queue[int]) 341 342 // reverseEach empty 343 var values []int 344 buffer.ReverseEach(func(v int) { 345 values = append(values, v) 346 }) 347 ItsEqual(t, nil, values) 348 buffer.Clear() 349 350 // each where head < tail 351 for x := 1; x < queueDefaultCapacity; x++ { 352 buffer.Push(x) 353 } 354 values = nil 355 buffer.ReverseEach(func(v int) { 356 values = append(values, v) 357 }) 358 ItsEqual(t, []int{3, 2, 1}, values) 359 buffer.Clear() 360 361 // 0, 1, 2, 3, 4, 5, 6, 7 362 // _, _, _, 3, 4, 5, 6, 7 363 // 8, 9, _, 3 364 for x := 0; x < 8; x++ { 365 buffer.Push(x) 366 } 367 for x := 0; x < 5; x++ { 368 _, _ = buffer.Pop() 369 } 370 for x := 0; x < 3; x++ { 371 buffer.Push(8 + x) 372 } 373 374 values = nil 375 buffer.ReverseEach(func(v int) { 376 values = append(values, v) 377 }) 378 ItsEqual(t, []int{10, 9, 8, 7, 6, 5}, values) 379 } 380 381 func Test_Queue_setCapacity_empty(t *testing.T) { 382 q := new(Queue[int]) 383 384 newCapacity := 8 385 q.setCapacity(newCapacity) 386 ItsEqual(t, 0, q.head) 387 ItsEqual(t, 0, q.tail) 388 } 389 390 func Test_Queue_setCapacity_default(t *testing.T) { 391 q := new(Queue[int]) 392 393 for x := 0; x < queueDefaultCapacity-1; x++ { 394 q.Push(x) 395 } 396 397 newCapacity := 8 398 q.setCapacity(newCapacity) 399 ItsEqual(t, 0, q.head) 400 ItsEqual(t, queueDefaultCapacity-1, q.tail) 401 ItsEqual(t, 3, q.size) 402 403 ItsEqual(t, 0, q.array[0]) 404 ItsEqual(t, 1, q.array[1]) 405 ItsEqual(t, 2, q.array[2]) 406 ItsEqual(t, 0, q.array[3]) 407 ItsEqual(t, 0, q.array[4]) 408 ItsEqual(t, 0, q.array[5]) 409 ItsEqual(t, 0, q.array[6]) 410 ItsEqual(t, 0, q.array[7]) 411 } 412 413 func Test_Queue_setCapacity_wrap(t *testing.T) { 414 q := new(Queue[int]) 415 416 for x := 0; x < queueDefaultCapacity+1; x++ { 417 q.Push(x) 418 } 419 420 newCapacity := 8 421 q.setCapacity(newCapacity) 422 ItsEqual(t, 0, q.head) 423 ItsEqual(t, 5, q.tail) 424 ItsEqual(t, 5, q.size) 425 ItsEqual(t, newCapacity, len(q.array)) 426 427 ItsEqual(t, 0, q.array[0]) 428 ItsEqual(t, 1, q.array[1]) 429 ItsEqual(t, 2, q.array[2]) 430 ItsEqual(t, 3, q.array[3]) 431 ItsEqual(t, 4, q.array[4]) 432 ItsEqual(t, 0, q.array[5]) 433 ItsEqual(t, 0, q.array[6]) 434 ItsEqual(t, 0, q.array[7]) 435 } 436 437 func Test_Queue_setCapacity_trim(t *testing.T) { 438 q := new(Queue[int]) 439 440 for x := 0; x < queueDefaultCapacity+1; x++ { 441 q.Push(x) 442 } 443 444 q.setCapacity(queueDefaultCapacity + 1) 445 ItsEqual(t, 0, q.head) 446 ItsEqual(t, 0, q.tail) 447 ItsEqual(t, 5, q.size) 448 449 ItsEqual(t, queueDefaultCapacity+1, len(q.array)) 450 ItsEqual(t, 0, q.array[0]) 451 ItsEqual(t, 1, q.array[1]) 452 ItsEqual(t, 2, q.array[2]) 453 ItsEqual(t, 3, q.array[3]) 454 ItsEqual(t, 4, q.array[4]) 455 }