mirror of https://github.com/k3s-io/k3s
Merge pull request #45543 from sttts/sttts-external-roundtrip
Automatic merge from submit-queue (batch tested with PRs 45382, 45384, 44781, 45333, 45543) Do roundtrip testing with external kinds in client-go TPR example This tests that our serialization machinery works for TPR types, i.e. without internal counterpart and without generated code. /cc @nileboxpull/6/head
commit
aba95a169b
|
@ -38,6 +38,7 @@ go_library(
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
|
|
|
@ -36,6 +36,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
)
|
)
|
||||||
|
@ -125,24 +126,28 @@ func roundTripTypes(t *testing.T, scheme *runtime.Scheme, codecFactory runtimese
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RoundTripSpecificKindWithoutProtobuf(t *testing.T, internalGVK schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
|
func RoundTripSpecificKindWithoutProtobuf(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
|
||||||
roundTripSpecificKind(t, internalGVK, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true)
|
roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RoundTripSpecificKind(t *testing.T, internalGVK schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
|
func RoundTripSpecificKind(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
|
||||||
roundTripSpecificKind(t, internalGVK, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, false)
|
roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func roundTripSpecificKind(t *testing.T, internalGVK schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool, skipProtobuf bool) {
|
func roundTripSpecificKind(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool, skipProtobuf bool) {
|
||||||
if nonRoundTrippableTypes[internalGVK] {
|
if nonRoundTrippableTypes[gvk] {
|
||||||
t.Logf("skipping %v", internalGVK)
|
t.Logf("skipping %v", gvk)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Logf("round tripping %v", internalGVK)
|
t.Logf("round tripping %v", gvk)
|
||||||
|
|
||||||
// Try a few times, since runTest uses random values.
|
// Try a few times, since runTest uses random values.
|
||||||
for i := 0; i < *FuzzIters; i++ {
|
for i := 0; i < *FuzzIters; i++ {
|
||||||
roundTripToAllExternalVersions(t, scheme, codecFactory, fuzzer, internalGVK, nonRoundTrippableTypes, skipProtobuf)
|
if gvk.Version == runtime.APIVersionInternal {
|
||||||
|
roundTripToAllExternalVersions(t, scheme, codecFactory, fuzzer, gvk, nonRoundTrippableTypes, skipProtobuf)
|
||||||
|
} else {
|
||||||
|
roundTripOfExternalType(t, scheme, codecFactory, fuzzer, gvk, skipProtobuf)
|
||||||
|
}
|
||||||
if t.Failed() {
|
if t.Failed() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -209,10 +214,43 @@ func roundTripToAllExternalVersions(t *testing.T, scheme *runtime.Scheme, codecF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func roundTripOfExternalType(t *testing.T, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, externalGVK schema.GroupVersionKind, skipProtobuf bool) {
|
||||||
|
object, err := scheme.New(externalGVK)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Couldn't make a %v? %v", externalGVK, err)
|
||||||
|
}
|
||||||
|
typeAcc, err := meta.TypeAccessor(object)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableInternalTypes: %v", externalGVK, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fuzzInternalObject(t, fuzzer, object)
|
||||||
|
|
||||||
|
externalGoType := reflect.TypeOf(object).PkgPath()
|
||||||
|
t.Logf("\tround tripping external type %v %v", externalGVK, externalGoType)
|
||||||
|
|
||||||
|
typeAcc.SetKind(externalGVK.Kind)
|
||||||
|
typeAcc.SetAPIVersion(externalGVK.GroupVersion().String())
|
||||||
|
|
||||||
|
roundTrip(t, scheme, json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false), object)
|
||||||
|
|
||||||
|
// TODO remove this hack after we're past the intermediate steps
|
||||||
|
if !skipProtobuf {
|
||||||
|
roundTrip(t, scheme, protobuf.NewSerializer(scheme, scheme, "application/protobuf"), object)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// roundTrip applies a single round-trip test to the given runtime object
|
// roundTrip applies a single round-trip test to the given runtime object
|
||||||
// using the given codec. The round-trip test ensures that an object can be
|
// using the given codec. The round-trip test ensures that an object can be
|
||||||
// deep-copied and converted from internal -> versioned -> internal without
|
// deep-copied, converted, marshaled and back without loss of data.
|
||||||
// loss of data.
|
//
|
||||||
|
// For internal types this means
|
||||||
|
//
|
||||||
|
// internal -> external -> json/protobuf -> external -> internal.
|
||||||
|
//
|
||||||
|
// For external types this means
|
||||||
|
//
|
||||||
|
// external -> json/protobuf -> external.
|
||||||
func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object runtime.Object) {
|
func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object runtime.Object) {
|
||||||
printer := spew.ConfigState{DisableMethods: true}
|
printer := spew.ConfigState{DisableMethods: true}
|
||||||
original := object
|
original := object
|
||||||
|
|
|
@ -122,6 +122,10 @@
|
||||||
"ImportPath": "github.com/golang/groupcache/lru",
|
"ImportPath": "github.com/golang/groupcache/lru",
|
||||||
"Rev": "02826c3e79038b59d737d3b1c0a1d937f71a4433"
|
"Rev": "02826c3e79038b59d737d3b1c0a1d937f71a4433"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/golang/protobuf/proto",
|
||||||
|
"Rev": "4bd1920723d7b7c925de087aa32e2187708897f7"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/gofuzz",
|
"ImportPath": "github.com/google/gofuzz",
|
||||||
"Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c"
|
"Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c"
|
||||||
|
@ -286,6 +290,10 @@
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
|
||||||
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery",
|
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
|
|
@ -14,8 +14,11 @@ go_test(
|
||||||
library = ":go_default_library",
|
library = ":go_default_library",
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,15 @@ limitations under the License.
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/gofuzz"
|
||||||
|
|
||||||
|
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ runtime.Object = &Example{}
|
var _ runtime.Object = &Example{}
|
||||||
|
@ -26,3 +33,31 @@ var _ metav1.ObjectMetaAccessor = &Example{}
|
||||||
|
|
||||||
var _ runtime.Object = &ExampleList{}
|
var _ runtime.Object = &ExampleList{}
|
||||||
var _ metav1.ListMetaAccessor = &ExampleList{}
|
var _ metav1.ListMetaAccessor = &ExampleList{}
|
||||||
|
|
||||||
|
func exampleFuzzerFuncs(t apitesting.TestingCommon) []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
func(obj *ExampleList, c fuzz.Continue) {
|
||||||
|
c.FuzzNoCustom(obj)
|
||||||
|
obj.Items = make([]Example, c.Intn(10))
|
||||||
|
for i := range obj.Items {
|
||||||
|
c.Fuzz(&obj.Items[i])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestRoundTrip tests that the third-party kinds can be marshaled and unmarshaled correctly to/from JSON
|
||||||
|
// without the loss of information. Moreover, deep copy is tested.
|
||||||
|
func TestRoundTrip(t *testing.T) {
|
||||||
|
scheme := runtime.NewScheme()
|
||||||
|
codecs := serializer.NewCodecFactory(scheme)
|
||||||
|
|
||||||
|
AddToScheme(scheme)
|
||||||
|
|
||||||
|
seed := rand.Int63()
|
||||||
|
fuzzerFuncs := apitesting.MergeFuzzerFuncs(t, apitesting.GenericFuzzerFuncs(t, codecs), exampleFuzzerFuncs(t))
|
||||||
|
fuzzer := apitesting.FuzzerFor(fuzzerFuncs, rand.NewSource(seed))
|
||||||
|
|
||||||
|
apitesting.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("Example"), scheme, codecs, fuzzer, nil)
|
||||||
|
apitesting.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("ExampleList"), scheme, codecs, fuzzer, nil)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue