Skip to content

Commit

Permalink
[YUNIKORN-2848] Refactor preemption_queue_test.go (#983)
Browse files Browse the repository at this point in the history
Closes: #983

Signed-off-by: Craig Condit <[email protected]>
  • Loading branch information
ryankert01 authored and craigcondit committed Oct 24, 2024
1 parent 597983c commit 5d3eb36
Showing 1 changed file with 197 additions and 84 deletions.
281 changes: 197 additions & 84 deletions pkg/scheduler/objects/preemption_queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,101 +53,214 @@ type res struct {
assertMessages assertMessage
}

func TestGetPreemptableResource(t *testing.T) {
// no guaranteed and no usage. so nothing to preempt
func setupQueueStructure(t *testing.T) (*Queue, *Queue, *Queue, *Queue) {
rootQ, err := createRootQueue(map[string]string{"first": "20"})
assert.NilError(t, err)
var parentQ, childQ1, childQ2 *Queue
parentQ, err = createManagedQueue(rootQ, "parent", true, map[string]string{"first": "15"})
parentQ, err := createManagedQueue(rootQ, "parent", true, map[string]string{"first": "15"})
assert.NilError(t, err)
childQ1, err = createManagedQueue(parentQ, "child1", false, map[string]string{"first": "10"})
childQ1, err := createManagedQueue(parentQ, "child1", false, map[string]string{"first": "10"})
assert.NilError(t, err)
childQ2, err = createManagedQueue(parentQ, "child2", false, map[string]string{"first": "5"})
childQ2, err := createManagedQueue(parentQ, "child2", false, map[string]string{"first": "5"})
assert.NilError(t, err)
return rootQ, parentQ, childQ1, childQ2
}

rootPreemptable, pPreemptable, cPreemptable1, cPreemptable2 := getPreemptableResource(rootQ, parentQ, childQ1, childQ2)
assert.Assert(t, rootPreemptable.IsEmpty(), "nothing to preempt as no guaranteed set and no usage")
assert.Assert(t, pPreemptable.IsEmpty(), "nothing to preempt as no guaranteed set and no usage")
assert.Assert(t, cPreemptable1.IsEmpty(), "nothing to preempt as no guaranteed set and no usage")
assert.Assert(t, cPreemptable2.IsEmpty(), "nothing to preempt as no guaranteed set and no usage")

// guaranteed set but no usage. so nothing to preempt
// clean start for the snapshot: whole hierarchy with guarantee
smallestRes := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 5})
//nolint:funlen
func TestGetPreemptableResource(t *testing.T) {
tests := []struct {
testName string
guaranteed resource
allocated resource
remaining resource
assertMsgs assertMessage
}{
{
// no guaranteed and no usage. so nothing to preempt
testName: "NoGuaranteedNoUsage",
guaranteed: resource{nil, nil, nil, nil},
allocated: resource{nil, nil, nil, nil},
remaining: resource{nil, nil, nil, nil},
assertMsgs: assertMessage{
rootR: "nothing to preempt as no guaranteed set and no usage",
parentR: "nothing to preempt as no guaranteed set and no usage",
childQ1R: "nothing to preempt as no guaranteed set and no usage",
childQ2R: "nothing to preempt as no guaranteed set and no usage",
},
},
{
// yes guaranteed and no usage. so nothing to preempt
testName: "YesGuaranteedNoUsage",
guaranteed: resource{
root: resources.Multiply(smallestRes, 2),
parent: smallestRes,
childQ1: childRes,
childQ2: smallestRes,
},
allocated: resource{nil, nil, nil, nil},
remaining: resource{nil, nil, nil, nil},
assertMsgs: assertMessage{
rootR: "nothing to preempt as no guaranteed set and no usage",
parentR: "nothing to preempt as no guaranteed set and no usage",
childQ1R: "nothing to preempt as no guaranteed set and no usage",
childQ2R: "nothing to preempt as no guaranteed set and no usage",
},
},
{
// add usage to parent + root: use all guaranteed at parent level
// add usage to child2: while guaranteed no resource
// usage has exceeded guaranteed for some queues, preemptable resources should be as expected
testName: "GuaranteedSetUsageExceeded1",
guaranteed: resource{nil, smallestRes, nil, nil},
allocated: resource{
root: resources.Multiply(smallestRes, 2),
parent: resources.Multiply(smallestRes, 2),
childQ1: nil,
childQ2: resources.Multiply(smallestRes, 2),
},
remaining: resource{
root: resources.Multiply(smallestRes, 2),
parent: smallestRes,
childQ1: nil,
childQ2: smallestRes,
},
assertMsgs: assertMessage{
rootR: "usage has exceeded guaranteed, preemptable resource should be as expected",
parentR: "usage has exceeded guaranteed, preemptable resource should be as expected",
childQ1R: "nothing to preempt as no guaranteed set and no usage",
childQ2R: "usage has exceeded guaranteed, preemptable resource should be as expected",
},
},
{
// add usage to parent + root: use all guaranteed at parent level
// add usage to child2: use double than guaranteed
// usage has exceeded guaranteed for some queues, preemptable resources should be as expected
testName: "GuaranteedSetUsageExceeded2",
guaranteed: resource{
root: resources.Multiply(smallestRes, 2),
parent: smallestRes,
childQ1: childRes,
childQ2: smallestRes,
},
allocated: resource{
root: resources.Multiply(smallestRes, 2),
parent: resources.Multiply(smallestRes, 2),
childQ1: nil,
childQ2: resources.Multiply(smallestRes, 2),
},
remaining: resource{
root: nil,
parent: smallestRes,
childQ1: nil,
childQ2: smallestRes,
},
assertMsgs: assertMessage{
rootR: "usage has exceeded guaranteed, preemptable resource should be as expected",
parentR: "usage has exceeded guaranteed, preemptable resource should be as expected",
childQ1R: "nothing to preempt as no guaranteed set and no usage",
childQ2R: "usage has exceeded guaranteed, preemptable resource should be as expected",
},
},
{
// add usage for all: use exactly guaranteed at parent and child level
// parent guarantee used for one type child guarantee used for second type
testName: "GuaranteedSetExactUsage",
guaranteed: resource{
root: resources.Multiply(smallestRes, 2),
parent: smallestRes,
childQ1: childRes,
childQ2: smallestRes,
},
allocated: resource{
root: smallestResDoublePlusChildRes,
parent: smallestResPlusChildRes,
childQ1: childRes,
childQ2: smallestRes,
},
remaining: resource{
root: childRes,
parent: childRes,
childQ1: nil,
childQ2: nil,
},
assertMsgs: assertMessage{
rootR: "usage has extra resource type not defined as part of guaranteed, that extra should be preemptable",
parentR: "usage has extra resource type not defined as part of guaranteed, that extra should be preemptable",
childQ1R: "nothing to preempt as no guaranteed set and no usage",
childQ2R: "nothing to preempt as no guaranteed set and no usage",
},
},
{
// add usage for root + parent: use exactly guaranteed at parent and child level
// add usage to child1: use double than guaranteed
// parent guarantee used for one type child guarantee used for second type
testName: "GuaranteedSetMixedUsage",
guaranteed: resource{
root: resources.Multiply(smallestRes, 2),
parent: smallestRes,
childQ1: childRes,
childQ2: smallestRes,
},
allocated: resource{
root: smallestResDoublePlusChildResDouble,
parent: smallestResPlusChildResDouble,
childQ1: childResDouble,
childQ2: nil,
},
remaining: resource{
root: resources.Multiply(childRes, 2),
parent: resources.Multiply(childRes, 2),
childQ1: childRes,
childQ2: nil,
},
assertMsgs: assertMessage{
rootR: "usage has extra resource type not defined as part of guaranteed, that extra should be preemptable",
parentR: "usage has extra resource type not defined as part of guaranteed, that extra should be preemptable",
childQ1R: "usage has exceeded guaranteed for some queues, preemptable resources should be as expected",
childQ2R: "nothing to preempt as no guaranteed set and no usage",
},
},
}

// clean start for the snapshot: all set guaranteed - new tests
// add usage to parent + root: use all guaranteed at parent level
// add usage to child2: use double than guaranteed
parentQ.guaranteedResource = smallestRes
rootQ.allocatedResource = resources.Multiply(smallestRes, 2)
parentQ.allocatedResource = resources.Multiply(smallestRes, 2)
childQ2.allocatedResource = resources.Multiply(smallestRes, 2)
rootPreemptable, pPreemptable, cPreemptable1, cPreemptable2 = getPreemptableResource(rootQ, parentQ, childQ1, childQ2)
assert.Assert(t, resources.Equals(rootPreemptable, resources.Multiply(smallestRes, 2)), "usage is equal to guaranteed in root queue. so nothing to preempt")
assert.Assert(t, resources.Equals(pPreemptable, smallestRes), "usage has exceeded twice than guaranteed in parent queue. preemtable resource should be equal to guaranteed res")
assert.Assert(t, resources.IsZero(cPreemptable1), "nothing to preempt as no usage in child1 queue")
assert.Assert(t, resources.Equals(cPreemptable2, smallestRes), "usage has exceeded twice than guaranteed in child2 queue. preemtable resource should be equal to guaranteed res")
for _, tt := range tests {
t.Run(tt.testName, func(t *testing.T) {
rootQ, parentQ, childQ1, childQ2 := setupQueueStructure(t)

rootQ.guaranteedResource = resources.Multiply(smallestRes, 2)
parentQ.guaranteedResource = smallestRes
childQ2.guaranteedResource = smallestRes
rootQ.allocatedResource = nil
parentQ.allocatedResource = nil
childQ2.allocatedResource = nil
childRes := resources.NewResourceFromMap(map[string]resources.Quantity{"second": 5})
childQ1.guaranteedResource = childRes
rootPreemptable, pPreemptable, cPreemptable1, cPreemptable2 = getPreemptableResource(rootQ, parentQ, childQ1, childQ2)
assert.Assert(t, rootPreemptable.IsEmpty(), "nothing to preempt as no usage")
assert.Assert(t, pPreemptable.IsEmpty(), "nothing to preempt as no usage")
assert.Assert(t, cPreemptable1.IsEmpty(), "nothing to preempt as no usage")
assert.Assert(t, cPreemptable2.IsEmpty(), "nothing to preempt as no usage")
// Set guaranteed resources
rootQ.guaranteedResource = tt.guaranteed.root
parentQ.guaranteedResource = tt.guaranteed.parent
childQ1.guaranteedResource = tt.guaranteed.childQ1
childQ2.guaranteedResource = tt.guaranteed.childQ2

// clean start for the snapshot: all set guaranteed
// add usage to parent + root: use all guaranteed at parent level
// add usage to child2: use double than guaranteed
rootQ.guaranteedResource = resources.Multiply(smallestRes, 2)
parentQ.guaranteedResource = smallestRes
childQ2.guaranteedResource = smallestRes
rootQ.allocatedResource = resources.Multiply(smallestRes, 2)
parentQ.allocatedResource = resources.Multiply(smallestRes, 2)
childQ2.allocatedResource = resources.Multiply(smallestRes, 2)
rootPreemptable, pPreemptable, cPreemptable1, cPreemptable2 = getPreemptableResource(rootQ, parentQ, childQ1, childQ2)
assert.Assert(t, resources.IsZero(rootPreemptable), "usage is equal to guaranteed in root queue. so nothing to preempt")
assert.Assert(t, resources.Equals(pPreemptable, smallestRes), "usage has exceeded twice than guaranteed in parent queue. preemtable resource should be equal to guaranteed res")
assert.Assert(t, resources.IsZero(cPreemptable1), "nothing to preempt as no usage in child1 queue")
assert.Assert(t, resources.Equals(cPreemptable2, smallestRes), "usage has exceeded twice than guaranteed in child2 queue. preemtable resource should be equal to guaranteed res")
// Set allocated resources
rootQ.allocatedResource = tt.allocated.root
parentQ.allocatedResource = tt.allocated.parent
childQ1.allocatedResource = tt.allocated.childQ1
childQ2.allocatedResource = tt.allocated.childQ2

// clean start for the snapshot: all set guaranteed
// add usage for all: use exactly guaranteed at parent and child level
// parent guarantee used for one type child guarantee used for second type
bothRes := resources.Multiply(smallestRes, 2)
bothRes.AddTo(childRes)
rootQ.allocatedResource = bothRes
bothRes = resources.Add(smallestRes, childRes)
parentQ.allocatedResource = bothRes
childQ1.allocatedResource = childRes
childQ2.allocatedResource = smallestRes
rootPreemptable, pPreemptable, cPreemptable1, cPreemptable2 = getPreemptableResource(rootQ, parentQ, childQ1, childQ2)
assert.Assert(t, resources.Equals(rootPreemptable, resources.Multiply(childRes, 1)), "usage in root queue has extra resource type not defined as part of guaranteed res. So, that extra resource type should be preempted")
assert.Assert(t, resources.Equals(pPreemptable, resources.Multiply(childRes, 1)), "usage in parent1 queue has extra resource type not defined as part of guaranteed res. So, that extra resource type should be preempted")
assert.Assert(t, resources.IsZero(cPreemptable1), "usage in child1 queue is equal to guaranteed res. so nothing to preempt")
assert.Assert(t, resources.IsZero(cPreemptable2), "nothing to preempt as no usage in child2 queue")
rootPreemptable, parentPreemptable, child1Preemptable, child2Preemptable := getPreemptableResource(rootQ, parentQ, childQ1, childQ2)

// clean start for the snapshot: all set guaranteed
// add usage for root + parent: use exactly guaranteed at parent and child level
// add usage to child1: use double than guaranteed
// parent guarantee used for one type child guarantee used for second type
bothRes = resources.Multiply(smallestRes, 2)
bothRes.AddTo(resources.Multiply(childRes, 2))
rootQ.allocatedResource = bothRes
bothRes = resources.Add(smallestRes, resources.Multiply(childRes, 2))
parentQ.allocatedResource = bothRes
childQ1.allocatedResource = resources.Multiply(childRes, 2)
rootPreemptable, pPreemptable, cPreemptable1, cPreemptable2 = getPreemptableResource(rootQ, parentQ, childQ1, childQ2)
assert.Assert(t, resources.Equals(rootPreemptable, resources.Multiply(childRes, 2)), "usage in root queue has extra resource type not defined as part of guaranteed res. So, that extra resource type should be preempted")
assert.Assert(t, resources.Equals(pPreemptable, resources.Multiply(childRes, 2)), "usage in parent1 queue has extra resource type not defined as part of guaranteed res. So, that extra resource type should be preempted")
assert.Assert(t, resources.Equals(cPreemptable1, childRes), "usage has exceeded twice than guaranteed in child1 queue. cPreemptable1 resource should be equal to guaranteed res")
assert.Assert(t, resources.IsZero(cPreemptable2), "nothing to preempt as no usage in child2 queue")
if tt.remaining.root != nil {
assert.Assert(t, resources.Equals(rootPreemptable, tt.remaining.root), tt.assertMsgs.rootR)
} else {
assert.Assert(t, resources.IsZero(rootPreemptable), tt.assertMsgs.rootR)
}
if tt.remaining.parent != nil {
assert.Assert(t, resources.Equals(parentPreemptable, tt.remaining.parent), tt.assertMsgs.parentR)
} else {
assert.Assert(t, resources.IsZero(parentPreemptable), tt.assertMsgs.parentR)
}
if tt.remaining.childQ1 != nil {
assert.Assert(t, resources.Equals(child1Preemptable, tt.remaining.childQ1), tt.assertMsgs.childQ1R)
} else {
assert.Assert(t, resources.IsZero(child1Preemptable), tt.assertMsgs.childQ1R)
}
if tt.remaining.childQ2 != nil {
assert.Assert(t, resources.Equals(child2Preemptable, tt.remaining.childQ2), tt.assertMsgs.childQ2R)
} else {
assert.Assert(t, resources.IsZero(child2Preemptable), tt.assertMsgs.childQ2R)
}
})
}
}

func TestGetRemainingGuaranteedResource(t *testing.T) {
Expand Down

0 comments on commit 5d3eb36

Please sign in to comment.