karmada/pkg/modeling/modeling_test.go

716 lines
19 KiB
Go

/*
Copyright 2022 The Karmada Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package modeling
import (
"container/list"
"fmt"
"reflect"
"testing"
"github.com/emirpasic/gods/trees/redblacktree"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
clusterapis "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
)
func TestInitSummary(t *testing.T) {
rms := []clusterapis.ResourceModel{
{
Grade: 0,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1024, resource.DecimalSI),
},
},
},
{
Grade: 1,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(1, resource.DecimalSI),
Max: *resource.NewQuantity(2, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(1024, resource.DecimalSI),
Max: *resource.NewQuantity(1024*2, resource.DecimalSI),
},
},
},
}
rs, err := InitSummary(rms)
if actualValue := len(rs.RMs); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if err != nil {
t.Errorf("Got %v expected %v", err, nil)
}
}
func TestInitSummaryError(t *testing.T) {
rms := []clusterapis.ResourceModel{
{
Grade: 0,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1024, resource.DecimalSI),
},
},
},
{
Grade: 1,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(1, resource.DecimalSI),
Max: *resource.NewQuantity(2, resource.DecimalSI),
},
},
},
}
rs, err := InitSummary(rms)
if actualValue := len(rs.RMs); actualValue != 0 {
t.Errorf("Got %v expected %v", actualValue, 0)
}
if err == nil {
t.Errorf("Got %v expected %v", err, nil)
}
}
func TestInitSummaryWithOneGrade(t *testing.T) {
rms := []clusterapis.ResourceModel{
{
Grade: 0,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1024, resource.DecimalSI),
},
},
},
}
rs, err := InitSummary(rms)
if actualValue := len(rs.RMs); actualValue != 1 {
t.Errorf("Got %v expected %v", actualValue, 1)
}
if err != nil {
t.Errorf("Got %v expected %v", err, nil)
}
}
func TestSearchLastLessElement(t *testing.T) {
nums, target := []resource.Quantity{
*resource.NewMilliQuantity(1999, resource.DecimalSI),
*resource.NewMilliQuantity(4327, resource.DecimalSI),
*resource.NewMilliQuantity(9783, resource.DecimalSI),
*resource.NewMilliQuantity(12378, resource.DecimalSI),
*resource.NewMilliQuantity(23480, resource.DecimalSI),
*resource.NewMilliQuantity(74217, resource.DecimalSI),
}, *resource.NewMilliQuantity(10000, resource.DecimalSI)
index := searchLastLessElement(nums, target)
if index != 2 {
t.Errorf("Got %v expected %v", index, 2)
}
nums, target = []resource.Quantity{
*resource.NewMilliQuantity(1000, resource.DecimalSI),
*resource.NewMilliQuantity(3400, resource.DecimalSI),
*resource.NewMilliQuantity(4500, resource.DecimalSI),
*resource.NewMilliQuantity(8700, resource.DecimalSI),
*resource.NewMilliQuantity(11599, resource.DecimalSI),
*resource.NewMilliQuantity(62300, resource.DecimalSI),
*resource.NewMilliQuantity(95600, resource.DecimalSI),
*resource.NewMilliQuantity(134600, resource.DecimalSI),
}, *resource.NewMilliQuantity(9700, resource.DecimalSI)
index = searchLastLessElement(nums, target)
if index != 3 {
t.Errorf("Got %v expected %v", index, 3)
}
nums, target = []resource.Quantity{
*resource.NewMilliQuantity(1000, resource.DecimalSI),
*resource.NewMilliQuantity(2000, resource.DecimalSI),
}, *resource.NewMilliQuantity(0, resource.DecimalSI)
index = searchLastLessElement(nums, target)
if index != -1 {
t.Errorf("Got %v expected %v", index, -1)
}
}
func TestGetIndex(t *testing.T) {
rms := []clusterapis.ResourceModel{
{
Grade: 0,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1024, resource.DecimalSI),
},
},
},
{
Grade: 1,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(1, resource.DecimalSI),
Max: *resource.NewQuantity(2, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(1024, resource.DecimalSI),
Max: *resource.NewQuantity(1024*2, resource.DecimalSI),
},
},
},
}
rs, err := InitSummary(rms)
if err != nil {
t.Errorf("Got %v expected %v", err, nil)
}
crn := ClusterResourceNode{
quantity: 1,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024, resource.DecimalSI),
},
}
index := rs.getIndex(crn)
if index != 1 {
t.Errorf("Got %v expected %v", index, 1)
}
crn = ClusterResourceNode{
quantity: 1,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(20, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*100, resource.DecimalSI),
},
}
index = rs.getIndex(crn)
if index != 1 {
t.Errorf("Got %v expected %v", index, 1)
}
}
func TestClusterResourceNodeComparator(t *testing.T) {
rms := []clusterapis.ResourceModel{
{
Grade: 0,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1024, resource.DecimalSI),
},
},
},
{
Grade: 1,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(1, resource.DecimalSI),
Max: *resource.NewQuantity(2, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(1024, resource.DecimalSI),
Max: *resource.NewQuantity(1024*2, resource.DecimalSI),
},
},
},
}
rs, err := InitSummary(rms)
if err != nil {
t.Errorf("Got %v expected %v", err, nil)
}
crn1 := ClusterResourceNode{
quantity: 10,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(10, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024, resource.DecimalSI),
},
}
crn2 := ClusterResourceNode{
quantity: 789,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(2, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024, resource.DecimalSI),
},
}
if res := rs.clusterResourceNodeComparator(crn1, crn2); res != 1 {
t.Errorf("Got %v expected %v", res, 1)
}
crn1 = ClusterResourceNode{
quantity: 10,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(6, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024, resource.DecimalSI),
},
}
crn2 = ClusterResourceNode{
quantity: 789,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(6, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024, resource.DecimalSI),
},
}
if res := rs.clusterResourceNodeComparator(crn1, crn2); res != 0 {
t.Errorf("Got %v expected %v", res, 0)
}
crn1 = ClusterResourceNode{
quantity: 10,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(6, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024, resource.DecimalSI),
},
}
crn2 = ClusterResourceNode{
quantity: 789,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(6, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*10, resource.DecimalSI),
},
}
if res := rs.clusterResourceNodeComparator(crn1, crn2); res != -1 {
t.Errorf("Got %v expected %v", res, -1)
}
}
func TestGetNodeNumFromModel(t *testing.T) {
rms := []clusterapis.ResourceModel{
{
Grade: 0,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1024, resource.DecimalSI),
},
},
},
{
Grade: 1,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(1, resource.DecimalSI),
Max: *resource.NewQuantity(2, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(1024, resource.DecimalSI),
Max: *resource.NewQuantity(1024*2, resource.DecimalSI),
},
},
},
}
rs, err := InitSummary(rms)
if actualValue := len(rs.RMs); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if err != nil {
t.Errorf("Got %v expected %v", err, nil)
}
crn1 := ClusterResourceNode{
quantity: 3,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(8, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*3, resource.DecimalSI),
},
}
crn2 := ClusterResourceNode{
quantity: 1,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*6, resource.DecimalSI),
},
}
crn3 := ClusterResourceNode{
quantity: 2,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*6, resource.DecimalSI),
},
}
rs.AddToResourceSummary(crn1)
rs.AddToResourceSummary(crn2)
rs.AddToResourceSummary(crn3)
for index := range rs.RMs {
num := rs.GetNodeNumFromModel(&rs.RMs[index])
if index == 0 {
if num != 0 {
t.Errorf("Got %v expected %v", num, 0)
}
}
if index == 1 {
if num != 2 {
t.Errorf("Got %v expected %v", num, 2)
}
}
}
}
func TestConvertToResourceList(t *testing.T) {
rsl := corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*6, resource.DecimalSI),
}
for name := range rsl {
if reflect.TypeOf(name).String() != "v1.ResourceName" {
t.Errorf("Got %v expected %v", reflect.TypeOf(name), "v1.ResourceName")
}
}
}
func TestLlConvertToRbt(t *testing.T) {
rms := []clusterapis.ResourceModel{
{
Grade: 0,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1024, resource.DecimalSI),
},
},
},
{
Grade: 1,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(1, resource.DecimalSI),
Max: *resource.NewQuantity(2, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(1024, resource.DecimalSI),
Max: *resource.NewQuantity(1024*2, resource.DecimalSI),
},
},
},
}
rs, err := InitSummary(rms)
if err != nil {
t.Errorf("Got %v expected %v", err, nil)
}
crn1 := ClusterResourceNode{
quantity: 6,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(2, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*7, resource.DecimalSI),
},
}
crn2 := ClusterResourceNode{
quantity: 5,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(6, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*3, resource.DecimalSI),
},
}
crn3 := ClusterResourceNode{
quantity: 4,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(5, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*8, resource.DecimalSI),
},
}
crn4 := ClusterResourceNode{
quantity: 3,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(8, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*3, resource.DecimalSI),
},
}
crn5 := ClusterResourceNode{
quantity: 2,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*6, resource.DecimalSI),
},
}
crn6 := ClusterResourceNode{
quantity: 1,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(2, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*12, resource.DecimalSI),
},
}
mylist := list.New()
mylist.PushBack(crn5)
mylist.PushBack(crn1)
mylist.PushBack(crn6)
mylist.PushBack(crn3)
mylist.PushBack(crn2)
mylist.PushBack(crn4)
rbt := rs.llConvertToRbt(mylist)
fmt.Println(rbt)
if actualValue := rbt.Size(); actualValue != 6 {
t.Errorf("Got %v expected %v", actualValue, 6)
}
actualValue := rbt.GetNode(crn5)
node := actualValue.Key.(ClusterResourceNode)
if quantity := node.quantity; quantity != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
}
actualValue = rbt.GetNode(crn6)
node = actualValue.Key.(ClusterResourceNode)
if quantity := node.quantity; quantity != 1 {
t.Errorf("Got %v expected %v", actualValue, 1)
}
actualValue = rbt.GetNode(crn1)
node = actualValue.Key.(ClusterResourceNode)
if quantity := node.quantity; quantity != 6 {
t.Errorf("Got %v expected %v", actualValue, 6)
}
}
func TestRbtConvertToLl(t *testing.T) {
rms := []clusterapis.ResourceModel{
{
Grade: 0,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1024, resource.DecimalSI),
},
},
},
{
Grade: 1,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(1, resource.DecimalSI),
Max: *resource.NewQuantity(2, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(1024, resource.DecimalSI),
Max: *resource.NewQuantity(1024*2, resource.DecimalSI),
},
},
},
}
rs, err := InitSummary(rms)
if err != nil {
t.Errorf("Got %v expected %v", err, nil)
}
tree := redblacktree.NewWith(rs.clusterResourceNodeComparator)
if actualValue := tree.Size(); actualValue != 0 {
t.Errorf("Got %v expected %v", actualValue, 0)
}
if actualValue := tree.GetNode(2).Size(); actualValue != 0 {
t.Errorf("Got %v expected %v", actualValue, 0)
}
}
func TestAddToResourceSummary(t *testing.T) {
rms := []clusterapis.ResourceModel{
{
Grade: 0,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(0, resource.DecimalSI),
Max: *resource.NewQuantity(1024, resource.DecimalSI),
},
},
},
{
Grade: 1,
Ranges: []clusterapis.ResourceModelRange{
{
Name: corev1.ResourceCPU,
Min: *resource.NewMilliQuantity(1, resource.DecimalSI),
Max: *resource.NewQuantity(2, resource.DecimalSI),
},
{
Name: corev1.ResourceMemory,
Min: *resource.NewMilliQuantity(1024, resource.DecimalSI),
Max: *resource.NewQuantity(1024*2, resource.DecimalSI),
},
},
},
}
rs, err := InitSummary(rms)
if actualValue := len(rs.RMs); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if err != nil {
t.Errorf("Got %v expected %v", err, nil)
}
crn1 := ClusterResourceNode{
quantity: 3,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(8, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*3, resource.DecimalSI),
},
}
crn2 := ClusterResourceNode{
quantity: 1,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*6, resource.DecimalSI),
},
}
crn3 := ClusterResourceNode{
quantity: 2,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(1024*6, resource.DecimalSI),
},
}
rs.AddToResourceSummary(crn1)
rs.AddToResourceSummary(crn2)
rs.AddToResourceSummary(crn3)
for index, v := range rs.RMs {
num := rs.GetNodeNumFromModel(&rs.RMs[index])
if index == 0 && num != 0 {
t.Errorf("Got %v expected %v", num, 0)
}
if index == 1 && num != 2 {
t.Errorf("Got %v expected %v", num, 2)
}
if index == 0 && v.Quantity != 0 {
t.Errorf("Got %v expected %v", v.Quantity, 0)
}
if index == 1 && v.Quantity != 6 {
t.Errorf("Got %v expected %v", v.Quantity, 6)
}
}
crn4 := ClusterResourceNode{
quantity: 2,
resourceList: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(0, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(19, resource.DecimalSI),
},
}
rs.AddToResourceSummary(crn4)
if actualValue := rs.RMs[0]; actualValue.Quantity != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue := rs.RMs[0]; rs.GetNodeNumFromModel(&actualValue) != 1 {
t.Errorf("Got %v expected %v", actualValue, 1)
}
}