mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
Make semantic deep equal public feature
* Use semantic deep equal when validating * More test cases for deep equal
This commit is contained in:
parent
7f49ba0dcf
commit
0d628b3bff
@ -18,6 +18,28 @@ package api
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
// Semantic can do semantic deep equality checks for api objects.
|
||||
// Example: api.Semantic.DeepEqual(aPod, aPodWithNonNilButEmptyMaps) == true
|
||||
var Semantic = conversion.EqualitiesOrDie(
|
||||
func(a, b resource.Quantity) bool {
|
||||
// Ignore formatting, only care that numeric value stayed the same.
|
||||
// TODO: if we decide it's important, after we drop v1beta1/2, we
|
||||
// could start comparing format.
|
||||
//
|
||||
// Uninitialized quantities are equivilent to 0 quantities.
|
||||
if a.Amount == nil && b.MilliValue() == 0 {
|
||||
return true
|
||||
}
|
||||
if b.Amount == nil && a.MilliValue() == 0 {
|
||||
return true
|
||||
}
|
||||
return a.Amount.Cmp(b.Amount) == 0
|
||||
},
|
||||
)
|
||||
|
||||
// TODO: Address these per #1502
|
||||
|
@ -30,7 +30,6 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
|
||||
@ -41,14 +40,6 @@ import (
|
||||
|
||||
var fuzzIters = flag.Int("fuzz_iters", 40, "How many fuzzing iterations to do.")
|
||||
|
||||
// apiObjectComparer can do semantic deep equality checks for api objects.
|
||||
var apiObjectComparer = conversion.EqualitiesOrDie(
|
||||
func(a, b resource.Quantity) bool {
|
||||
// Ignore formatting, only care that numeric value stayed the same.
|
||||
return a.Amount.Cmp(b.Amount) == 0
|
||||
},
|
||||
)
|
||||
|
||||
// apiObjectFuzzer can randomly populate api objects.
|
||||
var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
|
||||
func(j *runtime.PluginBase, c fuzz.Continue) {
|
||||
@ -181,7 +172,7 @@ func runTest(t *testing.T, codec runtime.Codec, source runtime.Object) {
|
||||
t.Errorf("0: %v: %v\nCodec: %v\nData: %s\nSource: %#v", name, err, codec, string(data), source)
|
||||
return
|
||||
}
|
||||
if !apiObjectComparer.DeepEqual(source, obj2) {
|
||||
if !api.Semantic.DeepEqual(source, obj2) {
|
||||
t.Errorf("1: %v: diff: %v\nCodec: %v\nData: %s\nSource: %#v", name, util.ObjectGoPrintDiff(source, obj2), codec, string(data), source)
|
||||
return
|
||||
}
|
||||
@ -192,7 +183,7 @@ func runTest(t *testing.T, codec runtime.Codec, source runtime.Object) {
|
||||
t.Errorf("2: %v: %v", name, err)
|
||||
return
|
||||
}
|
||||
if !apiObjectComparer.DeepEqual(source, obj3) {
|
||||
if !api.Semantic.DeepEqual(source, obj3) {
|
||||
t.Errorf("3: %v: diff: %v\nCodec: %v", name, util.ObjectDiff(source, obj3), codec)
|
||||
return
|
||||
}
|
||||
@ -266,7 +257,7 @@ func TestEncode_Ptr(t *testing.T) {
|
||||
if _, ok := obj2.(*api.Pod); !ok {
|
||||
t.Fatalf("Got wrong type")
|
||||
}
|
||||
if !apiObjectComparer.DeepEqual(obj2, pod) {
|
||||
if !api.Semantic.DeepEqual(obj2, pod) {
|
||||
t.Errorf("Expected:\n %#v,\n Got:\n %#v", &pod, obj2)
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
@ -429,7 +428,7 @@ func ValidatePodUpdate(newPod, oldPod *api.Pod) errs.ValidationErrorList {
|
||||
newContainers = append(newContainers, container)
|
||||
}
|
||||
pod.Spec.Containers = newContainers
|
||||
if !reflect.DeepEqual(pod.Spec, oldPod.Spec) {
|
||||
if !api.Semantic.DeepEqual(pod.Spec, oldPod.Spec) {
|
||||
// TODO: a better error would include all immutable fields explicitly.
|
||||
allErrs = append(allErrs, errs.NewFieldInvalid("spec.containers", newPod.Spec.Containers, "some fields are immutable"))
|
||||
}
|
||||
@ -586,7 +585,7 @@ func ValidateMinion(minion *api.Node) errs.ValidationErrorList {
|
||||
func ValidateMinionUpdate(oldMinion *api.Node, minion *api.Node) errs.ValidationErrorList {
|
||||
allErrs := errs.ValidationErrorList{}
|
||||
|
||||
if !reflect.DeepEqual(minion.Status, api.NodeStatus{}) {
|
||||
if !api.Semantic.DeepEqual(minion.Status, api.NodeStatus{}) {
|
||||
allErrs = append(allErrs, errs.NewFieldInvalid("status", minion.Status, "status must be empty"))
|
||||
}
|
||||
|
||||
@ -596,7 +595,7 @@ func ValidateMinionUpdate(oldMinion *api.Node, minion *api.Node) errs.Validation
|
||||
// Clear status
|
||||
oldMinion.Status = minion.Status
|
||||
|
||||
if !reflect.DeepEqual(oldMinion, minion) {
|
||||
if !api.Semantic.DeepEqual(oldMinion, minion) {
|
||||
glog.V(4).Infof("Update failed validation %#v vs %#v", oldMinion, minion)
|
||||
allErrs = append(allErrs, fmt.Errorf("update contains more than labels or capacity changes"))
|
||||
}
|
||||
|
@ -22,15 +22,28 @@ import (
|
||||
|
||||
func TestEqualities(t *testing.T) {
|
||||
e := Equalities{}
|
||||
type Bar struct {
|
||||
X int
|
||||
}
|
||||
type Baz struct {
|
||||
Y Bar
|
||||
}
|
||||
err := e.AddFuncs(
|
||||
func(a, b int) bool {
|
||||
return a+1 == b
|
||||
},
|
||||
func(a, b Bar) bool {
|
||||
return a.X*10 == b.X
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected: %v", err)
|
||||
}
|
||||
|
||||
type Foo struct {
|
||||
X int
|
||||
}
|
||||
|
||||
table := []struct {
|
||||
a, b interface{}
|
||||
equal bool
|
||||
@ -38,6 +51,10 @@ func TestEqualities(t *testing.T) {
|
||||
{1, 2, true},
|
||||
{2, 1, false},
|
||||
{"foo", "foo", true},
|
||||
{Foo{1}, Foo{2}, true},
|
||||
{Bar{1}, Bar{10}, true},
|
||||
{&Bar{1}, &Bar{10}, true},
|
||||
{Baz{Bar{1}}, Baz{Bar{10}}, true},
|
||||
{map[string]int{"foo": 1}, map[string]int{"foo": 2}, true},
|
||||
{map[string]int{}, map[string]int(nil), true},
|
||||
{[]int{}, []int(nil), true},
|
||||
|
Loading…
Reference in New Issue
Block a user