Merge pull request #1450 from XiShanYongYe-Chang/add-ut-for-quota
[UT] Add UT for FederatedResourceQuota validating
This commit is contained in:
commit
77e9d182b0
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
Copyright 2015 The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// This code is directly lifted from the Kubernetes codebase in order to avoid relying on the k8s.io/kubernetes package.
|
||||
// For reference:
|
||||
// https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers_test.go
|
||||
|
||||
package lifted
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func TestIsNativeResource(t *testing.T) {
|
||||
testCases := []struct {
|
||||
resourceName corev1.ResourceName
|
||||
expectVal bool
|
||||
}{
|
||||
{
|
||||
resourceName: "pod.alpha.kubernetes.io/opaque-int-resource-foo",
|
||||
expectVal: true,
|
||||
},
|
||||
{
|
||||
resourceName: "kubernetes.io/resource-foo",
|
||||
expectVal: true,
|
||||
},
|
||||
{
|
||||
resourceName: "foo",
|
||||
expectVal: true,
|
||||
},
|
||||
{
|
||||
resourceName: "a/b",
|
||||
expectVal: false,
|
||||
},
|
||||
{
|
||||
resourceName: "",
|
||||
expectVal: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("resourceName input=%s, expected value=%v", tc.resourceName, tc.expectVal), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
v := IsNativeResource(tc.resourceName)
|
||||
if v != tc.expectVal {
|
||||
t.Errorf("Got %v but expected %v", v, tc.expectVal)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsStandardResource(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
output bool
|
||||
}{
|
||||
{"cpu", true},
|
||||
{"memory", true},
|
||||
{"disk", false},
|
||||
{"blah", false},
|
||||
{"x.y.z", false},
|
||||
{"hugepages-2Mi", true},
|
||||
{"requests.hugepages-2Mi", true},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
if IsStandardResourceName(tc.input) != tc.output {
|
||||
t.Errorf("case[%d], input: %s, expected: %t, got: %t", i, tc.input, tc.output, !tc.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// This code is directly lifted from the Kubernetes codebase in order to avoid relying on the k8s.io/kubernetes package.
|
||||
// For reference:
|
||||
// https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/validation/validation_test.go#L15475-L15518
|
||||
|
||||
package lifted
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
func TestValidateResourceNames(t *testing.T) {
|
||||
table := []struct {
|
||||
input string
|
||||
success bool
|
||||
expect string
|
||||
}{
|
||||
{"memory", true, ""},
|
||||
{"cpu", true, ""},
|
||||
{"storage", true, ""},
|
||||
{"requests.cpu", true, ""},
|
||||
{"requests.memory", true, ""},
|
||||
{"requests.storage", true, ""},
|
||||
{"limits.cpu", true, ""},
|
||||
{"limits.memory", true, ""},
|
||||
{"network", false, ""},
|
||||
{"disk", false, ""},
|
||||
{"", false, ""},
|
||||
{".", false, ""},
|
||||
{"..", false, ""},
|
||||
{"my.favorite.app.co/12345", true, ""},
|
||||
{"my.favorite.app.co/_12345", false, ""},
|
||||
{"my.favorite.app.co/12345_", false, ""},
|
||||
{"kubernetes.io/..", false, ""},
|
||||
{"kubernetes.io/" + strings.Repeat("a", 63), true, ""},
|
||||
{"kubernetes.io/" + strings.Repeat("a", 64), false, ""},
|
||||
{"kubernetes.io//", false, ""},
|
||||
{"kubernetes.io", false, ""},
|
||||
{"kubernetes.io/will/not/work/", false, ""},
|
||||
}
|
||||
for k, item := range table {
|
||||
err := validateResourceName(item.input, field.NewPath("field"))
|
||||
if len(err) != 0 && item.success {
|
||||
t.Errorf("expected no failure for input %q", item.input)
|
||||
} else if len(err) == 0 && !item.success {
|
||||
t.Errorf("expected failure for input %q", item.input)
|
||||
for i := range err {
|
||||
detail := err[i].Detail
|
||||
if detail != "" && !strings.Contains(detail, item.expect) {
|
||||
t.Errorf("%d: expected error detail either empty or %s, got %s", k, item.expect, detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -91,7 +91,7 @@ func validateOverallAndAssignments(quotaSpec *policyv1alpha1.FederatedResourceQu
|
|||
for k, v := range quotaSpec.Overall {
|
||||
assignment := calculateAssignmentForResourceKey(k, quotaSpec.StaticAssignments)
|
||||
if v.Cmp(assignment) < 0 {
|
||||
errs = append(errs, field.Invalid(overallPath.Key(string(k)), v, "overall is less than assignments"))
|
||||
errs = append(errs, field.Invalid(overallPath.Key(string(k)), v.String(), "overall is less than assignments"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,158 @@
|
|||
package federatedresourcequota
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
)
|
||||
|
||||
func Test_validateOverallAndAssignments(t *testing.T) {
|
||||
specFld := field.NewPath("spec")
|
||||
cpuParse := resource.MustParse("10")
|
||||
memoryParse := resource.MustParse("10Gi")
|
||||
|
||||
type args struct {
|
||||
quotaSpec *policyv1alpha1.FederatedResourceQuotaSpec
|
||||
fld *field.Path
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want field.ErrorList
|
||||
}{
|
||||
{
|
||||
"normal",
|
||||
args{
|
||||
quotaSpec: &policyv1alpha1.FederatedResourceQuotaSpec{
|
||||
Overall: corev1.ResourceList{
|
||||
"cpu": cpuParse,
|
||||
"memory": memoryParse,
|
||||
},
|
||||
StaticAssignments: []policyv1alpha1.StaticClusterAssignment{
|
||||
{
|
||||
ClusterName: "m1",
|
||||
Hard: corev1.ResourceList{
|
||||
"cpu": resource.MustParse("1"),
|
||||
"memory": resource.MustParse("1Gi"),
|
||||
},
|
||||
},
|
||||
{
|
||||
ClusterName: "m2",
|
||||
Hard: corev1.ResourceList{
|
||||
"cpu": resource.MustParse("1.5"),
|
||||
"memory": resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
fld: specFld,
|
||||
},
|
||||
field.ErrorList{},
|
||||
},
|
||||
{
|
||||
"overall[cpu] is less than assignments",
|
||||
args{
|
||||
quotaSpec: &policyv1alpha1.FederatedResourceQuotaSpec{
|
||||
Overall: corev1.ResourceList{
|
||||
"cpu": cpuParse,
|
||||
"memory": memoryParse,
|
||||
},
|
||||
StaticAssignments: []policyv1alpha1.StaticClusterAssignment{
|
||||
{
|
||||
ClusterName: "m1",
|
||||
Hard: corev1.ResourceList{
|
||||
"cpu": resource.MustParse("1"),
|
||||
"memory": resource.MustParse("1Gi"),
|
||||
},
|
||||
},
|
||||
{
|
||||
ClusterName: "m2",
|
||||
Hard: corev1.ResourceList{
|
||||
"cpu": resource.MustParse("10"),
|
||||
"memory": resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
fld: specFld,
|
||||
},
|
||||
field.ErrorList{
|
||||
field.Invalid(specFld.Child("overall").Key("cpu"), cpuParse.String(), "overall is less than assignments"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"overall[memory] is less than assignments",
|
||||
args{
|
||||
quotaSpec: &policyv1alpha1.FederatedResourceQuotaSpec{
|
||||
Overall: corev1.ResourceList{
|
||||
"cpu": cpuParse,
|
||||
"memory": memoryParse,
|
||||
},
|
||||
StaticAssignments: []policyv1alpha1.StaticClusterAssignment{
|
||||
{
|
||||
ClusterName: "m1",
|
||||
Hard: corev1.ResourceList{
|
||||
"cpu": resource.MustParse("1"),
|
||||
"memory": resource.MustParse("1Gi"),
|
||||
},
|
||||
},
|
||||
{
|
||||
ClusterName: "m2",
|
||||
Hard: corev1.ResourceList{
|
||||
"cpu": resource.MustParse("1.5"),
|
||||
"memory": resource.MustParse("10Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
fld: specFld,
|
||||
},
|
||||
field.ErrorList{
|
||||
field.Invalid(specFld.Child("overall").Key("memory"), memoryParse.String(), "overall is less than assignments"),
|
||||
},
|
||||
},
|
||||
{
|
||||
"assignment resourceName is not exist in overall",
|
||||
args{
|
||||
quotaSpec: &policyv1alpha1.FederatedResourceQuotaSpec{
|
||||
Overall: corev1.ResourceList{
|
||||
"cpu": cpuParse,
|
||||
"memory": memoryParse,
|
||||
},
|
||||
StaticAssignments: []policyv1alpha1.StaticClusterAssignment{
|
||||
{
|
||||
ClusterName: "m1",
|
||||
Hard: corev1.ResourceList{
|
||||
"cpux": resource.MustParse("1"),
|
||||
"memory": resource.MustParse("1Gi"),
|
||||
},
|
||||
},
|
||||
{
|
||||
ClusterName: "m2",
|
||||
Hard: corev1.ResourceList{
|
||||
"cpu": resource.MustParse("1.5"),
|
||||
"memory": resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
fld: specFld,
|
||||
},
|
||||
field.ErrorList{
|
||||
field.Invalid(specFld.Child("staticAssignments").Index(0).Child("hard").Key("cpux"), corev1.ResourceName("cpux"), "assignment resourceName is not exist in overall"),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := validateOverallAndAssignments(tt.args.quotaSpec, tt.args.fld); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("validateOverallAndAssignments() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue