@@ -25,6 +25,7 @@ import (
25
25
26
26
"github.com/eapache/go-resiliency/retrier"
27
27
"github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/quotaplugins/quota-forest/quota-manager/quota"
28
+ "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/quotaplugins/quota-forest/quota-manager/quota/core"
28
29
"github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/quotaplugins/quota-forest/quota-manager/quota/utils"
29
30
"github.com/stretchr/testify/assert"
30
31
"k8s.io/utils/strings/slices"
@@ -662,6 +663,158 @@ func TestAddRemoveConsumers(t *testing.T) {
662
663
assert .Error (t , err , "Expecting error when removing a non-existing consumer" )
663
664
}
664
665
666
+ // TestPreemptSamePriorityAtRoot : test preemption of same priority borrowing consumer at root
667
+ func TestPreemptSamePriorityAtRoot (t * testing.T ) {
668
+
669
+ var treeString string = `{
670
+ "kind": "QuotaTree",
671
+ "metadata": {
672
+ "name": "tree"
673
+ },
674
+ "spec": {
675
+ "resourceNames": [
676
+ "gpu"
677
+ ],
678
+ "nodes": {
679
+ "T": {
680
+ "parent": "nil",
681
+ "hard": "true",
682
+ "quota": {
683
+ "gpu": "32"
684
+ }
685
+ },
686
+ "M": {
687
+ "parent": "T",
688
+ "quota": {
689
+ "gpu": "16"
690
+ }
691
+ },
692
+ "N": {
693
+ "parent": "T",
694
+ "quota": {
695
+ "gpu": "16"
696
+ }
697
+ },
698
+ "A": {
699
+ "parent": "M",
700
+ "quota": {
701
+ "gpu": "8"
702
+ }
703
+ },
704
+ "B": {
705
+ "parent": "M",
706
+ "quota": {
707
+ "gpu": "8"
708
+ }
709
+ },
710
+ "C": {
711
+ "parent": "N",
712
+ "quota": {
713
+ "gpu": "8"
714
+ }
715
+ },
716
+ "D": {
717
+ "parent": "N",
718
+ "quota": {
719
+ "gpu": "8"
720
+ }
721
+ }
722
+ }
723
+ }
724
+ }`
725
+
726
+ var job1String string = `{
727
+ "kind": "Consumer",
728
+ "metadata": {
729
+ "name": "job-1"
730
+ },
731
+ "spec": {
732
+ "id": "job-1",
733
+ "trees": [
734
+ {
735
+ "treeName": "tree",
736
+ "groupID": "A",
737
+ "request": {
738
+ "gpu": 24
739
+ }
740
+ }
741
+ ]
742
+ }
743
+ }`
744
+
745
+ var job2String string = `{
746
+ "kind": "Consumer",
747
+ "metadata": {
748
+ "name": "job-2"
749
+ },
750
+ "spec": {
751
+ "id": "job-2",
752
+ "trees": [
753
+ {
754
+ "treeName": "tree",
755
+ "groupID": "C",
756
+ "request": {
757
+ "gpu": 8
758
+ }
759
+ }
760
+ ]
761
+ }
762
+ }`
763
+
764
+ var job3String string = `{
765
+ "kind": "Consumer",
766
+ "metadata": {
767
+ "name": "job-3"
768
+ },
769
+ "spec": {
770
+ "id": "job-3",
771
+ "trees": [
772
+ {
773
+ "treeName": "tree",
774
+ "groupID": "B",
775
+ "request": {
776
+ "gpu": 1
777
+ }
778
+ }
779
+ ]
780
+ }
781
+ }`
782
+
783
+ // create a test quota manager
784
+ qmTest := quota .NewManager ()
785
+ assert .NotNil (t , qmTest , "Expecting no error creating a quota manager" )
786
+ modeSet := qmTest .SetMode (quota .Normal )
787
+ assert .True (t , modeSet , "Expecting no error setting mode to normal" )
788
+
789
+ // add quota tree
790
+ treeName , err := qmTest .AddTreeFromString (treeString )
791
+ assert .NoError (t , err , "No error expected when adding a tree" )
792
+
793
+ // create and add consumers
794
+ consumerStrings := []string {job1String , job2String , job3String }
795
+ numConsumers := len (consumerStrings )
796
+ consumerID := make ([]string , numConsumers )
797
+ var response * core.AllocationResponse
798
+ for i , consumerString := range consumerStrings {
799
+ consumerInfo , err := quota .NewConsumerInfoFromString (consumerString )
800
+ assert .NoError (t , err , "No error expected when creating a consumer info" )
801
+ consumerID [i ] = consumerInfo .GetID ()
802
+ added , err := qmTest .AddConsumer (consumerInfo )
803
+ assert .True (t , added && err == nil , "Expecting consumer to be added to quota manager" )
804
+ response , err = qmTest .Allocate (treeName , consumerID [i ])
805
+ assert .NoError (t , err , "No Error expected when allocating consumer %s to tree, err %v, got %v" ,
806
+ consumerID [i ], err , qmTest .GetTreeController (treeName ))
807
+ }
808
+
809
+ // check expected results after last allocation
810
+ assert .NotNil (t , response , "A non nill response is expected" )
811
+ assert .True (t , response .IsAllocated (), "Allocating consumer %s should succeed" , consumerID [numConsumers - 1 ])
812
+ assert .Contains (t , response .GetPreemptedIds (), consumerID [0 ],
813
+ "Expecting consumer %s to be preempted" , consumerID [0 ])
814
+ assert .Contains (t , qmTest .GetTreeController (treeName ).GetConsumerIDs (), consumerID [1 ],
815
+ "Expecting consumer %s to remain allocated" , consumerID [1 ])
816
+ }
817
+
665
818
type AllocationClassifier struct {
666
819
}
667
820
0 commit comments