github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/queues/priorityqueue/priorityqueue_test.go (about) 1 package priorityqueue 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "math/rand" 7 "strings" 8 "testing" 9 10 "github.com/songzhibin97/go-baseutils/base/bcomparator" 11 ) 12 13 type Element struct { 14 priority int 15 name string 16 } 17 18 func (element Element) String() string { 19 return fmt.Sprintf("{%v %v}", element.priority, element.name) 20 } 21 22 // Comparator function (sort by priority value in descending order) 23 func byPriority(a, b Element) int { 24 return -bcomparator.IntComparator()(a.priority, b.priority) 25 } 26 27 func TestBinaryQueueEnqueue(t *testing.T) { 28 queue := NewWith(byPriority) 29 30 if actualValue := queue.Empty(); actualValue != true { 31 t.Errorf("Got %v expected %v", actualValue, true) 32 } 33 34 a := Element{name: "a", priority: 1} 35 c := Element{name: "c", priority: 3} 36 b := Element{name: "b", priority: 2} 37 38 queue.Enqueue(a) 39 queue.Enqueue(c) 40 queue.Enqueue(b) 41 42 it := queue.Iterator() 43 count := 0 44 for it.Next() { 45 count++ 46 index := it.Index() 47 value := it.Value() 48 switch index { 49 case 0: 50 if actualValue, expectedValue := value.name, "c"; actualValue != expectedValue { 51 t.Errorf("Got %v expected %v", actualValue, expectedValue) 52 } 53 case 1: 54 if actualValue, expectedValue := value.name, "b"; actualValue != expectedValue { 55 t.Errorf("Got %v expected %v", actualValue, expectedValue) 56 } 57 case 2: 58 if actualValue, expectedValue := value.name, "a"; actualValue != expectedValue { 59 t.Errorf("Got %v expected %v", actualValue, expectedValue) 60 } 61 default: 62 t.Errorf("Too many") 63 } 64 if actualValue, expectedValue := index, count-1; actualValue != expectedValue { 65 t.Errorf("Got %v expected %v", actualValue, expectedValue) 66 } 67 } 68 69 if actualValue := queue.Values(); actualValue[0].name != "c" || actualValue[1].name != "b" || actualValue[2].name != "a" { 70 t.Errorf("Got %v expected %v", actualValue, `[{3 c} {2 b} {1 a}]`) 71 } 72 } 73 74 func TestBinaryQueueEnqueueBulk(t *testing.T) { 75 queue := NewWith(bcomparator.IntComparator()) 76 77 queue.Enqueue(15) 78 queue.Enqueue(20) 79 queue.Enqueue(3) 80 queue.Enqueue(1) 81 queue.Enqueue(2) 82 83 if actualValue, ok := queue.Dequeue(); actualValue != 1 || !ok { 84 t.Errorf("Got %v expected %v", actualValue, 1) 85 } 86 if actualValue, ok := queue.Dequeue(); actualValue != 2 || !ok { 87 t.Errorf("Got %v expected %v", actualValue, 2) 88 } 89 if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok { 90 t.Errorf("Got %v expected %v", actualValue, 3) 91 } 92 if actualValue, ok := queue.Dequeue(); actualValue != 15 || !ok { 93 t.Errorf("Got %v expected %v", actualValue, 15) 94 } 95 if actualValue, ok := queue.Dequeue(); actualValue != 20 || !ok { 96 t.Errorf("Got %v expected %v", actualValue, 20) 97 } 98 99 queue.Clear() 100 if actualValue := queue.Empty(); !actualValue { 101 t.Errorf("Got %v expected %v", actualValue, true) 102 } 103 } 104 105 func TestBinaryQueueDequeue(t *testing.T) { 106 queue := NewWith(bcomparator.IntComparator()) 107 108 if actualValue := queue.Empty(); actualValue != true { 109 t.Errorf("Got %v expected %v", actualValue, true) 110 } 111 112 queue.Enqueue(3) 113 queue.Enqueue(2) 114 queue.Enqueue(1) 115 queue.Dequeue() // removes 1 116 117 if actualValue, ok := queue.Dequeue(); actualValue != 2 || !ok { 118 t.Errorf("Got %v expected %v", actualValue, 2) 119 } 120 if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok { 121 t.Errorf("Got %v expected %v", actualValue, 3) 122 } 123 if actualValue, ok := queue.Dequeue(); actualValue != 0 || ok { 124 t.Errorf("Got %v expected %v", actualValue, nil) 125 } 126 if actualValue := queue.Empty(); actualValue != true { 127 t.Errorf("Got %v expected %v", actualValue, true) 128 } 129 if actualValue := queue.Values(); len(actualValue) != 0 { 130 t.Errorf("Got %v expected %v", actualValue, "[]") 131 } 132 } 133 134 func TestBinaryQueueRandom(t *testing.T) { 135 queue := NewWith(bcomparator.IntComparator()) 136 137 rand.Seed(3) 138 for i := 0; i < 10000; i++ { 139 r := int(rand.Int31n(30)) 140 queue.Enqueue(r) 141 } 142 143 prev, _ := queue.Dequeue() 144 for !queue.Empty() { 145 curr, _ := queue.Dequeue() 146 if prev > curr { 147 t.Errorf("Queue property invalidated. prev: %v current: %v", prev, curr) 148 } 149 prev = curr 150 } 151 } 152 153 func TestBinaryQueueIteratorOnEmpty(t *testing.T) { 154 queue := NewWith(bcomparator.IntComparator()) 155 it := queue.Iterator() 156 for it.Next() { 157 t.Errorf("Shouldn't iterate on empty queue") 158 } 159 } 160 161 func TestBinaryQueueIteratorNext(t *testing.T) { 162 queue := NewWith(bcomparator.IntComparator()) 163 queue.Enqueue(3) 164 queue.Enqueue(2) 165 queue.Enqueue(1) 166 167 it := queue.Iterator() 168 count := 0 169 for it.Next() { 170 count++ 171 index := it.Index() 172 value := it.Value() 173 switch index { 174 case 0: 175 if actualValue, expectedValue := value, 1; actualValue != expectedValue { 176 t.Errorf("Got %v expected %v", actualValue, expectedValue) 177 } 178 case 1: 179 if actualValue, expectedValue := value, 2; actualValue != expectedValue { 180 t.Errorf("Got %v expected %v", actualValue, expectedValue) 181 } 182 case 2: 183 if actualValue, expectedValue := value, 3; actualValue != expectedValue { 184 t.Errorf("Got %v expected %v", actualValue, expectedValue) 185 } 186 default: 187 t.Errorf("Too many") 188 } 189 if actualValue, expectedValue := index, count-1; actualValue != expectedValue { 190 t.Errorf("Got %v expected %v", actualValue, expectedValue) 191 } 192 } 193 if actualValue, expectedValue := count, 3; actualValue != expectedValue { 194 t.Errorf("Got %v expected %v", actualValue, expectedValue) 195 } 196 } 197 198 func TestBinaryQueueIteratorPrev(t *testing.T) { 199 queue := NewWith(bcomparator.IntComparator()) 200 queue.Enqueue(3) 201 queue.Enqueue(2) 202 queue.Enqueue(1) 203 204 it := queue.Iterator() 205 for it.Next() { 206 } 207 count := 0 208 for it.Prev() { 209 count++ 210 index := it.Index() 211 value := it.Value() 212 switch index { 213 case 0: 214 if actualValue, expectedValue := value, 1; actualValue != expectedValue { 215 t.Errorf("Got %v expected %v", actualValue, expectedValue) 216 } 217 case 1: 218 if actualValue, expectedValue := value, 2; actualValue != expectedValue { 219 t.Errorf("Got %v expected %v", actualValue, expectedValue) 220 } 221 case 2: 222 if actualValue, expectedValue := value, 3; actualValue != expectedValue { 223 t.Errorf("Got %v expected %v", actualValue, expectedValue) 224 } 225 default: 226 t.Errorf("Too many") 227 } 228 if actualValue, expectedValue := index, 3-count; actualValue != expectedValue { 229 t.Errorf("Got %v expected %v", actualValue, expectedValue) 230 } 231 } 232 if actualValue, expectedValue := count, 3; actualValue != expectedValue { 233 t.Errorf("Got %v expected %v", actualValue, expectedValue) 234 } 235 } 236 237 func TestBinaryQueueIteratorBegin(t *testing.T) { 238 queue := NewWith(bcomparator.IntComparator()) 239 it := queue.Iterator() 240 it.Begin() 241 queue.Enqueue(2) 242 queue.Enqueue(3) 243 queue.Enqueue(1) 244 for it.Next() { 245 } 246 it.Begin() 247 it.Next() 248 if index, value := it.Index(), it.Value(); index != 0 || value != 1 { 249 t.Errorf("Got %v,%v expected %v,%v", index, value, 0, 1) 250 } 251 } 252 253 func TestBinaryQueueIteratorEnd(t *testing.T) { 254 queue := NewWith(bcomparator.IntComparator()) 255 it := queue.Iterator() 256 257 if index := it.Index(); index != -1 { 258 t.Errorf("Got %v expected %v", index, -1) 259 } 260 261 it.End() 262 if index := it.Index(); index != 0 { 263 t.Errorf("Got %v expected %v", index, 0) 264 } 265 266 queue.Enqueue(3) 267 queue.Enqueue(2) 268 queue.Enqueue(1) 269 it.End() 270 if index := it.Index(); index != queue.Size() { 271 t.Errorf("Got %v expected %v", index, queue.Size()) 272 } 273 274 it.Prev() 275 if index, value := it.Index(), it.Value(); index != queue.Size()-1 || value != 3 { 276 t.Errorf("Got %v,%v expected %v,%v", index, value, queue.Size()-1, 3) 277 } 278 } 279 280 func TestBinaryQueueIteratorFirst(t *testing.T) { 281 queue := NewWith(bcomparator.IntComparator()) 282 it := queue.Iterator() 283 if actualValue, expectedValue := it.First(), false; actualValue != expectedValue { 284 t.Errorf("Got %v expected %v", actualValue, expectedValue) 285 } 286 queue.Enqueue(3) // [3] 287 queue.Enqueue(2) // [2,3] 288 queue.Enqueue(1) // [1,3,2](2 swapped with 1, hence last) 289 if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { 290 t.Errorf("Got %v expected %v", actualValue, expectedValue) 291 } 292 if index, value := it.Index(), it.Value(); index != 0 || value != 1 { 293 t.Errorf("Got %v,%v expected %v,%v", index, value, 0, 1) 294 } 295 } 296 297 func TestBinaryQueueIteratorLast(t *testing.T) { 298 tree := NewWith(bcomparator.IntComparator()) 299 it := tree.Iterator() 300 if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue { 301 t.Errorf("Got %v expected %v", actualValue, expectedValue) 302 } 303 tree.Enqueue(2) 304 tree.Enqueue(3) 305 tree.Enqueue(1) 306 if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { 307 t.Errorf("Got %v expected %v", actualValue, expectedValue) 308 } 309 if index, value := it.Index(), it.Value(); index != 2 || value != 3 { 310 t.Errorf("Got %v,%v expected %v,%v", index, value, 2, 3) 311 } 312 } 313 314 func TestBinaryQueueIteratorNextTo(t *testing.T) { 315 // Sample seek function, i.e. string starting with "b" 316 seek := func(index int, value string) bool { 317 return strings.HasSuffix(value, "b") 318 } 319 320 // NextTo (empty) 321 { 322 tree := NewWith(bcomparator.StringComparator()) 323 it := tree.Iterator() 324 for it.NextTo(seek) { 325 t.Errorf("Shouldn't iterate on empty list") 326 } 327 } 328 329 // NextTo (not found) 330 { 331 tree := NewWith(bcomparator.StringComparator()) 332 tree.Enqueue("xx") 333 tree.Enqueue("yy") 334 it := tree.Iterator() 335 for it.NextTo(seek) { 336 t.Errorf("Shouldn't iterate on empty list") 337 } 338 } 339 340 // NextTo (found) 341 { 342 tree := NewWith(bcomparator.StringComparator()) 343 tree.Enqueue("aa") 344 tree.Enqueue("bb") 345 tree.Enqueue("cc") 346 it := tree.Iterator() 347 it.Begin() 348 if !it.NextTo(seek) { 349 t.Errorf("Shouldn't iterate on empty list") 350 } 351 if index, value := it.Index(), it.Value(); index != 1 || value != "bb" { 352 t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb") 353 } 354 if !it.Next() { 355 t.Errorf("Should go to first element") 356 } 357 if index, value := it.Index(), it.Value(); index != 2 || value != "cc" { 358 t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc") 359 } 360 if it.Next() { 361 t.Errorf("Should not go past last element") 362 } 363 } 364 } 365 366 func TestBinaryQueueIteratorPrevTo(t *testing.T) { 367 // Sample seek function, i.e. string starting with "b" 368 seek := func(index int, value string) bool { 369 return strings.HasSuffix(value, "b") 370 } 371 372 // PrevTo (empty) 373 { 374 tree := NewWith(bcomparator.StringComparator()) 375 it := tree.Iterator() 376 it.End() 377 for it.PrevTo(seek) { 378 t.Errorf("Shouldn't iterate on empty list") 379 } 380 } 381 382 // PrevTo (not found) 383 { 384 tree := NewWith(bcomparator.StringComparator()) 385 tree.Enqueue("xx") 386 tree.Enqueue("yy") 387 it := tree.Iterator() 388 it.End() 389 for it.PrevTo(seek) { 390 t.Errorf("Shouldn't iterate on empty list") 391 } 392 } 393 394 // PrevTo (found) 395 { 396 tree := NewWith(bcomparator.StringComparator()) 397 tree.Enqueue("aa") 398 tree.Enqueue("bb") 399 tree.Enqueue("cc") 400 it := tree.Iterator() 401 it.End() 402 if !it.PrevTo(seek) { 403 t.Errorf("Shouldn't iterate on empty list") 404 } 405 if index, value := it.Index(), it.Value(); index != 1 || value != "bb" { 406 t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb") 407 } 408 if !it.Prev() { 409 t.Errorf("Should go to first element") 410 } 411 if index, value := it.Index(), it.Value(); index != 0 || value != "aa" { 412 t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa") 413 } 414 if it.Prev() { 415 t.Errorf("Should not go before first element") 416 } 417 } 418 } 419 420 func TestBinaryQueueSerialization(t *testing.T) { 421 queue := NewWith(bcomparator.StringComparator()) 422 423 queue.Enqueue("c") 424 queue.Enqueue("b") 425 queue.Enqueue("a") 426 427 var err error 428 assert := func() { 429 if actualValue := queue.Values(); actualValue[0] != "a" || actualValue[1] != "b" || actualValue[2] != "c" { 430 t.Errorf("Got %v expected %v", actualValue, "[1,3,2]") 431 } 432 if actualValue := queue.Size(); actualValue != 3 { 433 t.Errorf("Got %v expected %v", actualValue, 3) 434 } 435 if actualValue, ok := queue.Peek(); actualValue != "a" || !ok { 436 t.Errorf("Got %v expected %v", actualValue, "a") 437 } 438 if err != nil { 439 t.Errorf("Got error %v", err) 440 } 441 } 442 443 assert() 444 445 bytes, err := queue.MarshalJSON() 446 assert() 447 448 err = queue.UnmarshalJSON(bytes) 449 assert() 450 451 bytes, err = json.Marshal([]interface{}{"a", "b", "c", queue}) 452 if err != nil { 453 t.Errorf("Got error %v", err) 454 } 455 456 err = json.Unmarshal([]byte(`["1","2","3"]`), &queue) 457 if err != nil { 458 t.Errorf("Got error %v", err) 459 } 460 } 461 462 func TestBTreeString(t *testing.T) { 463 c := NewWith(bcomparator.IntComparator()) 464 c.Enqueue(1) 465 if !strings.HasPrefix(c.String(), "PriorityQueue") { 466 t.Errorf("String should start with container name") 467 } 468 } 469 470 func benchmarkEnqueue[E int](b *testing.B, queue *Queue[E], size int) { 471 for i := 0; i < b.N; i++ { 472 for n := 0; n < size; n++ { 473 queue.Enqueue(E(n)) 474 } 475 } 476 } 477 478 func benchmarkDequeue[E int](b *testing.B, queue *Queue[E], size int) { 479 for i := 0; i < b.N; i++ { 480 for n := 0; n < size; n++ { 481 queue.Dequeue() 482 } 483 } 484 } 485 486 func BenchmarkBinaryQueueDequeue100(b *testing.B) { 487 b.StopTimer() 488 size := 100 489 queue := NewWith(bcomparator.IntComparator()) 490 for n := 0; n < size; n++ { 491 queue.Enqueue(n) 492 } 493 b.StartTimer() 494 benchmarkDequeue(b, queue, size) 495 } 496 497 func BenchmarkBinaryQueueDequeue1000(b *testing.B) { 498 b.StopTimer() 499 size := 1000 500 queue := NewWith(bcomparator.IntComparator()) 501 for n := 0; n < size; n++ { 502 queue.Enqueue(n) 503 } 504 b.StartTimer() 505 benchmarkDequeue(b, queue, size) 506 } 507 508 func BenchmarkBinaryQueueDequeue10000(b *testing.B) { 509 b.StopTimer() 510 size := 10000 511 queue := NewWith(bcomparator.IntComparator()) 512 for n := 0; n < size; n++ { 513 queue.Enqueue(n) 514 } 515 b.StartTimer() 516 benchmarkDequeue(b, queue, size) 517 } 518 519 func BenchmarkBinaryQueueDequeue100000(b *testing.B) { 520 b.StopTimer() 521 size := 100000 522 queue := NewWith(bcomparator.IntComparator()) 523 for n := 0; n < size; n++ { 524 queue.Enqueue(n) 525 } 526 b.StartTimer() 527 benchmarkDequeue(b, queue, size) 528 } 529 530 func BenchmarkBinaryQueueEnqueue100(b *testing.B) { 531 b.StopTimer() 532 size := 100 533 queue := NewWith(bcomparator.IntComparator()) 534 b.StartTimer() 535 benchmarkEnqueue(b, queue, size) 536 } 537 538 func BenchmarkBinaryQueueEnqueue1000(b *testing.B) { 539 b.StopTimer() 540 size := 1000 541 queue := NewWith(bcomparator.IntComparator()) 542 for n := 0; n < size; n++ { 543 queue.Enqueue(n) 544 } 545 b.StartTimer() 546 benchmarkEnqueue(b, queue, size) 547 } 548 549 func BenchmarkBinaryQueueEnqueue10000(b *testing.B) { 550 b.StopTimer() 551 size := 10000 552 queue := NewWith(bcomparator.IntComparator()) 553 for n := 0; n < size; n++ { 554 queue.Enqueue(n) 555 } 556 b.StartTimer() 557 benchmarkEnqueue(b, queue, size) 558 } 559 560 func BenchmarkBinaryQueueEnqueue100000(b *testing.B) { 561 b.StopTimer() 562 size := 100000 563 queue := NewWith(bcomparator.IntComparator()) 564 for n := 0; n < size; n++ { 565 queue.Enqueue(n) 566 } 567 b.StartTimer() 568 benchmarkEnqueue(b, queue, size) 569 }