volcano.sh/volcano@v1.9.0/pkg/scheduler/cache/event_handlers_test.go (about) 1 /* 2 Copyright 2019 The Volcano Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cache 18 19 import ( 20 "fmt" 21 "strings" 22 "testing" 23 24 v1 "k8s.io/api/core/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/client-go/util/workqueue" 27 28 "volcano.sh/apis/pkg/apis/scheduling" 29 schedulingv1 "volcano.sh/apis/pkg/apis/scheduling/v1beta1" 30 "volcano.sh/volcano/pkg/scheduler/api" 31 ) 32 33 func TestSchedulerCache_updateTask(t *testing.T) { 34 namespace := "test" 35 owner := buildOwnerReference("j1") 36 37 tests := []struct { 38 Name string 39 OldPod *v1.Pod 40 NewPod *v1.Pod 41 Nodes []*v1.Node 42 JobInfo *api.JobInfo 43 OldTaskInfo *api.TaskInfo 44 NewTaskInfo *api.TaskInfo 45 Expected error 46 }{ 47 { 48 Name: "Success Case", 49 OldPod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 50 NewPod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "2G"), []metav1.OwnerReference{owner}, make(map[string]string)), 51 Nodes: []*v1.Node{ 52 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 53 }, 54 OldTaskInfo: &api.TaskInfo{}, 55 NewTaskInfo: &api.TaskInfo{}, 56 Expected: nil, 57 }, 58 { 59 Name: "Error Case", 60 OldPod: buildPod(namespace, "p1", "n1", v1.PodSucceeded, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 61 NewPod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "2G"), []metav1.OwnerReference{owner}, make(map[string]string)), 62 Nodes: []*v1.Node{ 63 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 64 }, 65 OldTaskInfo: &api.TaskInfo{}, 66 NewTaskInfo: &api.TaskInfo{}, 67 Expected: fmt.Errorf("failed to find task <%s/%s> on host <%s>", namespace, "p1", "n1"), 68 }, 69 } 70 71 for i, test := range tests { 72 cache := &SchedulerCache{ 73 Jobs: make(map[api.JobID]*api.JobInfo), 74 Nodes: make(map[string]*api.NodeInfo), 75 } 76 77 for _, n := range test.Nodes { 78 cache.AddOrUpdateNode(n) 79 } 80 81 cache.AddPod(test.OldPod) 82 test.OldTaskInfo = api.NewTaskInfo(test.OldPod) 83 test.NewTaskInfo = api.NewTaskInfo(test.NewPod) 84 85 new := cache.updateTask(test.OldTaskInfo, test.NewTaskInfo) 86 87 if test.Expected != nil && new != nil && !strings.Contains(new.Error(), test.Expected.Error()) { 88 t.Errorf("Expected Error to be %v but got %v in case %d", test.Expected, new, i) 89 } 90 } 91 } 92 93 func TestSchedulerCache_UpdatePod(t *testing.T) { 94 namespace := "test" 95 owner := buildOwnerReference("j1") 96 97 tests := []struct { 98 Name string 99 OldPod *v1.Pod 100 NewPod *v1.Pod 101 Nodes []*v1.Node 102 JobInfo *api.JobInfo 103 Expected error 104 }{ 105 { 106 Name: "Success Case", 107 OldPod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 108 NewPod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "2G"), []metav1.OwnerReference{owner}, make(map[string]string)), 109 Nodes: []*v1.Node{ 110 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 111 }, 112 Expected: nil, 113 }, 114 { 115 Name: "Error Case", 116 OldPod: buildPod(namespace, "p1", "n1", v1.PodSucceeded, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 117 NewPod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "2G"), []metav1.OwnerReference{owner}, make(map[string]string)), 118 Nodes: []*v1.Node{ 119 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 120 }, 121 Expected: fmt.Errorf("failed to find task <%s/%s> on host <%s>", namespace, "p1", "n1"), 122 }, 123 } 124 125 for i, test := range tests { 126 cache := &SchedulerCache{ 127 Jobs: make(map[api.JobID]*api.JobInfo), 128 Nodes: make(map[string]*api.NodeInfo), 129 } 130 131 for _, n := range test.Nodes { 132 cache.AddOrUpdateNode(n) 133 } 134 135 cache.AddPod(test.OldPod) 136 137 new := cache.updatePod(test.OldPod, test.NewPod) 138 139 if test.Expected != nil && new != nil && !strings.Contains(new.Error(), test.Expected.Error()) { 140 t.Errorf("Expected Error to be %v but got %v in case %d", test.Expected, new, i) 141 } 142 } 143 } 144 145 func TestSchedulerCache_AddPodGroupV1beta1(t *testing.T) { 146 namespace := "test" 147 owner := buildOwnerReference("j1") 148 149 tests := []struct { 150 Name string 151 Pod *v1.Pod 152 Nodes []*v1.Node 153 PodGroup interface{} 154 Expected *api.PodGroup 155 }{ 156 { 157 Name: "Success Case", 158 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 159 Nodes: []*v1.Node{ 160 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 161 }, 162 PodGroup: &schedulingv1.PodGroup{ 163 ObjectMeta: metav1.ObjectMeta{ 164 Name: "j1", 165 Namespace: namespace, 166 }, 167 }, 168 Expected: &api.PodGroup{ 169 PodGroup: scheduling.PodGroup{ 170 ObjectMeta: metav1.ObjectMeta{ 171 Name: "j1", 172 Namespace: namespace, 173 }, 174 }, 175 }, 176 }, 177 { 178 Name: "Error Case: 1 - Wrong Type", 179 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 180 Nodes: []*v1.Node{ 181 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 182 }, 183 PodGroup: &schedulingv1.PodGroup{ 184 ObjectMeta: metav1.ObjectMeta{ 185 Name: "j1", 186 Namespace: namespace, 187 }, 188 }, 189 Expected: nil, 190 }, 191 { 192 Name: "Error Case: 2 - PodGroup Without Identity", 193 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 194 Nodes: []*v1.Node{ 195 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 196 }, 197 PodGroup: &schedulingv1.PodGroup{ 198 Status: schedulingv1.PodGroupStatus{ 199 Running: int32(1), 200 }, 201 }, 202 Expected: nil, 203 }, 204 } 205 206 for i, test := range tests { 207 cache := &SchedulerCache{ 208 Jobs: make(map[api.JobID]*api.JobInfo), 209 Nodes: make(map[string]*api.NodeInfo), 210 } 211 212 for _, n := range test.Nodes { 213 cache.AddOrUpdateNode(n) 214 } 215 test.Pod.Annotations = map[string]string{ 216 "scheduling.k8s.io/group-name": "j1", 217 } 218 cache.AddPod(test.Pod) 219 220 cache.AddPodGroupV1beta1(test.PodGroup) 221 jobID := api.JobID("test/j1") 222 223 job := cache.Jobs[jobID] 224 pg := job.PodGroup 225 226 if test.Expected != nil && (pg.Namespace != test.Expected.Namespace || pg.Name != test.Expected.Name) { 227 t.Errorf("Expected pg to be: %v but got :%v in case %d", test.Expected, pg, i) 228 } 229 } 230 } 231 232 func TestSchedulerCache_UpdatePodGroupV1beta1(t *testing.T) { 233 namespace := "test" 234 owner := buildOwnerReference("j1") 235 236 tests := []struct { 237 Name string 238 Pod *v1.Pod 239 Nodes []*v1.Node 240 OldPodGroup interface{} 241 NewPodGroup interface{} 242 Expected *api.PodGroup 243 }{ 244 { 245 Name: "Success Case", 246 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 247 Nodes: []*v1.Node{ 248 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 249 }, 250 OldPodGroup: &schedulingv1.PodGroup{ 251 ObjectMeta: metav1.ObjectMeta{ 252 Name: "j1", 253 Namespace: namespace, 254 }, 255 }, 256 NewPodGroup: &schedulingv1.PodGroup{ 257 ObjectMeta: metav1.ObjectMeta{ 258 Name: "j1-updated", 259 Namespace: namespace, 260 }, 261 }, 262 Expected: &api.PodGroup{ 263 PodGroup: scheduling.PodGroup{ 264 ObjectMeta: metav1.ObjectMeta{ 265 Name: "j1-updated", 266 Namespace: namespace, 267 }, 268 }, 269 }, 270 }, 271 { 272 Name: "Error Case: 1 - Wrong Type(OldPodGroup)", 273 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 274 Nodes: []*v1.Node{ 275 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 276 }, 277 OldPodGroup: &schedulingv1.PodGroup{ 278 ObjectMeta: metav1.ObjectMeta{ 279 Name: "j1", 280 Namespace: namespace, 281 }, 282 }, 283 NewPodGroup: &schedulingv1.PodGroup{ 284 ObjectMeta: metav1.ObjectMeta{ 285 Name: "j1-updated", 286 Namespace: namespace, 287 }, 288 }, 289 Expected: nil, 290 }, 291 { 292 Name: "Error Case: 2 - PodGroup Without Identity", 293 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 294 Nodes: []*v1.Node{ 295 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 296 }, 297 NewPodGroup: &schedulingv1.PodGroup{ 298 Status: schedulingv1.PodGroupStatus{ 299 Running: int32(1), 300 }, 301 }, 302 OldPodGroup: &schedulingv1.PodGroup{ 303 ObjectMeta: metav1.ObjectMeta{ 304 Name: "j1-updated", 305 Namespace: namespace, 306 }, 307 }, 308 Expected: nil, 309 }, 310 { 311 Name: "Error Case: 3 - Wrong Type(NewPodGroup)", 312 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 313 Nodes: []*v1.Node{ 314 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 315 }, 316 OldPodGroup: &schedulingv1.PodGroup{ 317 ObjectMeta: metav1.ObjectMeta{ 318 Name: "j1", 319 Namespace: namespace, 320 }, 321 }, 322 NewPodGroup: &schedulingv1.PodGroup{ 323 ObjectMeta: metav1.ObjectMeta{ 324 Name: "j1-updated", 325 Namespace: namespace, 326 }, 327 }, 328 Expected: nil, 329 }, 330 } 331 332 for i, test := range tests { 333 cache := &SchedulerCache{ 334 Jobs: make(map[api.JobID]*api.JobInfo), 335 Nodes: make(map[string]*api.NodeInfo), 336 } 337 338 for _, n := range test.Nodes { 339 cache.AddOrUpdateNode(n) 340 } 341 test.Pod.Annotations = map[string]string{ 342 "scheduling.k8s.io/group-name": "j1", 343 } 344 cache.AddPod(test.Pod) 345 346 cache.UpdatePodGroupV1beta1(test.OldPodGroup, test.NewPodGroup) 347 jobID := api.JobID("test/j1") 348 349 job := cache.Jobs[jobID] 350 pg := job.PodGroup 351 352 if test.Expected != nil && pg != nil && (pg.Namespace != test.Expected.Namespace || pg.Name != test.Expected.Name) { 353 t.Errorf("Expected pg to be: %v but got :%v in case %d", test.Expected, pg, i) 354 } 355 } 356 } 357 358 func TestSchedulerCache_DeletePodGroupV1beta1(t *testing.T) { 359 namespace := "test" 360 owner := buildOwnerReference("j1") 361 362 tests := []struct { 363 Name string 364 Pod *v1.Pod 365 Nodes []*v1.Node 366 PodGroup interface{} 367 Expected *api.PodGroup 368 }{ 369 { 370 Name: "Success Case", 371 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 372 Nodes: []*v1.Node{ 373 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 374 }, 375 PodGroup: &schedulingv1.PodGroup{ 376 ObjectMeta: metav1.ObjectMeta{ 377 Name: "j1", 378 Namespace: namespace, 379 }, 380 }, 381 Expected: nil, 382 }, 383 { 384 Name: "Error Case: 1 - Wrong Type", 385 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 386 Nodes: []*v1.Node{ 387 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 388 }, 389 PodGroup: &schedulingv1.PodGroup{ 390 ObjectMeta: metav1.ObjectMeta{ 391 Name: "j1", 392 Namespace: namespace, 393 }, 394 }, 395 Expected: &api.PodGroup{ 396 PodGroup: scheduling.PodGroup{ 397 ObjectMeta: metav1.ObjectMeta{ 398 Name: "j1", 399 Namespace: namespace, 400 }, 401 }, 402 }, 403 }, 404 { 405 Name: "Error Case: 2 - PodGroup Without Identity", 406 Pod: buildPod(namespace, "p1", "n1", v1.PodRunning, api.BuildResourceList("1000m", "1G"), []metav1.OwnerReference{owner}, make(map[string]string)), 407 Nodes: []*v1.Node{ 408 buildNode("n1", api.BuildResourceList("2000m", "10G", []api.ScalarResource{{Name: "pods", Value: "10"}}...)), 409 }, 410 PodGroup: &schedulingv1.PodGroup{ 411 Status: schedulingv1.PodGroupStatus{ 412 Running: int32(1), 413 }, 414 }, 415 Expected: &api.PodGroup{ 416 PodGroup: scheduling.PodGroup{ 417 Status: scheduling.PodGroupStatus{ 418 Running: int32(1), 419 }, 420 }, 421 }, 422 }, 423 } 424 425 for i, test := range tests { 426 cache := &SchedulerCache{ 427 Jobs: make(map[api.JobID]*api.JobInfo), 428 Nodes: make(map[string]*api.NodeInfo), 429 } 430 431 cache.DeletedJobs = workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) 432 433 for _, n := range test.Nodes { 434 cache.AddOrUpdateNode(n) 435 } 436 test.Pod.Annotations = map[string]string{ 437 "scheduling.k8s.io/group-name": "j1", 438 } 439 cache.AddPod(test.Pod) 440 441 cache.AddPodGroupV1beta1(test.PodGroup) 442 443 cache.DeletePodGroupV1beta1(test.PodGroup) 444 jobID := api.JobID("test/j1") 445 446 job := cache.Jobs[jobID] 447 448 if test.Expected == nil && job.PodGroup != nil { 449 t.Errorf("Expected job to be: %v but got :%v in case %d", test.Expected, job, i) 450 } 451 } 452 } 453 454 func TestSchedulerCache_AddQueueV1beta1(t *testing.T) { 455 namespace := "test" 456 457 tests := []struct { 458 Name string 459 Queue interface{} 460 Expected *scheduling.Queue 461 }{ 462 { 463 Name: "Success Case", 464 Queue: &schedulingv1.Queue{ 465 ObjectMeta: metav1.ObjectMeta{ 466 Name: "q1", 467 Namespace: namespace, 468 }, 469 }, 470 Expected: &scheduling.Queue{ 471 ObjectMeta: metav1.ObjectMeta{ 472 Name: "q1", 473 Namespace: namespace, 474 }, 475 }, 476 }, 477 { 478 Name: "Error Case: 1 - Wrong Type", 479 Queue: &schedulingv1.Queue{ 480 ObjectMeta: metav1.ObjectMeta{ 481 Name: "q1", 482 Namespace: namespace, 483 }, 484 }, 485 Expected: nil, 486 }, 487 } 488 489 for i, test := range tests { 490 cache := &SchedulerCache{ 491 Jobs: make(map[api.JobID]*api.JobInfo), 492 Nodes: make(map[string]*api.NodeInfo), 493 Queues: make(map[api.QueueID]*api.QueueInfo)} 494 495 cache.AddQueueV1beta1(test.Queue) 496 497 queue := cache.Queues["q1"] 498 499 if test.Expected != nil && queue != nil && queue.Queue != nil && (queue.Queue.Namespace != test.Expected.Namespace || queue.Queue.Name != test.Expected.Name) { 500 t.Errorf("Expected: %v but got: %v in case %d", test.Expected, queue.Queue, i) 501 } 502 } 503 } 504 505 func TestSchedulerCache_UpdateQueueV1beta1(t *testing.T) { 506 namespace := "test" 507 508 tests := []struct { 509 Name string 510 OldQueue interface{} 511 NewQueue interface{} 512 Expected *scheduling.Queue 513 }{ 514 { 515 Name: "Success Case", 516 OldQueue: &schedulingv1.Queue{ 517 ObjectMeta: metav1.ObjectMeta{ 518 Name: "q1", 519 Namespace: namespace, 520 }, 521 }, 522 NewQueue: &schedulingv1.Queue{ 523 ObjectMeta: metav1.ObjectMeta{ 524 Name: "q1-updated", 525 Namespace: namespace, 526 }, 527 }, 528 Expected: &scheduling.Queue{ 529 ObjectMeta: metav1.ObjectMeta{ 530 Name: "q1-updated", 531 Namespace: namespace, 532 }, 533 }, 534 }, 535 { 536 Name: "Error Case: 1 - Wrong Type(OldQueue)", 537 OldQueue: &schedulingv1.Queue{ 538 ObjectMeta: metav1.ObjectMeta{ 539 Name: "q1", 540 Namespace: namespace, 541 }, 542 }, 543 NewQueue: &schedulingv1.Queue{ 544 ObjectMeta: metav1.ObjectMeta{ 545 Name: "q1-updated", 546 Namespace: namespace, 547 }, 548 }, 549 Expected: nil, 550 }, 551 { 552 Name: "Error Case: 2 - Wrong Type(NewQueue)", 553 OldQueue: &schedulingv1.Queue{ 554 ObjectMeta: metav1.ObjectMeta{ 555 Name: "q1", 556 Namespace: namespace, 557 }, 558 }, 559 NewQueue: &schedulingv1.Queue{ 560 ObjectMeta: metav1.ObjectMeta{ 561 Name: "q1-updated", 562 Namespace: namespace, 563 }, 564 }, 565 Expected: nil, 566 }, 567 } 568 569 for i, test := range tests { 570 cache := &SchedulerCache{ 571 Jobs: make(map[api.JobID]*api.JobInfo), 572 Nodes: make(map[string]*api.NodeInfo), 573 Queues: make(map[api.QueueID]*api.QueueInfo), 574 } 575 576 cache.UpdateQueueV1beta1(test.OldQueue, test.NewQueue) 577 578 queue := cache.Queues["q1-updated"] 579 580 if test.Expected != nil && queue != nil && queue.Queue != nil && (queue.Queue.Namespace != test.Expected.Namespace || queue.Queue.Name != test.Expected.Name) { 581 t.Errorf("Expected: %v but got: %v in case %d", test.Expected, queue.Queue, i) 582 } 583 } 584 } 585 586 func TestSchedulerCache_DeleteQueueV1beta1(t *testing.T) { 587 namespace := "test" 588 589 tests := []struct { 590 Name string 591 Queue interface{} 592 Expected *scheduling.Queue 593 }{ 594 { 595 Name: "Success Case", 596 Queue: &schedulingv1.Queue{ 597 ObjectMeta: metav1.ObjectMeta{ 598 Name: "q1", 599 Namespace: namespace, 600 }, 601 }, 602 Expected: &scheduling.Queue{ 603 ObjectMeta: metav1.ObjectMeta{ 604 Name: "q1", 605 Namespace: namespace, 606 }, 607 }, 608 }, 609 { 610 Name: "Error Case: 1 - Wrong Type", 611 Queue: &schedulingv1.Queue{ 612 ObjectMeta: metav1.ObjectMeta{ 613 Name: "q1", 614 Namespace: namespace, 615 }, 616 }, 617 Expected: nil, 618 }, 619 } 620 621 for i, test := range tests { 622 cache := &SchedulerCache{ 623 Jobs: make(map[api.JobID]*api.JobInfo), 624 Nodes: make(map[string]*api.NodeInfo), 625 Queues: make(map[api.QueueID]*api.QueueInfo), 626 } 627 628 cache.AddQueueV1beta1(test.Queue) 629 cache.DeleteQueueV1beta1(test.Queue) 630 631 queue := cache.Queues["q1"] 632 633 if test.Expected == nil && queue != nil { 634 t.Errorf("Expected: %v but got: %v in case %d", test.Expected, queue, i) 635 } 636 637 if test.Expected != nil && queue != nil && queue.Queue != nil && (queue.Queue.Namespace != test.Expected.Namespace || queue.Queue.Name != test.Expected.Name) { 638 t.Errorf("Expected: %v but got: %v in case %d", test.Expected, queue.Queue, i) 639 } 640 } 641 }