[ut]] add ut for resource.go

Signed-off-by: yingjinhui <yingjinhui@didiglobal.com>
This commit is contained in:
yingjinhui 2022-10-28 21:25:01 +08:00
parent dc8e5d20fe
commit 8e0ceb72ec
2 changed files with 594 additions and 28 deletions

View File

@ -20,7 +20,7 @@ type Resource struct {
ScalarResources map[corev1.ResourceName]int64
}
// EmptyResource creates a empty resource object and returns.
// EmptyResource creates an empty resource object and returns.
func EmptyResource() *Resource {
return &Resource{}
}
@ -58,6 +58,10 @@ func (r *Resource) Add(rl corev1.ResourceList) {
// SubResource is used to subtract two resources, if r < rr, set r to zero.
func (r *Resource) SubResource(rr *Resource) *Resource {
if r == nil || rr == nil {
return r
}
r.MilliCPU = MaxInt64(r.MilliCPU-rr.MilliCPU, 0)
r.Memory = MaxInt64(r.Memory-rr.Memory, 0)
r.EphemeralStorage = MaxInt64(r.EphemeralStorage-rr.EphemeralStorage, 0)
@ -182,33 +186,6 @@ func (r *Resource) MaxDivided(rl corev1.ResourceList) int64 {
return res
}
// LessEqual returns whether all dimensions of resources in r are less than or equal with that of rr.
func (r *Resource) LessEqual(rr *Resource) bool {
lessEqualFunc := func(l, r int64) bool {
return l <= r
}
if !lessEqualFunc(r.MilliCPU, rr.MilliCPU) {
return false
}
if !lessEqualFunc(r.Memory, rr.Memory) {
return false
}
if !lessEqualFunc(r.EphemeralStorage, rr.EphemeralStorage) {
return false
}
if !lessEqualFunc(r.AllowedPodNumber, rr.AllowedPodNumber) {
return false
}
for rrName, rrQuant := range rr.ScalarResources {
rQuant := r.ScalarResources[rrName]
if !lessEqualFunc(rQuant, rrQuant) {
return false
}
}
return true
}
// AddPodTemplateRequest add the effective request resource of a pod template to the origin resource.
// If pod container limits are specified, but requests are not, default requests to limits.
// The code logic is almost the same as kubernetes.
@ -275,6 +252,10 @@ func (r *Resource) AddResourcePods(pods int64) {
// Clone returns a copy of this resource.
func (r *Resource) Clone() *Resource {
if r == nil {
return nil
}
res := &Resource{
MilliCPU: r.MilliCPU,
Memory: r.Memory,

View File

@ -21,12 +21,16 @@ func TestNewResource(t *testing.T) {
corev1.ResourceMemory: *resource.NewQuantity(5, resource.BinarySI),
corev1.ResourcePods: *resource.NewQuantity(5, resource.DecimalSI),
corev1.ResourceEphemeralStorage: *resource.NewQuantity(5, resource.BinarySI),
"test.karmada.io/foo": *resource.NewQuantity(5, resource.BinarySI),
},
want: &Resource{
MilliCPU: 5,
Memory: 5,
EphemeralStorage: 5,
AllowedPodNumber: 5,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 5,
},
},
},
}
@ -39,3 +43,584 @@ func TestNewResource(t *testing.T) {
})
}
}
func TestResource_SubResource(t *testing.T) {
type args struct {
r *Resource
rr *Resource
}
tests := []struct {
name string
args args
want *Resource
}{
{
name: "r is nil",
args: args{
r: nil,
rr: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
"test.karmada.io/bar": 10,
},
},
},
want: nil,
},
{
name: "rr is nil",
args: args{
r: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
"test.karmada.io/bar": 10,
},
},
rr: nil,
},
want: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
"test.karmada.io/bar": 10,
},
},
},
{
name: "MilliCPU is not enough",
args: args{
r: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
"test.karmada.io/bar": 10,
},
},
rr: &Resource{
MilliCPU: 99999,
Memory: 6,
EphemeralStorage: 6,
AllowedPodNumber: 6,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 6,
"test.karmada.io/bar": 6,
},
},
},
want: &Resource{
MilliCPU: 0,
Memory: 4,
EphemeralStorage: 4,
AllowedPodNumber: 4,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 4,
"test.karmada.io/bar": 4,
},
},
},
{
name: "Memory is not enough",
args: args{
r: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
"test.karmada.io/bar": 10,
},
},
rr: &Resource{
MilliCPU: 6,
Memory: 99999,
EphemeralStorage: 6,
AllowedPodNumber: 6,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 6,
"test.karmada.io/bar": 6,
},
},
},
want: &Resource{
MilliCPU: 4,
Memory: 0,
EphemeralStorage: 4,
AllowedPodNumber: 4,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 4,
"test.karmada.io/bar": 4,
},
},
},
{
name: "EphemeralStorage is not enough",
args: args{
r: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
"test.karmada.io/bar": 10,
},
},
rr: &Resource{
MilliCPU: 6,
Memory: 6,
EphemeralStorage: 99999,
AllowedPodNumber: 6,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 6,
"test.karmada.io/bar": 6,
},
},
},
want: &Resource{
MilliCPU: 4,
Memory: 4,
EphemeralStorage: 0,
AllowedPodNumber: 4,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 4,
"test.karmada.io/bar": 4,
},
},
},
{
name: "AllowedPodNumber is not enough",
args: args{
r: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
"test.karmada.io/bar": 10,
},
},
rr: &Resource{
MilliCPU: 6,
Memory: 6,
EphemeralStorage: 6,
AllowedPodNumber: 99999,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 6,
"test.karmada.io/bar": 6,
},
},
},
want: &Resource{
MilliCPU: 4,
Memory: 4,
EphemeralStorage: 4,
AllowedPodNumber: 0,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 4,
"test.karmada.io/bar": 4,
},
},
},
{
name: "ScalarResources foo is not enough",
args: args{
r: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
"test.karmada.io/bar": 10,
},
},
rr: &Resource{
MilliCPU: 6,
Memory: 6,
EphemeralStorage: 6,
AllowedPodNumber: 6,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 9999,
"test.karmada.io/bar": 6,
},
},
},
want: &Resource{
MilliCPU: 4,
Memory: 4,
EphemeralStorage: 4,
AllowedPodNumber: 4,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 0,
"test.karmada.io/bar": 4,
},
},
},
{
name: "ScalarResources bar is not enough",
args: args{
r: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
"test.karmada.io/bar": 10,
},
},
rr: &Resource{
MilliCPU: 6,
Memory: 6,
EphemeralStorage: 6,
AllowedPodNumber: 6,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 6,
"test.karmada.io/bar": 9999,
},
},
},
want: &Resource{
MilliCPU: 4,
Memory: 4,
EphemeralStorage: 4,
AllowedPodNumber: 4,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 4,
"test.karmada.io/bar": 0,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.args.r.SubResource(tt.args.rr); !reflect.DeepEqual(got, tt.want) {
t.Errorf("got = %v, want = %v", tt.args.r, tt.want)
}
})
}
}
func TestResource_SetMaxResource(t *testing.T) {
type args struct {
r *Resource
rl corev1.ResourceList
}
tests := []struct {
name string
args args
want *Resource
}{
{
name: "r is nil",
args: args{
r: nil,
rl: map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: *resource.NewMilliQuantity(5, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(5, resource.BinarySI),
corev1.ResourcePods: *resource.NewQuantity(5, resource.DecimalSI),
corev1.ResourceEphemeralStorage: *resource.NewQuantity(5, resource.BinarySI),
"test.karmada.io/foo": *resource.NewQuantity(5, resource.BinarySI),
},
},
want: nil,
},
{
name: "r is max",
args: args{
r: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
},
},
rl: map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: *resource.NewMilliQuantity(5, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(5, resource.BinarySI),
corev1.ResourcePods: *resource.NewQuantity(5, resource.DecimalSI),
corev1.ResourceEphemeralStorage: *resource.NewQuantity(5, resource.BinarySI),
"test.karmada.io/foo": *resource.NewQuantity(5, resource.BinarySI),
},
},
want: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
},
},
},
{
name: "rl is max",
args: args{
r: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 10,
},
},
rl: map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: *resource.NewMilliQuantity(20, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(20, resource.BinarySI),
corev1.ResourcePods: *resource.NewQuantity(20, resource.DecimalSI),
corev1.ResourceEphemeralStorage: *resource.NewQuantity(20, resource.BinarySI),
"test.karmada.io/foo": *resource.NewQuantity(20, resource.BinarySI),
},
},
want: &Resource{
MilliCPU: 20,
Memory: 20,
EphemeralStorage: 20,
AllowedPodNumber: 20,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 20,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.args.r.SetMaxResource(tt.args.rl)
if !reflect.DeepEqual(tt.args.r, tt.want) {
t.Errorf("got %v, want %v", tt.args.r, tt.want)
}
})
}
}
func TestResource_ResourceList(t *testing.T) {
tests := []struct {
name string
resource *Resource
want corev1.ResourceList
}{
{
name: "resource is empty",
resource: EmptyResource(),
want: nil,
},
{
name: "resource list",
resource: &Resource{
MilliCPU: 10,
Memory: 10,
EphemeralStorage: 10,
AllowedPodNumber: 10,
ScalarResources: map[corev1.ResourceName]int64{
corev1.ResourceHugePagesPrefix + "foo": 10,
"test.karmada.io/bar": 10,
},
},
want: map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: *resource.NewMilliQuantity(10, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(10, resource.BinarySI),
corev1.ResourcePods: *resource.NewQuantity(10, resource.DecimalSI),
corev1.ResourceEphemeralStorage: *resource.NewQuantity(10, resource.BinarySI),
corev1.ResourceHugePagesPrefix + "foo": *resource.NewQuantity(10, resource.BinarySI),
"test.karmada.io/bar": *resource.NewQuantity(10, resource.DecimalSI),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.resource.ResourceList(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("ResourceList() = %v, want %v", got, tt.want)
}
})
}
}
func TestResource_MaxDivided(t *testing.T) {
type args struct {
r *Resource
rl corev1.ResourceList
}
tests := []struct {
name string
args args
want int64
}{
{
name: "MaxDivided",
args: args{
r: &Resource{
MilliCPU: 100,
Memory: 100,
EphemeralStorage: 100,
AllowedPodNumber: 100,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 100,
},
},
rl: map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: *resource.NewMilliQuantity(10, resource.DecimalSI), // 10
corev1.ResourceMemory: *resource.NewQuantity(5, resource.BinarySI), // 20
corev1.ResourcePods: *resource.NewQuantity(20, resource.DecimalSI), // 4
corev1.ResourceEphemeralStorage: *resource.NewQuantity(15, resource.BinarySI), // 6
"test.karmada.io/foo": *resource.NewQuantity(18, resource.DecimalSI), // 5
},
},
want: 5,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.args.r.MaxDivided(tt.args.rl); got != tt.want {
t.Errorf("MaxDivided() = %v, want %v", got, tt.want)
}
})
}
}
func TestResource_AddPodTemplateRequest(t *testing.T) {
type args struct {
podSpec *corev1.PodSpec
}
tests := []struct {
name string
args args
want *Resource
}{
{
name: "",
args: args{
podSpec: &corev1.PodSpec{
Containers: []corev1.Container{
{
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(10, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(10, resource.BinarySI),
"test.karmada.io/foo": *resource.NewQuantity(10, resource.DecimalSI),
"test.karmada.io/bar": *resource.NewQuantity(10, resource.DecimalSI),
},
Limits: corev1.ResourceList{
corev1.ResourceMemory: *resource.NewQuantity(99999, resource.BinarySI),
corev1.ResourcePods: *resource.NewQuantity(10, resource.DecimalSI),
"test.karmada.io/bar": *resource.NewQuantity(99999, resource.DecimalSI),
"test.karmada.io/baz": *resource.NewQuantity(10, resource.DecimalSI),
},
},
},
},
InitContainers: []corev1.Container{
{
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceCPU: *resource.NewMilliQuantity(5, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(10, resource.BinarySI),
"test.karmada.io/foo": *resource.NewQuantity(5, resource.DecimalSI),
"test.karmada.io/bar": *resource.NewQuantity(10, resource.DecimalSI),
},
Limits: corev1.ResourceList{
corev1.ResourceMemory: *resource.NewQuantity(99999, resource.BinarySI),
corev1.ResourcePods: *resource.NewQuantity(20, resource.DecimalSI),
"test.karmada.io/bar": *resource.NewQuantity(99999, resource.DecimalSI),
"test.karmada.io/baz": *resource.NewQuantity(20, resource.DecimalSI),
},
},
},
},
Overhead: map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: *resource.NewMilliQuantity(5, resource.DecimalSI),
corev1.ResourceMemory: *resource.NewQuantity(5, resource.BinarySI),
corev1.ResourceEphemeralStorage: *resource.NewQuantity(5, resource.BinarySI),
corev1.ResourcePods: *resource.NewQuantity(5, resource.DecimalSI),
"test.karmada.io/foo": *resource.NewQuantity(5, resource.DecimalSI),
"test.karmada.io/bar": *resource.NewQuantity(5, resource.DecimalSI),
"test.karmada.io/baz": *resource.NewQuantity(5, resource.DecimalSI),
},
},
},
want: &Resource{
MilliCPU: 15,
Memory: 15,
EphemeralStorage: 5,
AllowedPodNumber: 25,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 15,
"test.karmada.io/bar": 15,
"test.karmada.io/baz": 25,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := EmptyResource()
if got := r.AddPodTemplateRequest(tt.args.podSpec); !reflect.DeepEqual(got, tt.want) {
t.Errorf("AddPodTemplateRequest() = %v, want %v", got, tt.want)
}
})
}
}
func TestResource_Clone(t *testing.T) {
tests := []struct {
name string
caller *Resource
want *Resource
}{
{
name: "caller is nil",
caller: nil,
want: nil,
},
{
name: "clone",
caller: &Resource{
MilliCPU: 1,
Memory: 2,
EphemeralStorage: 3,
AllowedPodNumber: 4,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 5,
"test.karmada.io/bar": 6,
"test.karmada.io/baz": 7,
},
},
want: &Resource{
MilliCPU: 1,
Memory: 2,
EphemeralStorage: 3,
AllowedPodNumber: 4,
ScalarResources: map[corev1.ResourceName]int64{
"test.karmada.io/foo": 5,
"test.karmada.io/bar": 6,
"test.karmada.io/baz": 7,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.caller.Clone(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Clone() = %v, want %v", got, tt.want)
}
})
}
}