volcano.sh/volcano@v1.9.0/pkg/scheduler/plugins/tdm/tdm_test.go (about) 1 /* 2 Copyright 2021 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 tdm 18 19 import ( 20 "fmt" 21 "math" 22 "reflect" 23 "testing" 24 "time" 25 26 "github.com/agiledragon/gomonkey/v2" 27 v1 "k8s.io/api/core/v1" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/client-go/tools/record" 30 31 schedulingv2 "volcano.sh/apis/pkg/apis/scheduling/v1beta1" 32 "volcano.sh/volcano/pkg/scheduler/api" 33 "volcano.sh/volcano/pkg/scheduler/cache" 34 "volcano.sh/volcano/pkg/scheduler/conf" 35 "volcano.sh/volcano/pkg/scheduler/framework" 36 "volcano.sh/volcano/pkg/scheduler/util" 37 ) 38 39 const ( 40 eps = 1e-8 41 ) 42 43 func Test_parseRevocableZone(t *testing.T) { 44 tests := []struct { 45 rz string 46 delta int64 47 err bool 48 }{ 49 { 50 rz: "00:00_01:00", 51 delta: 0, 52 err: true, 53 }, 54 { 55 rz: "00:00-01:00", 56 delta: 60 * 60, 57 err: false, 58 }, 59 { 60 rz: "0:00-23:59", 61 delta: 23*60*60 + 59*60, 62 err: false, 63 }, 64 { 65 rz: "0:00", 66 delta: 0, 67 err: true, 68 }, 69 { 70 rz: "1:00-0:00", 71 delta: 23 * 60 * 60, 72 err: false, 73 }, 74 { 75 rz: "1:0-0:0", 76 delta: 0, 77 err: true, 78 }, 79 { 80 rz: " 1:00-0:00 ", 81 delta: 23 * 60 * 60, 82 err: false, 83 }, 84 { 85 rz: "23:59-23:59", 86 delta: 24 * 60 * 60, 87 err: false, 88 }, 89 { 90 rz: "63:59-23:59", 91 delta: 0, 92 err: true, 93 }, 94 } 95 96 for i, c := range tests { 97 t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { 98 start, end, err := parseRevocableZone(c.rz) 99 if (err != nil) != c.err { 100 t.Errorf("want %v ,got %v, err: %v", c.err, err != nil, err) 101 } 102 103 if end.Unix()-start.Unix() != c.delta { 104 t.Errorf("want %v, got %v", c.delta, end.Unix()-start.Unix()) 105 } 106 107 }) 108 } 109 } 110 111 func Test_TDM(t *testing.T) { 112 var tmp *cache.SchedulerCache 113 patchUpdateQueueStatus := gomonkey.ApplyMethod(reflect.TypeOf(tmp), "UpdateQueueStatus", func(scCache *cache.SchedulerCache, queue *api.QueueInfo) error { 114 return nil 115 }) 116 defer patchUpdateQueueStatus.Reset() 117 118 framework.RegisterPluginBuilder(PluginName, New) 119 defer framework.CleanupPluginBuilders() 120 121 p1 := util.BuildPod("c1", "p1", "", v1.PodPending, api.BuildResourceList("1", "1Gi"), "pg1", make(map[string]string), make(map[string]string)) 122 p2 := util.BuildPod("c1", "p2", "", v1.PodPending, api.BuildResourceList("1", "1Gi"), "pg1", make(map[string]string), make(map[string]string)) 123 p3 := util.BuildPod("c1", "p3", "", v1.PodPending, api.BuildResourceList("1", "1Gi"), "pg1", make(map[string]string), make(map[string]string)) 124 125 p1.Annotations[schedulingv2.RevocableZone] = "*" 126 p3.Annotations[schedulingv2.RevocableZone] = "*" 127 128 n1 := util.BuildNode("n1", api.BuildResourceList("16", "64Gi", []api.ScalarResource{{Name: "pods", Value: "10"}}...), map[string]string{ 129 schedulingv2.RevocableZone: "rz1", 130 }) 131 132 n2 := util.BuildNode("n2", api.BuildResourceList("16", "64Gi", []api.ScalarResource{{Name: "pods", Value: "10"}}...), map[string]string{ 133 schedulingv2.RevocableZone: "rz1", 134 }) 135 136 n3 := util.BuildNode("n3", api.BuildResourceList("16", "64Gi", []api.ScalarResource{{Name: "pods", Value: "10"}}...), map[string]string{}) 137 n4 := util.BuildNode("n4", api.BuildResourceList("16", "64Gi", []api.ScalarResource{{Name: "pods", Value: "10"}}...), map[string]string{}) 138 139 n5 := util.BuildNode("n5", api.BuildResourceList("16", "64Gi", []api.ScalarResource{{Name: "pods", Value: "10"}}...), map[string]string{ 140 schedulingv2.RevocableZone: "rz2", 141 }) 142 143 pg1 := &schedulingv2.PodGroup{ 144 ObjectMeta: metav1.ObjectMeta{ 145 Name: "pg1", 146 Namespace: "c1", 147 }, 148 Spec: schedulingv2.PodGroupSpec{ 149 Queue: "c1", 150 }, 151 } 152 153 queue1 := &schedulingv2.Queue{ 154 ObjectMeta: metav1.ObjectMeta{ 155 Name: "c1", 156 }, 157 Spec: schedulingv2.QueueSpec{ 158 Weight: 1, 159 }, 160 } 161 162 tests := []struct { 163 name string 164 podGroups []*schedulingv2.PodGroup 165 pod *v1.Pod 166 nodes []*v1.Node 167 queues []*schedulingv2.Queue 168 predicatedExpected map[string]bool 169 scoreExpected map[string]map[string]float64 170 }{ 171 { 172 name: "preemptable task rz available", 173 podGroups: []*schedulingv2.PodGroup{ 174 pg1, 175 }, 176 queues: []*schedulingv2.Queue{ 177 queue1, 178 }, 179 pod: p1, 180 nodes: []*v1.Node{ 181 n1, n2, n3, n4, n5, 182 }, 183 predicatedExpected: map[string]bool{"n1": true, "n2": true, "n3": true, "n4": true}, 184 scoreExpected: map[string]map[string]float64{ 185 "c1/p1": { 186 "n1": 100, 187 "n2": 100, 188 "n3": 0, 189 "n4": 0, 190 }, 191 }, 192 }, 193 { 194 name: "not preemptable task", 195 podGroups: []*schedulingv2.PodGroup{ 196 pg1, 197 }, 198 queues: []*schedulingv2.Queue{ 199 queue1, 200 }, 201 pod: p2, 202 nodes: []*v1.Node{ 203 n1, n2, n3, n4, n5, 204 }, 205 predicatedExpected: map[string]bool{"n3": true, "n4": true}, 206 scoreExpected: map[string]map[string]float64{ 207 "c1/p2": { 208 "n3": 0, 209 "n4": 0, 210 }, 211 }, 212 }, 213 { 214 name: "preemptable task and multiple rz", 215 podGroups: []*schedulingv2.PodGroup{ 216 pg1, 217 }, 218 queues: []*schedulingv2.Queue{ 219 queue1, 220 }, 221 pod: p3, 222 nodes: []*v1.Node{ 223 n1, n2, n3, n4, n5, 224 }, 225 predicatedExpected: map[string]bool{"n1": true, "n2": true, "n3": true, "n4": true}, 226 scoreExpected: map[string]map[string]float64{ 227 "c1/p3": { 228 "n1": 100, 229 "n2": 100, 230 "n3": 0, 231 "n4": 0, 232 }, 233 }, 234 }, 235 } 236 237 for i, test := range tests { 238 t.Run(fmt.Sprintf("case %v %v", i, test.name), func(t *testing.T) { 239 binder := &util.FakeBinder{ 240 Binds: map[string]string{}, 241 Channel: make(chan string), 242 } 243 schedulerCache := &cache.SchedulerCache{ 244 Nodes: make(map[string]*api.NodeInfo), 245 Jobs: make(map[api.JobID]*api.JobInfo), 246 Queues: make(map[api.QueueID]*api.QueueInfo), 247 Binder: binder, 248 StatusUpdater: &util.FakeStatusUpdater{}, 249 VolumeBinder: &util.FakeVolumeBinder{}, 250 251 Recorder: record.NewFakeRecorder(100), 252 } 253 for _, node := range test.nodes { 254 schedulerCache.AddOrUpdateNode(node) 255 } 256 257 schedulerCache.AddPod(test.pod) 258 259 for _, ss := range test.podGroups { 260 schedulerCache.AddPodGroupV1beta1(ss) 261 } 262 for _, q := range test.queues { 263 schedulerCache.AddQueueV1beta1(q) 264 } 265 266 trueValue := true 267 ssn := framework.OpenSession(schedulerCache, []conf.Tier{ 268 { 269 Plugins: []conf.PluginOption{ 270 { 271 Name: PluginName, 272 EnabledNodeOrder: &trueValue, 273 EnabledPredicate: &trueValue, 274 Arguments: map[string]interface{}{ 275 "tdm.revocable-zone.rz1": "0:00-0:00", 276 "tdm.revocable-zone.rz2": "0:00-0:01", 277 }, 278 }, 279 }, 280 }, 281 }, nil) 282 283 defer framework.CloseSession(ssn) 284 285 for _, job := range ssn.Jobs { 286 for _, task := range job.Tasks { 287 taskID := fmt.Sprintf("%s/%s", task.Namespace, task.Name) 288 289 predicatedNode := make([]*api.NodeInfo, 0) 290 for _, node := range ssn.Nodes { 291 predicateStatus, err := ssn.PredicateFn(task, node) 292 if err != nil { 293 continue 294 } 295 predicateIsSuccess := true 296 for _, status := range predicateStatus { 297 if status != nil && status.Code != api.Success { 298 predicateIsSuccess = false 299 break 300 } 301 } 302 if predicateIsSuccess == false { 303 continue 304 } 305 predicatedNode = append(predicatedNode, node) 306 } 307 308 if len(predicatedNode) != len(test.predicatedExpected) { 309 t.Errorf("want %v nodes,but got %v", len(test.predicatedExpected), len(predicatedNode)) 310 } 311 312 for _, node := range predicatedNode { 313 if !test.predicatedExpected[node.Name] { 314 t.Errorf("want node: %v,but not found", node.Name) 315 } 316 } 317 318 for _, node := range predicatedNode { 319 score, err := ssn.NodeOrderFn(task, node) 320 if err != nil { 321 t.Errorf("task %s on node %s has err %v", taskID, node.Name, err) 322 continue 323 } 324 if expectScore := test.scoreExpected[taskID][node.Name]; math.Abs(expectScore-score) > eps { 325 t.Errorf("task %s on node %s expect have score %v, but get %v", taskID, node.Name, expectScore, score) 326 } 327 } 328 } 329 } 330 }) 331 } 332 } 333 func Test_TDM_victimsFn(t *testing.T) { 334 var tmp *cache.SchedulerCache 335 patchUpdateQueueStatus := gomonkey.ApplyMethod(reflect.TypeOf(tmp), "UpdateQueueStatus", func(scCache *cache.SchedulerCache, queue *api.QueueInfo) error { 336 return nil 337 }) 338 defer patchUpdateQueueStatus.Reset() 339 340 framework.RegisterPluginBuilder(PluginName, New) 341 defer framework.CleanupPluginBuilders() 342 343 p1 := util.BuildPod("c1", "p1", "n1", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg1", make(map[string]string), make(map[string]string)) 344 p2 := util.BuildPod("c1", "p2", "n1", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg1", make(map[string]string), make(map[string]string)) 345 p3 := util.BuildPod("c1", "p3", "n1", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg1", make(map[string]string), make(map[string]string)) 346 p4 := util.BuildPod("c1", "p4", "n1", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg1", make(map[string]string), make(map[string]string)) 347 p5 := util.BuildPod("c1", "p5", "n1", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg1", make(map[string]string), make(map[string]string)) 348 p6 := util.BuildPod("c2", "p6", "n2", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg2", make(map[string]string), make(map[string]string)) 349 p7 := util.BuildPod("c2", "p7", "n2", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg2", make(map[string]string), make(map[string]string)) 350 p8 := util.BuildPod("c2", "p8", "n2", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg2", make(map[string]string), make(map[string]string)) 351 p9 := util.BuildPod("c2", "p9", "n2", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg2", make(map[string]string), make(map[string]string)) 352 p10 := util.BuildPod("c2", "p10", "n2", v1.PodRunning, api.BuildResourceList("1", "1Gi"), "pg2", make(map[string]string), make(map[string]string)) 353 354 p1.Annotations[schedulingv2.PodPreemptable] = "true" 355 p2.Annotations[schedulingv2.PodPreemptable] = "true" 356 p3.Annotations[schedulingv2.PodPreemptable] = "true" 357 358 p4.Annotations[schedulingv2.PodPreemptable] = "false" 359 p5.Annotations[schedulingv2.PodPreemptable] = "false" 360 361 p6.Annotations[schedulingv2.PodPreemptable] = "true" 362 p7.Annotations[schedulingv2.PodPreemptable] = "true" 363 p8.Annotations[schedulingv2.PodPreemptable] = "true" 364 p9.Annotations[schedulingv2.PodPreemptable] = "true" 365 p10.Annotations[schedulingv2.PodPreemptable] = "true" 366 367 n1 := util.BuildNode("n1", api.BuildResourceList("16", "64Gi", []api.ScalarResource{{Name: "pods", Value: "10"}}...), map[string]string{ 368 schedulingv2.RevocableZone: "rz1", 369 }) 370 371 n2 := util.BuildNode("n2", api.BuildResourceList("16", "64Gi", []api.ScalarResource{{Name: "pods", Value: "10"}}...), map[string]string{ 372 schedulingv2.RevocableZone: "rz1", 373 }) 374 375 queue1 := &schedulingv2.Queue{ 376 ObjectMeta: metav1.ObjectMeta{ 377 Name: "c1", 378 }, 379 Spec: schedulingv2.QueueSpec{ 380 Weight: 1, 381 }, 382 } 383 384 queue2 := &schedulingv2.Queue{ 385 ObjectMeta: metav1.ObjectMeta{ 386 Name: "c2", 387 }, 388 Spec: schedulingv2.QueueSpec{ 389 Weight: 1, 390 }, 391 } 392 393 tests := []struct { 394 podGroups []*schedulingv2.PodGroup 395 pods []*v1.Pod 396 nodes []*v1.Node 397 queues []*schedulingv2.Queue 398 args framework.Arguments 399 want int 400 }{ 401 { 402 podGroups: []*schedulingv2.PodGroup{ 403 { 404 ObjectMeta: metav1.ObjectMeta{ 405 Name: "pg1", 406 Namespace: "c1", 407 Annotations: map[string]string{ 408 schedulingv2.JDBMaxUnavailable: "30%", 409 }, 410 }, 411 Spec: schedulingv2.PodGroupSpec{ 412 Queue: "c1", 413 }, 414 }, 415 }, 416 queues: []*schedulingv2.Queue{ 417 queue1, 418 }, 419 pods: []*v1.Pod{ 420 p1, p2, p3, p4, p5, 421 }, 422 nodes: []*v1.Node{ 423 n1, 424 }, 425 args: framework.Arguments{ 426 "tdm.revocable-zone.rz1": "0:00-0:01", 427 "tdm.evict.period": "100ms", 428 }, 429 want: 2, 430 }, 431 { 432 podGroups: []*schedulingv2.PodGroup{ 433 { 434 ObjectMeta: metav1.ObjectMeta{ 435 Name: "pg1", 436 Namespace: "c1", 437 Annotations: map[string]string{ 438 schedulingv2.JDBMaxUnavailable: "30%", 439 }, 440 }, 441 Spec: schedulingv2.PodGroupSpec{ 442 Queue: "c1", 443 }, 444 }, 445 }, 446 queues: []*schedulingv2.Queue{ 447 queue1, 448 }, 449 pods: []*v1.Pod{ 450 p1, p2, p3, p4, p5, 451 }, 452 nodes: []*v1.Node{ 453 n1, 454 }, 455 args: framework.Arguments{ 456 "tdm.revocable-zone.rz1": "0:00-0:00", 457 "tdm.evict.period": "100ms", 458 }, 459 want: 0, 460 }, 461 { 462 podGroups: []*schedulingv2.PodGroup{ 463 { 464 ObjectMeta: metav1.ObjectMeta{ 465 Name: "pg1", 466 Namespace: "c1", 467 Annotations: map[string]string{ 468 schedulingv2.JDBMaxUnavailable: "99%", 469 }, 470 }, 471 Spec: schedulingv2.PodGroupSpec{ 472 Queue: "c1", 473 }, 474 }, 475 }, 476 queues: []*schedulingv2.Queue{ 477 queue1, 478 }, 479 pods: []*v1.Pod{ 480 p1, p2, p3, p4, p5, 481 }, 482 nodes: []*v1.Node{ 483 n1, 484 }, 485 args: framework.Arguments{ 486 "tdm.revocable-zone.rz1": "0:00-0:01", 487 "tdm.evict.period": "1s", 488 }, 489 want: 3, 490 }, 491 { 492 podGroups: []*schedulingv2.PodGroup{ 493 { 494 ObjectMeta: metav1.ObjectMeta{ 495 Name: "pg2", 496 Namespace: "c2", 497 Annotations: map[string]string{ 498 schedulingv2.JDBMaxUnavailable: "50%", 499 }, 500 }, 501 Spec: schedulingv2.PodGroupSpec{ 502 Queue: "c2", 503 }, 504 }, 505 }, 506 queues: []*schedulingv2.Queue{ 507 queue2, 508 }, 509 pods: []*v1.Pod{ 510 p6, p7, p8, p9, p10, 511 }, 512 nodes: []*v1.Node{ 513 n2, 514 }, 515 args: framework.Arguments{ 516 "tdm.revocable-zone.rz1": "0:00-0:01", 517 "tdm.evict.period": "1s", 518 }, 519 want: 3, 520 }, 521 { 522 podGroups: []*schedulingv2.PodGroup{ 523 { 524 ObjectMeta: metav1.ObjectMeta{ 525 Name: "pg2", 526 Namespace: "c2", 527 Annotations: map[string]string{ 528 schedulingv2.JDBMaxUnavailable: "50%", 529 }, 530 }, 531 Spec: schedulingv2.PodGroupSpec{ 532 Queue: "c2", 533 }, 534 }, 535 { 536 ObjectMeta: metav1.ObjectMeta{ 537 Name: "pg1", 538 Namespace: "c1", 539 Annotations: map[string]string{ 540 schedulingv2.JDBMaxUnavailable: "90%", 541 }, 542 }, 543 Spec: schedulingv2.PodGroupSpec{ 544 Queue: "c1", 545 }, 546 }, 547 }, 548 queues: []*schedulingv2.Queue{ 549 queue1, 550 queue2, 551 }, 552 pods: []*v1.Pod{ 553 p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, 554 }, 555 nodes: []*v1.Node{ 556 n1, n2, 557 }, 558 args: framework.Arguments{ 559 "tdm.revocable-zone.rz1": "0:00-0:01", 560 "tdm.evict.period": "1s", 561 }, 562 want: 6, 563 }, 564 { 565 podGroups: []*schedulingv2.PodGroup{ 566 { 567 ObjectMeta: metav1.ObjectMeta{ 568 Name: "pg2", 569 Namespace: "c2", 570 Annotations: map[string]string{ 571 schedulingv2.JDBMaxUnavailable: "3", 572 }, 573 }, 574 Spec: schedulingv2.PodGroupSpec{ 575 Queue: "c2", 576 }, 577 }, 578 }, 579 queues: []*schedulingv2.Queue{ 580 queue2, 581 }, 582 pods: []*v1.Pod{ 583 p6, p7, p8, p9, p10, 584 }, 585 nodes: []*v1.Node{ 586 n2, 587 }, 588 args: framework.Arguments{ 589 "tdm.revocable-zone.rz1": "0:00-0:01", 590 "tdm.evict.period": "1s", 591 }, 592 want: 3, 593 }, 594 { 595 podGroups: []*schedulingv2.PodGroup{ 596 { 597 ObjectMeta: metav1.ObjectMeta{ 598 Name: "pg2", 599 Namespace: "c2", 600 Annotations: map[string]string{ 601 schedulingv2.JDBMinAvailable: "3", 602 }, 603 }, 604 Spec: schedulingv2.PodGroupSpec{ 605 Queue: "c2", 606 }, 607 }, 608 }, 609 queues: []*schedulingv2.Queue{ 610 queue2, 611 }, 612 pods: []*v1.Pod{ 613 p6, p7, p8, p9, p10, 614 }, 615 nodes: []*v1.Node{ 616 n2, 617 }, 618 args: framework.Arguments{ 619 "tdm.revocable-zone.rz1": "0:00-0:01", 620 "tdm.evict.period": "1s", 621 }, 622 want: 2, 623 }, 624 { 625 podGroups: []*schedulingv2.PodGroup{ 626 { 627 ObjectMeta: metav1.ObjectMeta{ 628 Name: "pg2", 629 Namespace: "c2", 630 Annotations: map[string]string{ 631 schedulingv2.JDBMinAvailable: "30%", 632 }, 633 }, 634 Spec: schedulingv2.PodGroupSpec{ 635 Queue: "c2", 636 }, 637 }, 638 }, 639 queues: []*schedulingv2.Queue{ 640 queue2, 641 }, 642 pods: []*v1.Pod{ 643 p6, p7, p8, p9, p10, 644 }, 645 nodes: []*v1.Node{ 646 n2, 647 }, 648 args: framework.Arguments{ 649 "tdm.revocable-zone.rz1": "0:00-0:01", 650 "tdm.evict.period": "1s", 651 }, 652 want: 3, 653 }, 654 { 655 podGroups: []*schedulingv2.PodGroup{ 656 { 657 ObjectMeta: metav1.ObjectMeta{ 658 Name: "pg2", 659 Namespace: "c2", 660 Annotations: map[string]string{ 661 schedulingv2.JDBMinAvailable: "2", 662 }, 663 }, 664 Spec: schedulingv2.PodGroupSpec{ 665 Queue: "c2", 666 }, 667 }, 668 { 669 ObjectMeta: metav1.ObjectMeta{ 670 Name: "pg1", 671 Namespace: "c1", 672 Annotations: map[string]string{ 673 schedulingv2.JDBMaxUnavailable: "3", 674 }, 675 }, 676 Spec: schedulingv2.PodGroupSpec{ 677 Queue: "c1", 678 }, 679 }, 680 }, 681 queues: []*schedulingv2.Queue{ 682 queue1, 683 queue2, 684 }, 685 pods: []*v1.Pod{ 686 p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, 687 }, 688 nodes: []*v1.Node{ 689 n1, n2, 690 }, 691 args: framework.Arguments{ 692 "tdm.revocable-zone.rz1": "0:00-0:01", 693 "tdm.evict.period": "1s", 694 }, 695 want: 6, 696 }, 697 } 698 699 for i, test := range tests { 700 t.Run(fmt.Sprintf("case %v", i), func(t *testing.T) { 701 binder := &util.FakeBinder{ 702 Binds: map[string]string{}, 703 Channel: make(chan string), 704 } 705 schedulerCache := &cache.SchedulerCache{ 706 Nodes: make(map[string]*api.NodeInfo), 707 Jobs: make(map[api.JobID]*api.JobInfo), 708 Queues: make(map[api.QueueID]*api.QueueInfo), 709 Binder: binder, 710 StatusUpdater: &util.FakeStatusUpdater{}, 711 VolumeBinder: &util.FakeVolumeBinder{}, 712 713 Recorder: record.NewFakeRecorder(100), 714 } 715 for _, node := range test.nodes { 716 schedulerCache.AddOrUpdateNode(node) 717 } 718 719 for _, pod := range test.pods { 720 schedulerCache.AddPod(pod) 721 } 722 723 for _, ss := range test.podGroups { 724 schedulerCache.AddPodGroupV1beta1(ss) 725 } 726 for _, q := range test.queues { 727 schedulerCache.AddQueueV1beta1(q) 728 } 729 730 trueValue := true 731 ssn := framework.OpenSession(schedulerCache, []conf.Tier{ 732 { 733 Plugins: []conf.PluginOption{ 734 { 735 Name: PluginName, 736 EnabledVictim: &trueValue, 737 Arguments: test.args, 738 }, 739 }, 740 }, 741 }, nil) 742 743 defer framework.CloseSession(ssn) 744 745 d, _ := time.ParseDuration(test.args[evictPeriodLabel].(string)) 746 time.Sleep(d) 747 tasks := make([]*api.TaskInfo, 0) 748 res := ssn.VictimTasks(tasks) 749 if len(res) != test.want { 750 t.Errorf("want %v, got %v", test.want, len(res)) 751 return 752 } 753 754 }) 755 } 756 }